diff --git a/.buildkite/ftr_configs.yml b/.buildkite/ftr_configs.yml index ebaeb6c3692b7..f16b0e46ada95 100644 --- a/.buildkite/ftr_configs.yml +++ b/.buildkite/ftr_configs.yml @@ -129,6 +129,7 @@ enabled: - x-pack/test/banners_functional/config.ts - x-pack/test/cases_api_integration/security_and_spaces/config_basic.ts - x-pack/test/cases_api_integration/security_and_spaces/config_trial.ts + - x-pack/test/cases_api_integration/security_and_spaces/config_no_public_base_url.ts - x-pack/test/cases_api_integration/spaces_only/config.ts - x-pack/test/detection_engine_api_integration/basic/config.ts - x-pack/test/detection_engine_api_integration/security_and_spaces/group1/config.ts diff --git a/.eslintrc.js b/.eslintrc.js index 0e43c15cca13e..5341c63e52e36 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1111,7 +1111,10 @@ module.exports = { }, overrides: [ { - files: ['x-pack/plugins/security_solution/**/*.{js,mjs,ts,tsx}'], + files: [ + 'x-pack/plugins/security_solution/**/*.{js,mjs,ts,tsx}', + 'x-pack/plugins/cases/public/**/*.{js,mjs,ts,tsx}', + ], rules: { '@typescript-eslint/consistent-type-imports': 'error', }, diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 17e8a0f1b4d4b..e19165cf4faa1 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -864,6 +864,7 @@ packages/kbn-babel-plugin-synthetic-packages @elastic/kibana-operations packages/kbn-babel-preset @elastic/kibana-operations packages/kbn-bazel-packages @elastic/kibana-operations packages/kbn-bazel-runner @elastic/kibana-operations +packages/kbn-cases-components @elastic/response-ops packages/kbn-chart-icons @elastic/kibana-vis-editors packages/kbn-ci-stats-core @elastic/kibana-operations packages/kbn-ci-stats-performance-metrics @elastic/kibana-operations diff --git a/.i18nrc.json b/.i18nrc.json index 462daff20de63..5f0d6b1d2e30a 100644 --- a/.i18nrc.json +++ b/.i18nrc.json @@ -5,6 +5,7 @@ "apmOss": "src/plugins/apm_oss", "autocomplete": "packages/kbn-securitysolution-autocomplete/src", "bfetch": "src/plugins/bfetch", + "cases": ["packages/kbn-cases-components"], "charts": "src/plugins/charts", "console": "src/plugins/console", "contentManagement": "packages/content-management", diff --git a/api_docs/actions.mdx b/api_docs/actions.mdx index 2bab1ac914cb6..a99d47ae21095 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-10 +date: 2022-10-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'actions'] --- import actionsObj from './actions.devdocs.json'; diff --git a/api_docs/advanced_settings.mdx b/api_docs/advanced_settings.mdx index 10139c992c0d1..2521e6f0a08ed 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-10 +date: 2022-10-16 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 f9ea9de800a28..742f14ce17fcf 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-10 +date: 2022-10-16 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 cf275b4f7fda8..4c8345c2bc602 100644 --- a/api_docs/alerting.devdocs.json +++ b/api_docs/alerting.devdocs.json @@ -2832,9 +2832,9 @@ }, ">; getGlobalExecutionKpiWithAuth: ({ dateStart, dateEnd, filter, }: ", "GetGlobalExecutionKPIParams", - ") => Promise<{ success: number; unknown: number; failure: number; activeAlerts: number; newAlerts: number; recoveredAlerts: number; erroredActions: number; triggeredActions: number; }>; getRuleExecutionKPI: ({ id, dateStart, dateEnd, filter }: ", + ") => Promise<{ success: number; unknown: number; failure: number; warning: number; activeAlerts: number; newAlerts: number; recoveredAlerts: number; erroredActions: number; triggeredActions: number; }>; getRuleExecutionKPI: ({ id, dateStart, dateEnd, filter }: ", "GetRuleExecutionKPIParams", - ") => Promise<{ success: number; unknown: number; failure: number; activeAlerts: number; newAlerts: number; recoveredAlerts: number; erroredActions: number; triggeredActions: number; }>; bulkEdit: Promise<{ success: number; unknown: number; failure: number; warning: number; activeAlerts: number; newAlerts: number; recoveredAlerts: number; erroredActions: number; triggeredActions: number; }>; bulkEdit: ; }, ", "APMRouteCreateOptions", - ">; \"GET /internal/apm/services/{serviceName}/serviceNodes\": ", - "ServerRoute", - "<\"GET /internal/apm/services/{serviceName}/serviceNodes\", ", - "TypeC", - "<{ path: ", - "TypeC", - "<{ serviceName: ", - "StringC", - "; }>; query: ", - "IntersectionC", - "<[", - "TypeC", - "<{ kuery: ", - "StringC", - "; }>, ", - "TypeC", - "<{ start: ", - "Type", - "; end: ", - "Type", - "; }>, ", - "TypeC", - "<{ environment: ", - "UnionC", - "<[", - "LiteralC", - "<\"ENVIRONMENT_NOT_DEFINED\">, ", - "LiteralC", - "<\"ENVIRONMENT_ALL\">, ", - "BrandC", - "<", - "StringC", - ", ", - "NonEmptyStringBrand", - ">]>; }>]>; }>, ", - { - "pluginId": "apm", - "scope": "server", - "docId": "kibApmPluginApi", - "section": "def-server.APMRouteHandlerResources", - "text": "APMRouteHandlerResources" - }, - ", { serviceNodes: { name: string; cpu: number | null; heapMemory: number | null; hostName: string | null | undefined; nonHeapMemory: number | null; threadCount: number | null; }[]; }, ", - "APMRouteCreateOptions", ">; \"GET /internal/apm/service-map/dependency\": ", "ServerRoute", "<\"GET /internal/apm/service-map/dependency\", ", @@ -5029,6 +4985,50 @@ }, ", { serviceCount: number; transactionPerMinute: { value: undefined; timeseries: never[]; } | { value: number; timeseries: { x: number; y: number | null; }[]; }; }, ", "APMRouteCreateOptions", + ">; \"GET /internal/apm/services/{serviceName}/metrics/nodes\": ", + "ServerRoute", + "<\"GET /internal/apm/services/{serviceName}/metrics/nodes\", ", + "TypeC", + "<{ path: ", + "TypeC", + "<{ serviceName: ", + "StringC", + "; }>; query: ", + "IntersectionC", + "<[", + "TypeC", + "<{ kuery: ", + "StringC", + "; }>, ", + "TypeC", + "<{ start: ", + "Type", + "; end: ", + "Type", + "; }>, ", + "TypeC", + "<{ environment: ", + "UnionC", + "<[", + "LiteralC", + "<\"ENVIRONMENT_NOT_DEFINED\">, ", + "LiteralC", + "<\"ENVIRONMENT_ALL\">, ", + "BrandC", + "<", + "StringC", + ", ", + "NonEmptyStringBrand", + ">]>; }>]>; }>, ", + { + "pluginId": "apm", + "scope": "server", + "docId": "kibApmPluginApi", + "section": "def-server.APMRouteHandlerResources", + "text": "APMRouteHandlerResources" + }, + ", { serviceNodes: { name: string; cpu: number | null; heapMemory: number | null; hostName: string | null | undefined; nonHeapMemory: number | null; threadCount: number | null; }[]; }, ", + "APMRouteCreateOptions", ">; \"GET /internal/apm/services/{serviceName}/metrics/charts\": ", "ServerRoute", "<\"GET /internal/apm/services/{serviceName}/metrics/charts\", ", diff --git a/api_docs/apm.mdx b/api_docs/apm.mdx index c30a0992fd7f4..ad225d6a6f12b 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-10 +date: 2022-10-16 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 66bd7c7e641e1..e2a3e28365e36 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-10 +date: 2022-10-16 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 e8065146fd3d3..7652d52e2a4d8 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-10 +date: 2022-10-16 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 a98cfd8e0fd77..a1f78678f2806 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-10 +date: 2022-10-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'canvas'] --- import canvasObj from './canvas.devdocs.json'; diff --git a/api_docs/cases.devdocs.json b/api_docs/cases.devdocs.json index 5d2f51ee8d1b4..4119ccb5ec28f 100644 --- a/api_docs/cases.devdocs.json +++ b/api_docs/cases.devdocs.json @@ -779,13 +779,7 @@ "description": [], "signature": [ "{ getRelatedCases: (alertId: string, query: { owner?: string | string[] | undefined; }) => Promise<{ id: string; title: string; }[]>; cases: { find: (query: { tags?: string | string[] | undefined; status?: ", - { - "pluginId": "cases", - "scope": "common", - "docId": "kibCasesPluginApi", - "section": "def-common.CaseStatuses", - "text": "CaseStatuses" - }, + "CaseStatuses", " | undefined; severity?: ", "CaseSeverity", " | undefined; assignees?: string | string[] | undefined; reporters?: string | string[] | undefined; defaultSearchOperator?: \"AND\" | \"OR\" | undefined; fields?: string | string[] | undefined; from?: string | undefined; page?: number | undefined; perPage?: number | undefined; search?: string | undefined; searchFields?: string | string[] | undefined; sortField?: string | undefined; sortOrder?: \"asc\" | \"desc\" | undefined; to?: string | undefined; owner?: string | string[] | undefined; }, signal?: AbortSignal | undefined) => Promise<", @@ -1475,7 +1469,10 @@ "tags": [], "label": "CaseStatuses", "description": [], - "path": "x-pack/plugins/cases/common/api/cases/status.ts", + "signature": [ + "CaseStatuses" + ], + "path": "node_modules/@types/kbn__cases-components/index.d.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -1515,13 +1512,7 @@ "description": [], "signature": [ "Omit<{ description: string; status: ", - { - "pluginId": "cases", - "scope": "common", - "docId": "kibCasesPluginApi", - "section": "def-common.CaseStatuses", - "text": "CaseStatuses" - }, + "CaseStatuses", "; tags: string[]; title: string; connector: { id: string; type: ", "ConnectorTypes", ".casesWebhook; fields: null; name: string; } | { id: string; type: ", diff --git a/api_docs/cases.mdx b/api_docs/cases.mdx index 99dd1bbe89355..f7dded33a64e0 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-10 +date: 2022-10-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cases'] --- import casesObj from './cases.devdocs.json'; @@ -21,7 +21,7 @@ Contact [ResponseOps](https://github.com/orgs/elastic/teams/response-ops) for qu | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 87 | 0 | 71 | 28 | +| 87 | 0 | 70 | 28 | ## Client diff --git a/api_docs/charts.mdx b/api_docs/charts.mdx index 0d6e5deb4ebb4..c6ac856a241a6 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-10 +date: 2022-10-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'charts'] --- import chartsObj from './charts.devdocs.json'; diff --git a/api_docs/cloud.mdx b/api_docs/cloud.mdx index 5ed1afbaec4d1..9a7bfc274ce25 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-10 +date: 2022-10-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloud'] --- import cloudObj from './cloud.devdocs.json'; diff --git a/api_docs/cloud_chat.mdx b/api_docs/cloud_chat.mdx index 154ea7db58498..5ddb69349bb95 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-10 +date: 2022-10-16 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 3f36edd65c5e7..7b97ace6641a8 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-10 +date: 2022-10-16 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 299993c715eb8..9b7a4d5aa8ea6 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-10 +date: 2022-10-16 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 61acddd4e8811..cebec6616fdb0 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-10 +date: 2022-10-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'console'] --- import consoleObj from './console.devdocs.json'; diff --git a/api_docs/controls.devdocs.json b/api_docs/controls.devdocs.json index 0a54b22525152..0768321579c9b 100644 --- a/api_docs/controls.devdocs.json +++ b/api_docs/controls.devdocs.json @@ -604,10 +604,26 @@ }, { "parentPluginId": "controls", - "id": "def-public.ControlGroupContainer.untilReady", + "id": "def-public.ControlGroupContainer.untilAllChildrenReady", "type": "Function", "tags": [], - "label": "untilReady", + "label": "untilAllChildrenReady", + "description": [], + "signature": [ + "() => Promise" + ], + "path": "src/plugins/controls/public/control_group/embeddable/control_group_container.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "controls", + "id": "def-public.ControlGroupContainer.untilInitialized", + "type": "Function", + "tags": [], + "label": "untilInitialized", "description": [], "signature": [ "() => Promise" diff --git a/api_docs/controls.mdx b/api_docs/controls.mdx index fd7bbc2f1dadf..adf5fdc18a17b 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-10 +date: 2022-10-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'controls'] --- import controlsObj from './controls.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 | |-------------------|-----------|------------------------|-----------------| -| 212 | 0 | 204 | 7 | +| 213 | 0 | 205 | 7 | ## Client diff --git a/api_docs/core.devdocs.json b/api_docs/core.devdocs.json index 197b485695674..6ef18a3a1a34a 100644 --- a/api_docs/core.devdocs.json +++ b/api_docs/core.devdocs.json @@ -520,6 +520,10 @@ "plugin": "dashboard", "path": "src/plugins/dashboard/public/services/analytics/analytics_service.ts" }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/services/fleet_usage_sender.ts" + }, { "plugin": "osquery", "path": "x-pack/plugins/osquery/server/lib/telemetry/sender.ts" @@ -978,6 +982,14 @@ "plugin": "@kbn/core-status-server-internal", "path": "packages/core/status/core-status-server-internal/src/status_service.ts" }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/analytics/analytics_service.test.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/analytics/analytics_service.test.ts" + }, { "plugin": "security", "path": "x-pack/plugins/security/public/analytics/register_user_context.test.ts" @@ -11082,18 +11094,6 @@ "plugin": "alerting", "path": "x-pack/plugins/alerting/server/saved_objects/geo_containment/migrations.ts" }, - { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/saved_objects/migrations.ts" - }, - { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/saved_objects/migrations.ts" - }, - { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/saved_objects/migrations.ts" - }, { "plugin": "alerting", "path": "x-pack/plugins/alerting/server/types.ts" @@ -11274,6 +11274,22 @@ "plugin": "ml", "path": "x-pack/plugins/ml/common/types/modules.ts" }, + { + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/saved_objects/migrations/7.11/index.ts" + }, + { + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/saved_objects/migrations/7.11/index.ts" + }, + { + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/saved_objects/migrations/7.15/index.ts" + }, + { + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/saved_objects/migrations/7.15/index.ts" + }, { "plugin": "dashboard", "path": "src/plugins/dashboard/public/services/dashboard_saved_object/lib/save_dashboard_state_to_saved_object.ts" @@ -19275,6 +19291,10 @@ "plugin": "dashboard", "path": "src/plugins/dashboard/public/services/analytics/analytics_service.ts" }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/server/services/fleet_usage_sender.ts" + }, { "plugin": "osquery", "path": "x-pack/plugins/osquery/server/lib/telemetry/sender.ts" @@ -19733,6 +19753,14 @@ "plugin": "@kbn/core-status-server-internal", "path": "packages/core/status/core-status-server-internal/src/status_service.ts" }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/analytics/analytics_service.test.ts" + }, + { + "plugin": "security", + "path": "x-pack/plugins/security/public/analytics/analytics_service.test.ts" + }, { "plugin": "security", "path": "x-pack/plugins/security/public/analytics/register_user_context.test.ts" @@ -24612,6 +24640,31 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "core", + "id": "def-server.ElasticsearchClientConfig.maxIdleSockets", + "type": "number", + "tags": [], + "label": "maxIdleSockets", + "description": [], + "path": "node_modules/@types/kbn__core-elasticsearch-server/index.d.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "core", + "id": "def-server.ElasticsearchClientConfig.idleSocketTimeout", + "type": "Object", + "tags": [], + "label": "idleSocketTimeout", + "description": [], + "signature": [ + "moment.Duration" + ], + "path": "node_modules/@types/kbn__core-elasticsearch-server/index.d.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "core", "id": "def-server.ElasticsearchClientConfig.compression", @@ -27363,7 +27416,9 @@ "TransportRequestOptions", " | undefined): Promise<", "UpdateResponse", - ">; }; [kInternal]: symbol | null; [kAsyncSearch]: symbol | null; [kAutoscaling]: symbol | null; [kCat]: symbol | null; [kCcr]: symbol | null; [kCluster]: symbol | null; [kDanglingIndices]: symbol | null; [kEnrich]: symbol | null; [kEql]: symbol | null; [kFeatures]: symbol | null; [kFleet]: symbol | null; [kGraph]: symbol | null; [kIlm]: symbol | null; [kIndices]: symbol | null; [kIngest]: symbol | null; [kLicense]: symbol | null; [kLogstash]: symbol | null; [kMigration]: symbol | null; [kMl]: symbol | null; [kMonitoring]: symbol | null; [kNodes]: symbol | null; [kRollup]: symbol | null; [kSearchableSnapshots]: symbol | null; [kSecurity]: symbol | null; [kShutdown]: symbol | null; [kSlm]: symbol | null; [kSnapshot]: symbol | null; [kSql]: symbol | null; [kSsl]: symbol | null; [kTasks]: symbol | null; [kTextStructure]: symbol | null; [kTransform]: symbol | null; [kWatcher]: symbol | null; [kXpack]: symbol | null; transport: ", + ">; }; asyncSearch: ", + "default", + "; [kInternal]: symbol | null; [kAsyncSearch]: symbol | null; [kAutoscaling]: symbol | null; [kCat]: symbol | null; [kCcr]: symbol | null; [kCluster]: symbol | null; [kDanglingIndices]: symbol | null; [kEnrich]: symbol | null; [kEql]: symbol | null; [kFeatures]: symbol | null; [kFleet]: symbol | null; [kGraph]: symbol | null; [kIlm]: symbol | null; [kIndices]: symbol | null; [kIngest]: symbol | null; [kLicense]: symbol | null; [kLogstash]: symbol | null; [kMigration]: symbol | null; [kMl]: symbol | null; [kMonitoring]: symbol | null; [kNodes]: symbol | null; [kRollup]: symbol | null; [kSearchableSnapshots]: symbol | null; [kSecurity]: symbol | null; [kShutdown]: symbol | null; [kSlm]: symbol | null; [kSnapshot]: symbol | null; [kSql]: symbol | null; [kSsl]: symbol | null; [kTasks]: symbol | null; [kTextStructure]: symbol | null; [kTransform]: symbol | null; [kWatcher]: symbol | null; [kXpack]: symbol | null; transport: ", "default", "; helpers: ", "default", @@ -27373,8 +27428,6 @@ "default", "; Internal: ", "default", - "; asyncSearch: ", - "default", "; autoscaling: ", "default", "; bulk: { (this: That, params: ", @@ -32536,7 +32589,9 @@ "TransportRequestOptions", " | undefined): Promise<", "UpdateResponse", - ">; }; [kInternal]: symbol | null; [kAsyncSearch]: symbol | null; [kAutoscaling]: symbol | null; [kCat]: symbol | null; [kCcr]: symbol | null; [kCluster]: symbol | null; [kDanglingIndices]: symbol | null; [kEnrich]: symbol | null; [kEql]: symbol | null; [kFeatures]: symbol | null; [kFleet]: symbol | null; [kGraph]: symbol | null; [kIlm]: symbol | null; [kIndices]: symbol | null; [kIngest]: symbol | null; [kLicense]: symbol | null; [kLogstash]: symbol | null; [kMigration]: symbol | null; [kMl]: symbol | null; [kMonitoring]: symbol | null; [kNodes]: symbol | null; [kRollup]: symbol | null; [kSearchableSnapshots]: symbol | null; [kSecurity]: symbol | null; [kShutdown]: symbol | null; [kSlm]: symbol | null; [kSnapshot]: symbol | null; [kSql]: symbol | null; [kSsl]: symbol | null; [kTasks]: symbol | null; [kTextStructure]: symbol | null; [kTransform]: symbol | null; [kWatcher]: symbol | null; [kXpack]: symbol | null; transport: ", + ">; }; asyncSearch: ", + "default", + "; [kInternal]: symbol | null; [kAsyncSearch]: symbol | null; [kAutoscaling]: symbol | null; [kCat]: symbol | null; [kCcr]: symbol | null; [kCluster]: symbol | null; [kDanglingIndices]: symbol | null; [kEnrich]: symbol | null; [kEql]: symbol | null; [kFeatures]: symbol | null; [kFleet]: symbol | null; [kGraph]: symbol | null; [kIlm]: symbol | null; [kIndices]: symbol | null; [kIngest]: symbol | null; [kLicense]: symbol | null; [kLogstash]: symbol | null; [kMigration]: symbol | null; [kMl]: symbol | null; [kMonitoring]: symbol | null; [kNodes]: symbol | null; [kRollup]: symbol | null; [kSearchableSnapshots]: symbol | null; [kSecurity]: symbol | null; [kShutdown]: symbol | null; [kSlm]: symbol | null; [kSnapshot]: symbol | null; [kSql]: symbol | null; [kSsl]: symbol | null; [kTasks]: symbol | null; [kTextStructure]: symbol | null; [kTransform]: symbol | null; [kWatcher]: symbol | null; [kXpack]: symbol | null; transport: ", "default", "; helpers: ", "default", @@ -32546,8 +32601,6 @@ "default", "; Internal: ", "default", - "; asyncSearch: ", - "default", "; autoscaling: ", "default", "; bulk: { (this: That, params: ", @@ -33740,7 +33793,9 @@ "TransportRequestOptions", " | undefined): Promise<", "UpdateResponse", - ">; }; [kInternal]: symbol | null; [kAsyncSearch]: symbol | null; [kAutoscaling]: symbol | null; [kCat]: symbol | null; [kCcr]: symbol | null; [kCluster]: symbol | null; [kDanglingIndices]: symbol | null; [kEnrich]: symbol | null; [kEql]: symbol | null; [kFeatures]: symbol | null; [kFleet]: symbol | null; [kGraph]: symbol | null; [kIlm]: symbol | null; [kIndices]: symbol | null; [kIngest]: symbol | null; [kLicense]: symbol | null; [kLogstash]: symbol | null; [kMigration]: symbol | null; [kMl]: symbol | null; [kMonitoring]: symbol | null; [kNodes]: symbol | null; [kRollup]: symbol | null; [kSearchableSnapshots]: symbol | null; [kSecurity]: symbol | null; [kShutdown]: symbol | null; [kSlm]: symbol | null; [kSnapshot]: symbol | null; [kSql]: symbol | null; [kSsl]: symbol | null; [kTasks]: symbol | null; [kTextStructure]: symbol | null; [kTransform]: symbol | null; [kWatcher]: symbol | null; [kXpack]: symbol | null; transport: ", + ">; }; asyncSearch: ", + "default", + "; [kInternal]: symbol | null; [kAsyncSearch]: symbol | null; [kAutoscaling]: symbol | null; [kCat]: symbol | null; [kCcr]: symbol | null; [kCluster]: symbol | null; [kDanglingIndices]: symbol | null; [kEnrich]: symbol | null; [kEql]: symbol | null; [kFeatures]: symbol | null; [kFleet]: symbol | null; [kGraph]: symbol | null; [kIlm]: symbol | null; [kIndices]: symbol | null; [kIngest]: symbol | null; [kLicense]: symbol | null; [kLogstash]: symbol | null; [kMigration]: symbol | null; [kMl]: symbol | null; [kMonitoring]: symbol | null; [kNodes]: symbol | null; [kRollup]: symbol | null; [kSearchableSnapshots]: symbol | null; [kSecurity]: symbol | null; [kShutdown]: symbol | null; [kSlm]: symbol | null; [kSnapshot]: symbol | null; [kSql]: symbol | null; [kSsl]: symbol | null; [kTasks]: symbol | null; [kTextStructure]: symbol | null; [kTransform]: symbol | null; [kWatcher]: symbol | null; [kXpack]: symbol | null; transport: ", "default", "; helpers: ", "default", @@ -33750,8 +33805,6 @@ "default", "; Internal: ", "default", - "; asyncSearch: ", - "default", "; autoscaling: ", "default", "; bulk: { (this: That, params: ", @@ -38294,7 +38347,9 @@ "TransportRequestOptions", " | undefined): Promise<", "UpdateResponse", - ">; }; [kInternal]: symbol | null; [kAsyncSearch]: symbol | null; [kAutoscaling]: symbol | null; [kCat]: symbol | null; [kCcr]: symbol | null; [kCluster]: symbol | null; [kDanglingIndices]: symbol | null; [kEnrich]: symbol | null; [kEql]: symbol | null; [kFeatures]: symbol | null; [kFleet]: symbol | null; [kGraph]: symbol | null; [kIlm]: symbol | null; [kIndices]: symbol | null; [kIngest]: symbol | null; [kLicense]: symbol | null; [kLogstash]: symbol | null; [kMigration]: symbol | null; [kMl]: symbol | null; [kMonitoring]: symbol | null; [kNodes]: symbol | null; [kRollup]: symbol | null; [kSearchableSnapshots]: symbol | null; [kSecurity]: symbol | null; [kShutdown]: symbol | null; [kSlm]: symbol | null; [kSnapshot]: symbol | null; [kSql]: symbol | null; [kSsl]: symbol | null; [kTasks]: symbol | null; [kTextStructure]: symbol | null; [kTransform]: symbol | null; [kWatcher]: symbol | null; [kXpack]: symbol | null; transport: ", + ">; }; asyncSearch: ", + "default", + "; [kInternal]: symbol | null; [kAsyncSearch]: symbol | null; [kAutoscaling]: symbol | null; [kCat]: symbol | null; [kCcr]: symbol | null; [kCluster]: symbol | null; [kDanglingIndices]: symbol | null; [kEnrich]: symbol | null; [kEql]: symbol | null; [kFeatures]: symbol | null; [kFleet]: symbol | null; [kGraph]: symbol | null; [kIlm]: symbol | null; [kIndices]: symbol | null; [kIngest]: symbol | null; [kLicense]: symbol | null; [kLogstash]: symbol | null; [kMigration]: symbol | null; [kMl]: symbol | null; [kMonitoring]: symbol | null; [kNodes]: symbol | null; [kRollup]: symbol | null; [kSearchableSnapshots]: symbol | null; [kSecurity]: symbol | null; [kShutdown]: symbol | null; [kSlm]: symbol | null; [kSnapshot]: symbol | null; [kSql]: symbol | null; [kSsl]: symbol | null; [kTasks]: symbol | null; [kTextStructure]: symbol | null; [kTransform]: symbol | null; [kWatcher]: symbol | null; [kXpack]: symbol | null; transport: ", "default", "; helpers: ", "default", @@ -38304,8 +38359,6 @@ "default", "; Internal: ", "default", - "; asyncSearch: ", - "default", "; autoscaling: ", "default", "; bulk: { (this: That, params: ", @@ -40721,18 +40774,6 @@ "plugin": "alerting", "path": "x-pack/plugins/alerting/server/saved_objects/geo_containment/migrations.ts" }, - { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/saved_objects/migrations.ts" - }, - { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/saved_objects/migrations.ts" - }, - { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/saved_objects/migrations.ts" - }, { "plugin": "alerting", "path": "x-pack/plugins/alerting/server/types.ts" @@ -40913,6 +40954,22 @@ "plugin": "ml", "path": "x-pack/plugins/ml/common/types/modules.ts" }, + { + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/saved_objects/migrations/7.11/index.ts" + }, + { + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/saved_objects/migrations/7.11/index.ts" + }, + { + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/saved_objects/migrations/7.15/index.ts" + }, + { + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/saved_objects/migrations/7.15/index.ts" + }, { "plugin": "dashboard", "path": "src/plugins/dashboard/public/services/dashboard_saved_object/lib/save_dashboard_state_to_saved_object.ts" @@ -50606,7 +50663,9 @@ "TransportRequestOptions", " | undefined): Promise<", "UpdateResponse", - ">; }; [kInternal]: symbol | null; [kAsyncSearch]: symbol | null; [kAutoscaling]: symbol | null; [kCat]: symbol | null; [kCcr]: symbol | null; [kCluster]: symbol | null; [kDanglingIndices]: symbol | null; [kEnrich]: symbol | null; [kEql]: symbol | null; [kFeatures]: symbol | null; [kFleet]: symbol | null; [kGraph]: symbol | null; [kIlm]: symbol | null; [kIndices]: symbol | null; [kIngest]: symbol | null; [kLicense]: symbol | null; [kLogstash]: symbol | null; [kMigration]: symbol | null; [kMl]: symbol | null; [kMonitoring]: symbol | null; [kNodes]: symbol | null; [kRollup]: symbol | null; [kSearchableSnapshots]: symbol | null; [kSecurity]: symbol | null; [kShutdown]: symbol | null; [kSlm]: symbol | null; [kSnapshot]: symbol | null; [kSql]: symbol | null; [kSsl]: symbol | null; [kTasks]: symbol | null; [kTextStructure]: symbol | null; [kTransform]: symbol | null; [kWatcher]: symbol | null; [kXpack]: symbol | null; transport: ", + ">; }; asyncSearch: ", + "default", + "; [kInternal]: symbol | null; [kAsyncSearch]: symbol | null; [kAutoscaling]: symbol | null; [kCat]: symbol | null; [kCcr]: symbol | null; [kCluster]: symbol | null; [kDanglingIndices]: symbol | null; [kEnrich]: symbol | null; [kEql]: symbol | null; [kFeatures]: symbol | null; [kFleet]: symbol | null; [kGraph]: symbol | null; [kIlm]: symbol | null; [kIndices]: symbol | null; [kIngest]: symbol | null; [kLicense]: symbol | null; [kLogstash]: symbol | null; [kMigration]: symbol | null; [kMl]: symbol | null; [kMonitoring]: symbol | null; [kNodes]: symbol | null; [kRollup]: symbol | null; [kSearchableSnapshots]: symbol | null; [kSecurity]: symbol | null; [kShutdown]: symbol | null; [kSlm]: symbol | null; [kSnapshot]: symbol | null; [kSql]: symbol | null; [kSsl]: symbol | null; [kTasks]: symbol | null; [kTextStructure]: symbol | null; [kTransform]: symbol | null; [kWatcher]: symbol | null; [kXpack]: symbol | null; transport: ", "default", "; helpers: ", "default", @@ -50616,8 +50675,6 @@ "default", "; Internal: ", "default", - "; asyncSearch: ", - "default", "; autoscaling: ", "default", "; bulk: { (this: That, params: ", diff --git a/api_docs/core.mdx b/api_docs/core.mdx index eaf05e52d4d5e..d7bf847b93965 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-10 +date: 2022-10-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'core'] --- import coreObj from './core.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 | |-------------------|-----------|------------------------|-----------------| -| 2689 | 0 | 23 | 0 | +| 2691 | 0 | 23 | 0 | ## Client diff --git a/api_docs/custom_integrations.devdocs.json b/api_docs/custom_integrations.devdocs.json index 44611a9497dfc..e7512ead801df 100644 --- a/api_docs/custom_integrations.devdocs.json +++ b/api_docs/custom_integrations.devdocs.json @@ -974,6 +974,48 @@ } ], "objects": [ + { + "parentPluginId": "customIntegrations", + "id": "def-common.FEATURED_INTEGRATIONS_BY_CATEGORY", + "type": "Object", + "tags": [], + "label": "FEATURED_INTEGRATIONS_BY_CATEGORY", + "description": [], + "path": "src/plugins/custom_integrations/common/index.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "customIntegrations", + "id": "def-common.FEATURED_INTEGRATIONS_BY_CATEGORY.security", + "type": "Array", + "tags": [], + "label": "security", + "description": [], + "signature": [ + "string[]" + ], + "path": "src/plugins/custom_integrations/common/index.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "customIntegrations", + "id": "def-common.FEATURED_INTEGRATIONS_BY_CATEGORY.", + "type": "Array", + "tags": [], + "label": "''", + "description": [], + "signature": [ + "string[]" + ], + "path": "src/plugins/custom_integrations/common/index.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, { "parentPluginId": "customIntegrations", "id": "def-common.INTEGRATION_CATEGORY_DISPLAY", diff --git a/api_docs/custom_integrations.mdx b/api_docs/custom_integrations.mdx index 2638867b78d5f..0602cbe560a2f 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-10 +date: 2022-10-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'customIntegrations'] --- import customIntegrationsObj from './custom_integrations.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Fleet](https://github.com/orgs/elastic/teams/fleet) for questions regar | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 104 | 0 | 85 | 1 | +| 107 | 0 | 88 | 1 | ## Client diff --git a/api_docs/dashboard.mdx b/api_docs/dashboard.mdx index 19197f8324fed..6f895403e4104 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-10 +date: 2022-10-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dashboard'] --- import dashboardObj from './dashboard.devdocs.json'; diff --git a/api_docs/dashboard_enhanced.mdx b/api_docs/dashboard_enhanced.mdx index d313c049a619f..92177d27269e9 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-10 +date: 2022-10-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dashboardEnhanced'] --- import dashboardEnhancedObj from './dashboard_enhanced.devdocs.json'; diff --git a/api_docs/data.devdocs.json b/api_docs/data.devdocs.json index 33d5834e2191a..f2b4bf9e4a06d 100644 --- a/api_docs/data.devdocs.json +++ b/api_docs/data.devdocs.json @@ -2588,7 +2588,7 @@ "description": [], "signature": [ "PluginInitializerContext", - "; }>; sessions: Readonly<{} & { enabled: boolean; notTouchedTimeout: moment.Duration; maxUpdateRetries: number; defaultExpiration: moment.Duration; management: Readonly<{} & { refreshInterval: moment.Duration; maxSessions: number; refreshTimeout: moment.Duration; expiresSoonWarning: moment.Duration; }>; }>; }>; }>>" + "; }>; asyncSearch: Readonly<{} & { waitForCompletion: moment.Duration; keepAlive: moment.Duration; batchedReduceSize: number; }>; sessions: Readonly<{} & { enabled: boolean; notTouchedTimeout: moment.Duration; maxUpdateRetries: number; defaultExpiration: moment.Duration; management: Readonly<{} & { refreshInterval: moment.Duration; maxSessions: number; refreshTimeout: moment.Duration; expiresSoonWarning: moment.Duration; }>; }>; }>; }>>" ], "path": "src/plugins/data/public/plugin.ts", "deprecated": false, @@ -11780,7 +11780,7 @@ "section": "def-server.PluginInitializerContext", "text": "PluginInitializerContext" }, - "; }>; sessions: Readonly<{} & { enabled: boolean; notTouchedTimeout: moment.Duration; maxUpdateRetries: number; defaultExpiration: moment.Duration; management: Readonly<{} & { refreshInterval: moment.Duration; maxSessions: number; refreshTimeout: moment.Duration; expiresSoonWarning: moment.Duration; }>; }>; }>; }>>" + "; }>; asyncSearch: Readonly<{} & { waitForCompletion: moment.Duration; keepAlive: moment.Duration; batchedReduceSize: number; }>; sessions: Readonly<{} & { enabled: boolean; notTouchedTimeout: moment.Duration; maxUpdateRetries: number; defaultExpiration: moment.Duration; management: Readonly<{} & { refreshInterval: moment.Duration; maxSessions: number; refreshTimeout: moment.Duration; expiresSoonWarning: moment.Duration; }>; }>; }>; }>>" ], "path": "src/plugins/data/server/plugin.ts", "deprecated": false, @@ -12048,3588 +12048,4490 @@ "parentPluginId": "data", "id": "def-server.DataView.title", "type": "string", - "tags": [], + "tags": [ + "deprecated" + ], "label": "title", "description": [ "\nTitle of data view" ], "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "data", - "id": "def-server.DataView.fieldFormatMap", - "type": "Object", - "tags": [], - "label": "fieldFormatMap", - "description": [ - "\nMap of field formats by field name" - ], - "signature": [ - "{ [x: string]: ", + "deprecated": true, + "trackAdoption": false, + "references": [ { - "pluginId": "fieldFormats", - "scope": "common", - "docId": "kibFieldFormatsPluginApi", - "section": "def-common.SerializedFieldFormat", - "text": "SerializedFieldFormat" + "plugin": "timelines", + "path": "x-pack/plugins/timelines/public/container/source/index.tsx" }, - "<{}, ", - "SerializableRecord", - ">; }" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "data", - "id": "def-server.DataView.typeMeta", - "type": "Object", - "tags": [], - "label": "typeMeta", - "description": [ - "\nOnly used by rollup indices, used by rollup specific endpoint to load field list." - ], - "signature": [ { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.TypeMeta", - "text": "TypeMeta" + "plugin": "timelines", + "path": "x-pack/plugins/timelines/public/container/source/index.tsx" }, - " | undefined" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "data", - "id": "def-server.DataView.fields", - "type": "CompoundType", - "tags": [], - "label": "fields", - "description": [ - "\nField list, in extended array format" - ], - "signature": [ { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.IIndexPatternFieldList", - "text": "IIndexPatternFieldList" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/containers/source/index.tsx" }, - " & { toSpec: () => ", { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataViewFieldMap", - "text": "DataViewFieldMap" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/containers/source/index.tsx" }, - "; }" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "data", - "id": "def-server.DataView.timeFieldName", - "type": "string", - "tags": [], - "label": "timeFieldName", - "description": [ - "\nTimestamp field name" - ], - "signature": [ - "string | undefined" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "data", - "id": "def-server.DataView.type", - "type": "string", - "tags": [], - "label": "type", - "description": [ - "\nType is used to identify rollup index patterns." - ], - "signature": [ - "string | undefined" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "data", - "id": "def-server.DataView.flattenHit", - "type": "Function", - "tags": [ - "deprecated" - ], - "label": "flattenHit", - "description": [], - "signature": [ - "(hit: Record, deep?: boolean | undefined) => Record" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": true, - "trackAdoption": false, - "references": [ { - "plugin": "dataViews", - "path": "src/plugins/data_views/common/data_views/data_view.ts" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/detections/containers/detection_engine/exceptions/get_es_query_filter.ts" }, { - "plugin": "maps", - "path": "x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts" }, { - "plugin": "maps", - "path": "x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx" - } - ], - "returnComment": [], - "children": [ + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/utils.ts" + }, { - "parentPluginId": "data", - "id": "def-server.DataView.flattenHit.$1", - "type": "Object", - "tags": [], - "label": "hit", - "description": [], - "signature": [ - "{ [x: string]: unknown[]; }" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/signals/get_query_filter.ts" }, { - "parentPluginId": "data", - "id": "def-server.DataView.flattenHit.$2", - "type": "CompoundType", - "tags": [], - "label": "deep", - "description": [], - "signature": [ - "boolean | undefined" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false - } - ] - }, - { - "parentPluginId": "data", - "id": "def-server.DataView.metaFields", - "type": "Array", - "tags": [], - "label": "metaFields", - "description": [ - "\nList of meta fields by name" - ], - "signature": [ - "string[]" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "data", - "id": "def-server.DataView.version", - "type": "string", - "tags": [], - "label": "version", - "description": [ - "\nSavedObject version" - ], - "signature": [ - "string | undefined" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "data", - "id": "def-server.DataView.sourceFilters", - "type": "Array", - "tags": [], - "label": "sourceFilters", - "description": [ - "\nArray of filters - hides fields in discover" - ], - "signature": [ + "plugin": "timelines", + "path": "x-pack/plugins/timelines/public/mock/index_pattern.ts" + }, { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.SourceFilter", - "text": "SourceFilter" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/mock/index_pattern.ts" }, - "[] | undefined" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "data", - "id": "def-server.DataView.namespaces", - "type": "Array", - "tags": [], - "label": "namespaces", - "description": [ - "\nArray of namespace ids" - ], - "signature": [ - "string[]" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "data", - "id": "def-server.DataView.allowNoIndex", - "type": "boolean", - "tags": [], - "label": "allowNoIndex", - "description": [ - "\nPrevents errors when index pattern exists before indices" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "data", - "id": "def-server.DataView.name", - "type": "string", - "tags": [], - "label": "name", - "description": [ - "\nName of the data view. Human readable name used to differentiate data view." - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "data", - "id": "def-server.DataView.matchedIndices", - "type": "Array", - "tags": [], - "label": "matchedIndices", - "description": [], - "signature": [ - "string[]" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "data", - "id": "def-server.DataView.Unnamed", - "type": "Function", - "tags": [], - "label": "Constructor", - "description": [ - "\nconstructor" - ], - "signature": [ - "any" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ { - "parentPluginId": "data", - "id": "def-server.DataView.Unnamed.$1", - "type": "Object", - "tags": [], - "label": "config", - "description": [ - "- config data and dependencies" - ], - "signature": [ - "DataViewDeps" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "data", - "id": "def-server.DataView.getName", - "type": "Function", - "tags": [], - "label": "getName", - "description": [ - "\nGet name of Data View" - ], - "signature": [ - "() => string" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [] - }, - { - "parentPluginId": "data", - "id": "def-server.DataView.getOriginalSavedObjectBody", - "type": "Function", - "tags": [], - "label": "getOriginalSavedObjectBody", - "description": [ - "\nGet last saved saved object fields" - ], - "signature": [ - "() => { fieldAttrs?: string | undefined; title?: string | undefined; timeFieldName?: string | undefined; fields?: string | undefined; sourceFilters?: string | undefined; fieldFormatMap?: string | undefined; typeMeta?: string | undefined; type?: string | undefined; }" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [] - }, - { - "parentPluginId": "data", - "id": "def-server.DataView.resetOriginalSavedObjectBody", - "type": "Function", - "tags": [], - "label": "resetOriginalSavedObjectBody", - "description": [ - "\nReset last saved saved object fields. Used after saving." - ], - "signature": [ - "() => void" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [] - }, - { - "parentPluginId": "data", - "id": "def-server.DataView.getFieldAttrs", - "type": "Function", - "tags": [], - "label": "getFieldAttrs", - "description": [ - "\nReturns field attributes map" - ], - "signature": [ - "() => { [x: string]: ", + "plugin": "lists", + "path": "x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts" + }, { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.FieldAttrSet", - "text": "FieldAttrSet" + "plugin": "lists", + "path": "x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts" }, - "; }" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [] - }, - { - "parentPluginId": "data", - "id": "def-server.DataView.getComputedFields", - "type": "Function", - "tags": [], - "label": "getComputedFields", - "description": [ - "\nReturns scripted fields" - ], - "signature": [ - "() => { storedFields: string[]; scriptFields: Record; docvalueFields: { field: string; format: string; }[]; runtimeFields: ", - "MappingRuntimeFields", - "; }" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [] - }, - { - "parentPluginId": "data", - "id": "def-server.DataView.isPersisted", - "type": "Function", - "tags": [], - "label": "isPersisted", - "description": [], - "signature": [ - "() => boolean" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [] - }, - { - "parentPluginId": "data", - "id": "def-server.DataView.toSpec", - "type": "Function", - "tags": [], - "label": "toSpec", - "description": [ - "\nCreates static representation of the data view." - ], - "signature": [ - "(includeFields?: boolean) => ", { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataViewSpec", - "text": "DataViewSpec" - } - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ + "plugin": "lists", + "path": "x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts" + }, { - "parentPluginId": "data", - "id": "def-server.DataView.toSpec.$1", - "type": "boolean", - "tags": [], - "label": "includeFields", - "description": [ - "Whether or not to include the `fields` list as part of this spec. If not included, the list\nwill be fetched from Elasticsearch when instantiating a new Data View with this spec." - ], - "signature": [ - "boolean" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "data", - "id": "def-server.DataView.getSourceFiltering", - "type": "Function", - "tags": [], - "label": "getSourceFiltering", - "description": [ - "\nGet the source filtering configuration for that index." - ], - "signature": [ - "() => { excludes: string[]; }" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [] - }, - { - "parentPluginId": "data", - "id": "def-server.DataView.removeScriptedField", - "type": "Function", - "tags": [ - "deprecated" - ], - "label": "removeScriptedField", - "description": [ - "\nRemoves scripted field from field list." - ], - "signature": [ - "(fieldName: string) => void" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": true, - "trackAdoption": false, - "references": [ - { - "plugin": "dataViewManagement", - "path": "src/plugins/data_view_management/public/components/edit_index_pattern/scripted_fields_table/scripted_fields_table.tsx" + "plugin": "lists", + "path": "x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts" }, { - "plugin": "dataViewManagement", - "path": "src/plugins/data_view_management/public/components/field_editor/field_editor.tsx" + "plugin": "lists", + "path": "x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts" }, { - "plugin": "dataViews", - "path": "src/plugins/data_views/common/data_views/data_view.test.ts" - } - ], - "children": [ - { - "parentPluginId": "data", - "id": "def-server.DataView.removeScriptedField.$1", - "type": "string", - "tags": [], - "label": "fieldName", - "description": [ - "name of scripted field to remove" - ], - "signature": [ - "string" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "data", - "id": "def-server.DataView.getNonScriptedFields", - "type": "Function", - "tags": [ - "deprecated" - ], - "label": "getNonScriptedFields", - "description": [ - "\n" - ], - "signature": [ - "() => ", + "plugin": "lists", + "path": "x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts" + }, { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataViewField", - "text": "DataViewField" + "plugin": "lists", + "path": "x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts" }, - "[]" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": true, - "trackAdoption": false, - "references": [ { - "plugin": "visTypeTimeseries", - "path": "src/plugins/vis_types/timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts" + "plugin": "lists", + "path": "x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts" }, { - "plugin": "graph", - "path": "x-pack/plugins/graph/public/services/persistence/deserialize.ts" + "plugin": "lists", + "path": "x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts" }, { - "plugin": "graph", - "path": "x-pack/plugins/graph/public/state_management/datasource.test.ts" + "plugin": "threatIntelligence", + "path": "x-pack/plugins/threat_intelligence/public/common/mocks/mock_security_context.tsx" }, { - "plugin": "graph", - "path": "x-pack/plugins/graph/public/services/persistence/deserialize.test.ts" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/flyout_components/alerts_actions/utils.test.ts" }, { - "plugin": "graph", - "path": "x-pack/plugins/graph/public/services/persistence/deserialize.test.ts" + "plugin": "dataViews", + "path": "src/plugins/data_views/common/data_views/data_view.ts" }, { - "plugin": "dataViewManagement", - "path": "src/plugins/data_view_management/public/components/edit_index_pattern/source_filters_table/components/table/table.tsx" + "plugin": "dataViews", + "path": "src/plugins/data_views/common/data_views/data_view.ts" }, { - "plugin": "dataViewManagement", - "path": "src/plugins/data_view_management/public/components/edit_index_pattern/edit_index_pattern.tsx" + "plugin": "dataViews", + "path": "src/plugins/data_views/common/data_views/data_view.ts" }, { - "plugin": "dataViewManagement", - "path": "src/plugins/data_view_management/public/components/edit_index_pattern/edit_index_pattern.tsx" + "plugin": "dataViews", + "path": "src/plugins/data_views/common/data_views/data_view.ts" }, { - "plugin": "dataViewManagement", - "path": "src/plugins/data_view_management/public/components/edit_index_pattern/edit_index_pattern.tsx" + "plugin": "dataViewEditor", + "path": "src/plugins/data_view_editor/public/components/data_view_editor_flyout_content.tsx" }, { - "plugin": "dataViews", - "path": "src/plugins/data_views/common/data_views/data_view.test.ts" + "plugin": "unifiedSearch", + "path": "src/plugins/unified_search/public/autocomplete/providers/value_suggestion_provider.ts" }, { - "plugin": "visTypeTimeseries", - "path": "src/plugins/vis_types/timeseries/public/application/lib/fetch_fields.ts" - } - ], - "children": [], - "returnComment": [] - }, - { - "parentPluginId": "data", - "id": "def-server.DataView.getScriptedFields", - "type": "Function", - "tags": [ - "deprecated" - ], - "label": "getScriptedFields", - "description": [ - "\n" - ], - "signature": [ - "() => ", + "plugin": "unifiedSearch", + "path": "src/plugins/unified_search/public/query_string_input/fetch_index_patterns.ts" + }, { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataViewField", - "text": "DataViewField" + "plugin": "unifiedSearch", + "path": "src/plugins/unified_search/public/dataview_picker/change_dataview.tsx" }, - "[]" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": true, - "trackAdoption": false, - "references": [ { "plugin": "dataViews", - "path": "src/plugins/data_views/common/data_views/data_view.ts" + "path": "src/plugins/data_views/server/rest_api_routes/update_data_view.ts" }, { "plugin": "dataViews", - "path": "src/plugins/data_views/common/data_views/data_view.ts" + "path": "src/plugins/data_views/server/rest_api_routes/update_data_view.ts" }, { - "plugin": "dataViews", - "path": "src/plugins/data_views/common/data_views/data_views.ts" + "plugin": "triggersActionsUi", + "path": "x-pack/plugins/triggers_actions_ui/public/common/lib/data_apis.ts" }, { - "plugin": "dataViews", - "path": "src/plugins/data_views/server/register_index_pattern_usage_collection.ts" + "plugin": "savedObjectsManagement", + "path": "src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx" }, { - "plugin": "dataViewManagement", - "path": "src/plugins/data_view_management/public/components/edit_index_pattern/scripted_fields_table/scripted_fields_table.tsx" + "plugin": "savedObjectsManagement", + "path": "src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx" }, { - "plugin": "dataViews", - "path": "src/plugins/data_views/common/data_views/data_view.test.ts" + "plugin": "unifiedFieldList", + "path": "src/plugins/unified_field_list/public/services/field_stats/load_field_stats.ts" }, { - "plugin": "dataViews", - "path": "src/plugins/data_views/common/data_views/data_view.test.ts" + "plugin": "unifiedFieldList", + "path": "src/plugins/unified_field_list/common/utils/field_existing_utils.ts" }, { - "plugin": "dataViews", - "path": "src/plugins/data_views/common/data_views/data_view.test.ts" + "plugin": "unifiedFieldList", + "path": "src/plugins/unified_field_list/common/utils/field_existing_utils.ts" }, { - "plugin": "dataViews", - "path": "src/plugins/data_views/common/data_views/data_view.test.ts" + "plugin": "unifiedFieldList", + "path": "src/plugins/unified_field_list/common/utils/field_existing_utils.ts" }, { - "plugin": "dataViews", - "path": "src/plugins/data_views/common/data_views/data_view.test.ts" - } - ], - "children": [], - "returnComment": [] - }, - { - "parentPluginId": "data", - "id": "def-server.DataView.isTSDBMode", - "type": "Function", - "tags": [], - "label": "isTSDBMode", - "description": [ - "\nreturns true if dataview contains TSDB fields" - ], - "signature": [ - "() => boolean" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [] - }, - { - "parentPluginId": "data", - "id": "def-server.DataView.isTimeBased", - "type": "Function", - "tags": [], - "label": "isTimeBased", - "description": [ - "\nDoes the data view have a timestamp field?" - ], - "signature": [ - "() => this is ", + "plugin": "discover", + "path": "src/plugins/discover/public/hooks/use_es_doc_search.ts" + }, { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.TimeBasedDataView", - "text": "TimeBasedDataView" - } - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [] - }, - { - "parentPluginId": "data", - "id": "def-server.DataView.isTimeNanosBased", - "type": "Function", - "tags": [], - "label": "isTimeNanosBased", - "description": [ - "\nDoes the data view have a timestamp field and is it a date nanos field?" - ], - "signature": [ - "() => this is ", + "plugin": "discover", + "path": "src/plugins/discover/public/application/main/utils/resolve_data_view.ts" + }, { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.TimeBasedDataView", - "text": "TimeBasedDataView" - } - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [] - }, - { - "parentPluginId": "data", - "id": "def-server.DataView.getTimeField", - "type": "Function", - "tags": [], - "label": "getTimeField", - "description": [ - "\nGet timestamp field as DataViewField or return undefined" - ], - "signature": [ - "() => ", + "plugin": "discover", + "path": "src/plugins/discover/public/application/main/utils/resolve_data_view.ts" + }, { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataViewField", - "text": "DataViewField" + "plugin": "discover", + "path": "src/plugins/discover/public/application/main/components/sidebar/discover_sidebar.tsx" }, - " | undefined" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [] - }, - { - "parentPluginId": "data", - "id": "def-server.DataView.getFieldByName", - "type": "Function", - "tags": [], - "label": "getFieldByName", - "description": [ - "\nGet field by name." - ], - "signature": [ - "(name: string) => ", { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataViewField", - "text": "DataViewField" + "plugin": "discover", + "path": "src/plugins/discover/public/application/main/components/top_nav/discover_topnav.tsx" }, - " | undefined" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ { - "parentPluginId": "data", - "id": "def-server.DataView.getFieldByName.$1", - "type": "string", - "tags": [], - "label": "name", - "description": [ - "field name" - ], - "signature": [ - "string" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "data", - "id": "def-server.DataView.getAggregationRestrictions", - "type": "Function", - "tags": [], - "label": "getAggregationRestrictions", - "description": [ - "\nGet aggregation restrictions. Rollup fields can only perform a subset of aggregations." - ], - "signature": [ - "() => Record | undefined" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [] - }, - { - "parentPluginId": "data", - "id": "def-server.DataView.getAsSavedObjectBody", - "type": "Function", - "tags": [], - "label": "getAsSavedObjectBody", - "description": [ - "\nReturns index pattern as saved object body for saving" - ], - "signature": [ - "() => ", { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataViewAttributes", - "text": "DataViewAttributes" - } - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [] - }, - { - "parentPluginId": "data", - "id": "def-server.DataView.getFormatterForField", - "type": "Function", - "tags": [], - "label": "getFormatterForField", - "description": [ - "\nProvide a field, get its formatter" - ], - "signature": [ - "(field: ", + "plugin": "aiops", + "path": "x-pack/plugins/aiops/public/components/explain_log_rate_spikes/explain_log_rate_spikes_analysis.tsx" + }, { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.FieldSpec", - "text": "FieldSpec" + "plugin": "aiops", + "path": "x-pack/plugins/aiops/public/components/log_categorization/log_categorization_page.tsx" }, - " | ", { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataViewField", - "text": "DataViewField" + "plugin": "presentationUtil", + "path": "src/plugins/presentation_util/public/services/storybook/data_views.ts" }, - ") => ", { - "pluginId": "fieldFormats", - "scope": "common", - "docId": "kibFieldFormatsPluginApi", - "section": "def-common.FieldFormat", - "text": "FieldFormat" - } - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ + "plugin": "controls", + "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" + }, { - "parentPluginId": "data", - "id": "def-server.DataView.getFormatterForField.$1", - "type": "CompoundType", - "tags": [], - "label": "field", - "description": [ - "field to get formatter for" - ], - "signature": [ - { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.FieldSpec", - "text": "FieldSpec" - }, - " | ", - { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataViewField", - "text": "DataViewField" - } - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "data", - "id": "def-server.DataView.addRuntimeField", - "type": "Function", - "tags": [], - "label": "addRuntimeField", - "description": [ - "\nAdd a runtime field - Appended to existing mapped field or a new field is\ncreated as appropriate." - ], - "signature": [ - "(name: string, runtimeField: ", + "plugin": "controls", + "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" + }, { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.RuntimeField", - "text": "RuntimeField" + "plugin": "lens", + "path": "x-pack/plugins/lens/public/data_views_service/loader.ts" }, - ") => ", { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataViewField", - "text": "DataViewField" + "plugin": "lens", + "path": "x-pack/plugins/lens/public/app_plugin/lens_top_nav.tsx" }, - "[]" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ { - "parentPluginId": "data", - "id": "def-server.DataView.addRuntimeField.$1", - "type": "string", - "tags": [], - "label": "name", - "description": [ - "Field name" - ], - "signature": [ - "string" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true + "plugin": "observability", + "path": "x-pack/plugins/observability/public/utils/observability_data_views/observability_data_views.ts" }, { - "parentPluginId": "data", - "id": "def-server.DataView.addRuntimeField.$2", - "type": "Object", - "tags": [], - "label": "runtimeField", - "description": [ - "Runtime field definition" - ], - "signature": [ - { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.RuntimeField", - "text": "RuntimeField" - } - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "data", - "id": "def-server.DataView.hasRuntimeField", - "type": "Function", - "tags": [], - "label": "hasRuntimeField", - "description": [ - "\nChecks if runtime field exists" - ], - "signature": [ - "(name: string) => boolean" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ + "plugin": "observability", + "path": "x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/report_definition_field.tsx" + }, { - "parentPluginId": "data", - "id": "def-server.DataView.hasRuntimeField.$1", - "type": "string", - "tags": [], - "label": "name", - "description": [ - "field name" - ], - "signature": [ - "string" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "data", - "id": "def-server.DataView.getRuntimeField", - "type": "Function", - "tags": [], - "label": "getRuntimeField", - "description": [ - "\nReturns runtime field if exists" - ], - "signature": [ - "(name: string) => ", + "plugin": "observability", + "path": "x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/use_filter_values.ts" + }, { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.RuntimeField", - "text": "RuntimeField" + "plugin": "observability", + "path": "x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/filter_value_btn.tsx" }, - " | null" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ { - "parentPluginId": "data", - "id": "def-server.DataView.getRuntimeField.$1", - "type": "string", - "tags": [], - "label": "name", - "description": [ - "Runtime field name" - ], - "signature": [ - "string" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "data", - "id": "def-server.DataView.getAllRuntimeFields", - "type": "Function", - "tags": [], - "label": "getAllRuntimeFields", - "description": [ - "\nGet all runtime field definitions.\nNOTE: this does not strip out runtime fields that match mapped field names" - ], - "signature": [ - "() => Record" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [ - "map of runtime field definitions by field name" - ] - }, - { - "parentPluginId": "data", - "id": "def-server.DataView.getFieldsByRuntimeFieldName", - "type": "Function", - "tags": [], - "label": "getFieldsByRuntimeFieldName", - "description": [ - "\nReturns data view fields backed by runtime fields." - ], - "signature": [ - "(name: string) => Record | undefined" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ { - "parentPluginId": "data", - "id": "def-server.DataView.getFieldsByRuntimeFieldName.$1", - "type": "string", - "tags": [], - "label": "name", - "description": [ - "runtime field name" - ], - "signature": [ - "string" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [ - "map of DataViewFields (that are runtime fields) by field name" - ] - }, - { - "parentPluginId": "data", - "id": "def-server.DataView.replaceAllRuntimeFields", - "type": "Function", - "tags": [], - "label": "replaceAllRuntimeFields", - "description": [ - "\nReplaces all existing runtime fields with new fields." - ], - "signature": [ - "(newFields: Record) => void" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ { - "parentPluginId": "data", - "id": "def-server.DataView.replaceAllRuntimeFields.$1", - "type": "Object", - "tags": [], - "label": "newFields", - "description": [ - "Map of runtime field definitions by field name" - ], - "signature": [ - "Record" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "data", - "id": "def-server.DataView.removeRuntimeField", - "type": "Function", - "tags": [], - "label": "removeRuntimeField", - "description": [ - "\nRemove a runtime field - removed from mapped field or removed unmapped\nfield as appropriate. Doesn't clear associated field attributes." - ], - "signature": [ - "(name: string) => void" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ + "plugin": "maps", + "path": "x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx" + }, { - "parentPluginId": "data", - "id": "def-server.DataView.removeRuntimeField.$1", - "type": "string", - "tags": [], - "label": "name", - "description": [ - "- Field name to remove" - ], - "signature": [ - "string" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "data", - "id": "def-server.DataView.getRuntimeMappings", - "type": "Function", - "tags": [], - "label": "getRuntimeMappings", - "description": [ - "\nReturn the \"runtime_mappings\" section of the ES search query." - ], - "signature": [ - "() => ", - "MappingRuntimeFields" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [] - }, - { - "parentPluginId": "data", - "id": "def-server.DataView.getFormatterForFieldNoDefault", - "type": "Function", - "tags": [], - "label": "getFormatterForFieldNoDefault", - "description": [ - "\nGet formatter for a given field name. Return undefined if none exists." - ], - "signature": [ - "(fieldname: string) => ", + "plugin": "maps", + "path": "x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx" + }, { - "pluginId": "fieldFormats", - "scope": "common", - "docId": "kibFieldFormatsPluginApi", - "section": "def-common.FieldFormat", - "text": "FieldFormat" + "plugin": "maps", + "path": "x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx" }, - " | undefined" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ { - "parentPluginId": "data", - "id": "def-server.DataView.getFormatterForFieldNoDefault.$1", - "type": "string", - "tags": [], - "label": "fieldname", - "description": [ - "name of field to get formatter for" - ], - "signature": [ - "string" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "data", - "id": "def-server.DataView.setFieldAttrs", - "type": "Function", - "tags": [], - "label": "setFieldAttrs", - "description": [ - "\nSet field attribute" - ], - "signature": [ - "(fieldName: string, attrName: K, value: ", { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.FieldAttrSet", - "text": "FieldAttrSet" + "plugin": "maps", + "path": "x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx" }, - "[K]) => void" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ { - "parentPluginId": "data", - "id": "def-server.DataView.setFieldAttrs.$1", - "type": "string", - "tags": [], - "label": "fieldName", - "description": [ - "name of field to set attribute on" - ], - "signature": [ - "string" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true + "plugin": "maps", + "path": "x-pack/plugins/maps/public/trigger_actions/visualize_geo_field_action.ts" }, { - "parentPluginId": "data", - "id": "def-server.DataView.setFieldAttrs.$2", - "type": "Uncategorized", - "tags": [], - "label": "attrName", - "description": [ - "name of attribute to set" - ], - "signature": [ - "K" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true + "plugin": "dataVisualizer", + "path": "x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/full_time_range_selector/full_time_range_selector_service.ts" }, { - "parentPluginId": "data", - "id": "def-server.DataView.setFieldAttrs.$3", - "type": "Uncategorized", - "tags": [], - "label": "value", - "description": [ - "value of attribute" - ], - "signature": [ - { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.FieldAttrSet", - "text": "FieldAttrSet" - }, - "[K]" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "data", - "id": "def-server.DataView.setFieldCustomLabel", - "type": "Function", - "tags": [], - "label": "setFieldCustomLabel", - "description": [ - "\nSet field custom label" - ], - "signature": [ - "(fieldName: string, customLabel: string | null | undefined) => void" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ + "plugin": "dataVisualizer", + "path": "x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/actions_panel/actions_panel.tsx" + }, { - "parentPluginId": "data", - "id": "def-server.DataView.setFieldCustomLabel.$1", - "type": "string", - "tags": [], - "label": "fieldName", - "description": [ - "name of field to set custom label on" - ], - "signature": [ - "string" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true + "plugin": "dataVisualizer", + "path": "x-pack/plugins/data_visualizer/public/application/index_data_visualizer/hooks/use_data_visualizer_grid_data.ts" }, { - "parentPluginId": "data", - "id": "def-server.DataView.setFieldCustomLabel.$2", - "type": "CompoundType", - "tags": [], - "label": "customLabel", - "description": [ - "custom label value. If undefined, custom label is removed" - ], - "signature": [ - "string | null | undefined" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": false - } - ], - "returnComment": [] - }, - { - "parentPluginId": "data", - "id": "def-server.DataView.setFieldCount", - "type": "Function", - "tags": [], - "label": "setFieldCount", - "description": [ - "\nSet field count" - ], - "signature": [ - "(fieldName: string, count: number | null | undefined) => void" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ + "plugin": "dataVisualizer", + "path": "x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/index_data_visualizer_view.tsx" + }, { - "parentPluginId": "data", - "id": "def-server.DataView.setFieldCount.$1", - "type": "string", - "tags": [], - "label": "fieldName", - "description": [ - "name of field to set count on" - ], - "signature": [ - "string" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/util/index_utils.ts" }, { - "parentPluginId": "data", - "id": "def-server.DataView.setFieldCount.$2", - "type": "CompoundType", - "tags": [], - "label": "count", - "description": [ - "count value. If undefined, count is removed" - ], - "signature": [ - "number | null | undefined" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": false - } - ], - "returnComment": [] - }, - { - "parentPluginId": "data", - "id": "def-server.DataView.setFieldFormat", - "type": "Function", - "tags": [], - "label": "setFieldFormat", - "description": [ - "\nSet field formatter" - ], - "signature": [ - "(fieldName: string, format: ", + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/util/index_utils.ts" + }, { - "pluginId": "fieldFormats", - "scope": "common", - "docId": "kibFieldFormatsPluginApi", - "section": "def-common.SerializedFieldFormat", - "text": "SerializedFieldFormat" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/util/index_utils.ts" }, - "<{}, ", - "SerializableRecord", - ">) => void" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ { - "parentPluginId": "data", - "id": "def-server.DataView.setFieldFormat.$1", - "type": "string", - "tags": [], - "label": "fieldName", - "description": [ - "name of field to set format on" - ], - "signature": [ - "string" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/services/new_job_capabilities/new_job_capabilities_service_analytics.ts" }, { - "parentPluginId": "data", - "id": "def-server.DataView.setFieldFormat.$2", - "type": "Object", - "tags": [], - "label": "format", - "description": [ - "field format in serialized form" - ], - "signature": [ - { - "pluginId": "fieldFormats", - "scope": "common", - "docId": "kibFieldFormatsPluginApi", - "section": "def-common.SerializedFieldFormat", - "text": "SerializedFieldFormat" - }, - "<{}, ", - "SerializableRecord", - ">" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "data", - "id": "def-server.DataView.deleteFieldFormat", - "type": "Function", - "tags": [], - "label": "deleteFieldFormat", - "description": [ - "\nRemove field format from the field format map." - ], - "signature": [ - "(fieldName: string) => void" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/services/new_job_capabilities/new_job_capabilities_service_analytics.ts" + }, { - "parentPluginId": "data", - "id": "def-server.DataView.deleteFieldFormat.$1", - "type": "string", - "tags": [], - "label": "fieldName", - "description": [ - "field name associated with the format for removal" - ], - "signature": [ - "string" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - } - ], - "initialIsOpen": false - }, - { - "parentPluginId": "data", - "id": "def-server.DataViewsService", - "type": "Class", - "tags": [], - "label": "DataViewsService", - "description": [ - "\nData views service, providing CRUD operations for data views." - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "data", - "id": "def-server.DataViewsService.getCanSave", - "type": "Function", - "tags": [], - "label": "getCanSave", - "description": [ - "\nCan the user save data views?" - ], - "signature": [ - "() => Promise" - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "returnComment": [], - "children": [] - }, - { - "parentPluginId": "data", - "id": "def-server.DataViewsService.Unnamed", - "type": "Function", - "tags": [], - "label": "Constructor", - "description": [ - "\nDataViewsService constructor" - ], - "signature": [ - "any" - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_details.tsx" + }, { - "parentPluginId": "data", - "id": "def-server.DataViewsService.Unnamed.$1", - "type": "Object", - "tags": [], - "label": "deps", - "description": [ - "Service dependencies" - ], - "signature": [ - { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataViewsServiceDeps", - "text": "DataViewsServiceDeps" - } - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "data", - "id": "def-server.DataViewsService.getIds", - "type": "Function", - "tags": [], - "label": "getIds", - "description": [ - "\nGets list of index pattern ids." - ], - "signature": [ - "(refresh?: boolean) => Promise" - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/datavisualizer/index_based/data_loader/data_loader.ts" + }, { - "parentPluginId": "data", - "id": "def-server.DataViewsService.getIds.$1", - "type": "boolean", - "tags": [], - "label": "refresh", - "description": [ - "Force refresh of index pattern list" - ], - "signature": [ - "boolean" - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "data", - "id": "def-server.DataViewsService.getTitles", - "type": "Function", - "tags": [], - "label": "getTitles", - "description": [ - "\nGets list of index pattern titles." - ], - "signature": [ - "(refresh?: boolean) => Promise" - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" + }, { - "parentPluginId": "data", - "id": "def-server.DataViewsService.getTitles.$1", - "type": "boolean", - "tags": [], - "label": "refresh", - "description": [ - "Force refresh of index pattern list" - ], - "signature": [ - "boolean" - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "data", - "id": "def-server.DataViewsService.find", - "type": "Function", - "tags": [], - "label": "find", - "description": [ - "\nFind and load index patterns by title." - ], - "signature": [ - "(search: string, size?: number) => Promise<", + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" + }, { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataView", - "text": "DataView" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" }, - "[]>" - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ { - "parentPluginId": "data", - "id": "def-server.DataViewsService.find.$1", - "type": "string", - "tags": [], - "label": "search", - "description": [ - "Search string" - ], - "signature": [ - "string" - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" }, { - "parentPluginId": "data", - "id": "def-server.DataViewsService.find.$2", - "type": "number", - "tags": [], - "label": "size", - "description": [ - "Number of data views to return" - ], - "signature": [ - "number" - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [ - "DataView[]" - ] - }, - { - "parentPluginId": "data", - "id": "def-server.DataViewsService.getIdsWithTitle", - "type": "Function", - "tags": [], - "label": "getIdsWithTitle", - "description": [ - "\nGets list of index pattern ids with titles." - ], - "signature": [ - "(refresh?: boolean) => Promise<", + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" + }, { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataViewListItem", - "text": "DataViewListItem" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" }, - "[]>" - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ { - "parentPluginId": "data", - "id": "def-server.DataViewsService.getIdsWithTitle.$1", - "type": "boolean", - "tags": [], - "label": "refresh", - "description": [ - "Force refresh of index pattern list" - ], - "signature": [ - "boolean" - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "data", - "id": "def-server.DataViewsService.clearCache", - "type": "Function", - "tags": [], - "label": "clearCache", - "description": [ - "\nClear index pattern saved objects cache." - ], - "signature": [ - "() => void" - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [] - }, - { - "parentPluginId": "data", - "id": "def-server.DataViewsService.clearInstanceCache", - "type": "Function", - "tags": [], - "label": "clearInstanceCache", - "description": [ - "\nClear index pattern instance cache" - ], - "signature": [ - "(id?: string | undefined) => void" - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" + }, { - "parentPluginId": "data", - "id": "def-server.DataViewsService.clearInstanceCache.$1", - "type": "string", - "tags": [], - "label": "id", - "description": [], - "signature": [ - "string | undefined" - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": false - } - ], - "returnComment": [] - }, - { - "parentPluginId": "data", - "id": "def-server.DataViewsService.getCache", - "type": "Function", - "tags": [], - "label": "getCache", - "description": [ - "\nGet cache, contains data view saved objects." - ], - "signature": [ - "() => Promise<", - "SavedObject", - "<", + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" + }, { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataViewSavedObjectAttrs", - "text": "DataViewSavedObjectAttrs" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/page.tsx" }, - ">[] | null | undefined>" - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [] - }, - { - "parentPluginId": "data", - "id": "def-server.DataViewsService.getDefault", - "type": "Function", - "tags": [], - "label": "getDefault", - "description": [ - "\nGet default index pattern" - ], - "signature": [ - "() => Promise<", { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataView", - "text": "DataView" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_clone/clone_action_name.tsx" }, - " | null>" - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [] - }, - { - "parentPluginId": "data", - "id": "def-server.DataViewsService.getDefaultId", - "type": "Function", - "tags": [], - "label": "getDefaultId", - "description": [ - "\nGet default index pattern id" - ], - "signature": [ - "() => Promise" - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [] - }, - { - "parentPluginId": "data", - "id": "def-server.DataViewsService.setDefault", - "type": "Function", - "tags": [], - "label": "setDefault", - "description": [ - "\nOptionally set default index pattern, unless force = true" - ], - "signature": [ - "(id: string | null, force?: boolean) => Promise" - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ { - "parentPluginId": "data", - "id": "def-server.DataViewsService.setDefault.$1", - "type": "CompoundType", - "tags": [], - "label": "id", - "description": [ - "data view id" - ], - "signature": [ - "string | null" - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": false + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/index_or_search/preconfigured_job_redirect.ts" }, { - "parentPluginId": "data", - "id": "def-server.DataViewsService.setDefault.$2", - "type": "boolean", - "tags": [], - "label": "force", - "description": [ - "set default data view even if there's an existing default" - ], - "signature": [ - "boolean" - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "data", - "id": "def-server.DataViewsService.hasUserDataView", - "type": "Function", - "tags": [], - "label": "hasUserDataView", - "description": [ - "\nChecks if current user has a user created index pattern ignoring fleet's server default index patterns." - ], - "signature": [ - "() => Promise" - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [] - }, - { - "parentPluginId": "data", - "id": "def-server.DataViewsService.getFieldsForWildcard", - "type": "Function", - "tags": [], - "label": "getFieldsForWildcard", - "description": [ - "\nGet field list by providing { pattern }." - ], - "signature": [ - "(options: ", + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/job_type/page.tsx" + }, { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.GetFieldsOptions", - "text": "GetFieldsOptions" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/job_type/page.tsx" }, - ") => Promise<", { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.FieldSpec", - "text": "FieldSpec" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/job_type/page.tsx" }, - "[]>" - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ { - "parentPluginId": "data", - "id": "def-server.DataViewsService.getFieldsForWildcard.$1", - "type": "Object", - "tags": [], - "label": "options", - "description": [ - "options for getting field list" - ], - "signature": [ - { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.GetFieldsOptions", - "text": "GetFieldsOptions" - } - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [ - "FieldSpec[]" - ] - }, - { - "parentPluginId": "data", - "id": "def-server.DataViewsService.getFieldsForIndexPattern", - "type": "Function", - "tags": [], - "label": "getFieldsForIndexPattern", - "description": [ - "\nGet field list by providing an index patttern (or spec)." - ], - "signature": [ - "(indexPattern: ", + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/services/new_job_capabilities/new_job_capabilities_service.ts" + }, { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataView", - "text": "DataView" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/services/new_job_capabilities/new_job_capabilities_service.ts" }, - " | ", { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataViewSpec", - "text": "DataViewSpec" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/job_creator.ts" }, - ", options?: ", { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.GetFieldsOptions", - "text": "GetFieldsOptions" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/common/chart_loader/chart_loader.ts" }, - " | undefined) => Promise<", { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.FieldSpec", - "text": "FieldSpec" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/common/results_loader/categorization_examples_loader.ts" }, - "[]>" - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ { - "parentPluginId": "data", - "id": "def-server.DataViewsService.getFieldsForIndexPattern.$1", - "type": "CompoundType", - "tags": [], - "label": "indexPattern", - "description": [], - "signature": [ - { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataView", - "text": "DataView" - }, - " | ", - { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataViewSpec", - "text": "DataViewSpec" - } - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/components/full_time_range_selector/full_time_range_selector_service.ts" }, { - "parentPluginId": "data", - "id": "def-server.DataViewsService.getFieldsForIndexPattern.$2", - "type": "Object", - "tags": [], - "label": "options", - "description": [ - "options for getting field list" - ], - "signature": [ - { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.GetFieldsOptions", - "text": "GetFieldsOptions" - }, - " | undefined" - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": false - } - ], - "returnComment": [ - "FieldSpec[]" - ] - }, - { - "parentPluginId": "data", - "id": "def-server.DataViewsService.refreshFields", - "type": "Function", - "tags": [], - "label": "refreshFields", - "description": [ - "\nRefresh field list for a given index pattern." - ], - "signature": [ - "(indexPattern: ", + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/bucket_span_estimator/estimate_bucket_span.ts" + }, { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataView", - "text": "DataView" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/components/datafeed_step/components/data_view/change_data_view.tsx" }, - ") => Promise" - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ { - "parentPluginId": "data", - "id": "def-server.DataViewsService.refreshFields.$1", - "type": "Object", - "tags": [], - "label": "indexPattern", - "description": [], - "signature": [ - { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataView", - "text": "DataView" - } - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "data", - "id": "def-server.DataViewsService.fieldArrayToMap", - "type": "Function", - "tags": [], - "label": "fieldArrayToMap", - "description": [ - "\nConverts field array to map." - ], - "signature": [ - "(fields: ", + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/new_job/wizard_steps.tsx" + }, { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.FieldSpec", - "text": "FieldSpec" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/recognize/components/job_settings_form.tsx" }, - "[], fieldAttrs?: ", { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.FieldAttrs", - "text": "FieldAttrs" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/recognize/page.tsx" }, - " | undefined) => ", { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataViewFieldMap", - "text": "DataViewFieldMap" - } - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/recognize/page.tsx" + }, { - "parentPluginId": "data", - "id": "def-server.DataViewsService.fieldArrayToMap.$1", - "type": "Array", - "tags": [], - "label": "fields", - "description": [ - ": FieldSpec[]" - ], - "signature": [ - { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.FieldSpec", - "text": "FieldSpec" - }, - "[]" - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/quick_create_job.ts" }, { - "parentPluginId": "data", - "id": "def-server.DataViewsService.fieldArrayToMap.$2", - "type": "Object", - "tags": [], - "label": "fieldAttrs", - "description": [ - ": FieldAttrs" - ], - "signature": [ - { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.FieldAttrs", - "text": "FieldAttrs" - }, - " | undefined" - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": false - } - ], - "returnComment": [ - "Record" - ] - }, - { - "parentPluginId": "data", - "id": "def-server.DataViewsService.savedObjectToSpec", - "type": "Function", - "tags": [], - "label": "savedObjectToSpec", - "description": [ - "\nConverts data view saved object to data view spec." - ], - "signature": [ - "(savedObject: ", - "SavedObject", - "<", + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/use_outlier_data.ts" + }, { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataViewAttributes", - "text": "DataViewAttributes" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/use_exploration_results.ts" }, - ">) => ", { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataViewSpec", - "text": "DataViewSpec" - } - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/source_selection/source_selection.tsx" + }, { - "parentPluginId": "data", - "id": "def-server.DataViewsService.savedObjectToSpec.$1", - "type": "Object", - "tags": [], - "label": "savedObject", - "description": [], - "signature": [ - "SavedObject", - "<", - { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataViewAttributes", - "text": "DataViewAttributes" - }, - ">" - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [ - "DataViewSpec" - ] - }, - { - "parentPluginId": "data", - "id": "def-server.DataViewsService.get", - "type": "Function", - "tags": [], - "label": "get", - "description": [ - "\nGet an index pattern by id, cache optimized." - ], - "signature": [ - "(id: string) => Promise<", + "plugin": "ml", + "path": "x-pack/plugins/ml/public/embeddables/anomaly_charts/anomaly_charts_embeddable.tsx" + }, { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataView", - "text": "DataView" + "plugin": "infra", + "path": "x-pack/plugins/infra/public/pages/logs/settings/validation_errors.ts" }, - ">" - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ { - "parentPluginId": "data", - "id": "def-server.DataViewsService.get.$1", - "type": "string", - "tags": [], - "label": "id", - "description": [], - "signature": [ - "string" - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "data", - "id": "def-server.DataViewsService.create", - "type": "Function", - "tags": [], - "label": "create", - "description": [ - "\nCreate a new data view instance." - ], - "signature": [ - "({ id, name, title, ...restOfSpec }: ", + "plugin": "infra", + "path": "x-pack/plugins/infra/public/pages/logs/settings/validation_errors.ts" + }, { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataViewSpec", - "text": "DataViewSpec" + "plugin": "infra", + "path": "x-pack/plugins/infra/public/pages/logs/settings/validation_errors.ts" }, - ", skipFetchFields?: boolean) => Promise<", { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataView", - "text": "DataView" + "plugin": "infra", + "path": "x-pack/plugins/infra/public/pages/logs/settings/validation_errors.ts" }, - ">" - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ { - "parentPluginId": "data", - "id": "def-server.DataViewsService.create.$1", - "type": "Object", - "tags": [], - "label": "{ id, name, title, ...restOfSpec }", - "description": [], - "signature": [ - { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataViewSpec", - "text": "DataViewSpec" - } - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true + "plugin": "fleet", + "path": "x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/filter_dataset.tsx" }, { - "parentPluginId": "data", - "id": "def-server.DataViewsService.create.$2", - "type": "boolean", - "tags": [], - "label": "skipFetchFields", - "description": [ - "if true, will not fetch fields" - ], - "signature": [ - "boolean" - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [ - "DataView" - ] - }, - { - "parentPluginId": "data", - "id": "def-server.DataViewsService.createAndSave", - "type": "Function", - "tags": [], - "label": "createAndSave", - "description": [ - "\nCreate a new data view and save it right away." - ], - "signature": [ - "(spec: ", + "plugin": "fleet", + "path": "x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/filter_log_level.tsx" + }, { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataViewSpec", - "text": "DataViewSpec" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/query_bar.tsx" }, - ", override?: boolean, skipFetchFields?: boolean) => Promise<", { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataView", - "text": "DataView" + "plugin": "fleet", + "path": "x-pack/plugins/fleet/public/applications/fleet/components/search_bar.tsx" }, - ">" - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ { - "parentPluginId": "data", - "id": "def-server.DataViewsService.createAndSave.$1", - "type": "Object", - "tags": [], - "label": "spec", - "description": [ - "data view spec" - ], - "signature": [ - { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataViewSpec", - "text": "DataViewSpec" - } - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true + "plugin": "ml", + "path": "x-pack/plugins/ml/server/models/data_frame_analytics/index_patterns.ts" }, { - "parentPluginId": "data", - "id": "def-server.DataViewsService.createAndSave.$2", - "type": "boolean", - "tags": [], - "label": "override", - "description": [ - "Overwrite if existing index pattern exists." - ], - "signature": [ - "boolean" - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true + "plugin": "ml", + "path": "x-pack/plugins/ml/server/models/job_service/new_job_caps/rollup.ts" }, { - "parentPluginId": "data", - "id": "def-server.DataViewsService.createAndSave.$3", - "type": "boolean", - "tags": [], - "label": "skipFetchFields", - "description": [ - "Whether to skip field refresh step." - ], - "signature": [ - "boolean" - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "data", - "id": "def-server.DataViewsService.createSavedObject", - "type": "Function", - "tags": [], - "label": "createSavedObject", - "description": [ - "\nSave a new data view." - ], - "signature": [ - "(dataView: ", + "plugin": "ml", + "path": "x-pack/plugins/ml/server/lib/alerts/alerting_service.ts" + }, { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataView", - "text": "DataView" + "plugin": "ml", + "path": "x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.ts" }, - ", override?: boolean) => Promise<", { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataView", - "text": "DataView" + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/common/index_patterns_utils.ts" }, - ">" - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ { - "parentPluginId": "data", - "id": "def-server.DataViewsService.createSavedObject.$1", - "type": "Object", - "tags": [], - "label": "dataView", - "description": [ - "data view instance" - ], - "signature": [ - { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataView", - "text": "DataView" - } - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/common/index_patterns_utils.ts" }, { - "parentPluginId": "data", - "id": "def-server.DataViewsService.createSavedObject.$2", - "type": "boolean", - "tags": [], - "label": "override", - "description": [ - "Overwrite if existing index pattern exists" - ], - "signature": [ - "boolean" - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "data", - "id": "def-server.DataViewsService.updateSavedObject", - "type": "Function", - "tags": [], - "label": "updateSavedObject", - "description": [ - "\nSave existing data view. Will attempt to merge differences if there are conflicts." - ], - "signature": [ - "(indexPattern: ", + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/server/lib/get_fields.ts" + }, { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataView", - "text": "DataView" + "plugin": "apm", + "path": "x-pack/plugins/apm/server/routes/data_view/create_static_data_view.ts" }, - ", saveAttempts?: number, ignoreErrors?: boolean) => Promise" - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ { - "parentPluginId": "data", - "id": "def-server.DataViewsService.updateSavedObject.$1", - "type": "Object", - "tags": [], - "label": "indexPattern", - "description": [], - "signature": [ - { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataView", - "text": "DataView" - } - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true + "plugin": "graph", + "path": "x-pack/plugins/graph/public/state_management/datasource.sagas.ts" }, { - "parentPluginId": "data", - "id": "def-server.DataViewsService.updateSavedObject.$2", - "type": "number", - "tags": [], - "label": "saveAttempts", - "description": [], - "signature": [ - "number" - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true + "plugin": "graph", + "path": "x-pack/plugins/graph/public/state_management/persistence.ts" }, { - "parentPluginId": "data", - "id": "def-server.DataViewsService.updateSavedObject.$3", - "type": "boolean", - "tags": [], - "label": "ignoreErrors", - "description": [], - "signature": [ - "boolean" - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "data", - "id": "def-server.DataViewsService.delete", - "type": "Function", - "tags": [], - "label": "delete", - "description": [ - "\nDeletes an index pattern from .kibana index." - ], - "signature": [ - "(indexPatternId: string) => Promise<{}>" - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ + "plugin": "graph", + "path": "x-pack/plugins/graph/public/state_management/persistence.ts" + }, { - "parentPluginId": "data", - "id": "def-server.DataViewsService.delete.$1", - "type": "string", - "tags": [], - "label": "indexPatternId", - "description": [ - ": Id of kibana Index Pattern to delete" - ], - "signature": [ - "string" - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "data", - "id": "def-server.DataViewsService.getDefaultDataView", - "type": "Function", - "tags": [], - "label": "getDefaultDataView", - "description": [ - "\nReturns the default data view as an object.\nIf no default is found, or it is missing\nanother data view is selected as default and returned.\nIf no possible data view found to become a default returns null.\n" - ], - "signature": [ - "() => Promise<", + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/detections/components/rules/eql_query_bar/validators.ts" + }, { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataView", - "text": "DataView" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/detections/components/rules/step_define_rule/index.tsx" }, - " | null>" - ], - "path": "src/plugins/data_views/common/data_views/data_views.ts", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [ - "default data view" - ] - } - ], - "initialIsOpen": false - }, - { - "parentPluginId": "data", - "id": "def-server.IndexPatternsFetcher", - "type": "Class", - "tags": [], - "label": "IndexPatternsFetcher", - "description": [], - "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "data", - "id": "def-server.IndexPatternsFetcher.Unnamed", - "type": "Function", - "tags": [], - "label": "Constructor", - "description": [], - "signature": [ - "any" - ], - "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ { - "parentPluginId": "data", - "id": "def-server.IndexPatternsFetcher.Unnamed.$1", - "type": "Object", - "tags": [], - "label": "elasticsearchClient", - "description": [], - "signature": [ - "ElasticsearchClient" - ], - "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/index.tsx" }, { - "parentPluginId": "data", - "id": "def-server.IndexPatternsFetcher.Unnamed.$2", - "type": "boolean", - "tags": [], - "label": "allowNoIndices", - "description": [], - "signature": [ - "boolean" - ], - "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/sourcerer/routes/index.ts" + }, + { + "plugin": "stackAlerts", + "path": "x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/expressions/boundary_index_expression.tsx" + }, + { + "plugin": "stackAlerts", + "path": "x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/expressions/entity_index_expression.tsx" + }, + { + "plugin": "stackAlerts", + "path": "x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/index.tsx" + }, + { + "plugin": "stackAlerts", + "path": "x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/index.tsx" + }, + { + "plugin": "stackAlerts", + "path": "x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/index.tsx" + }, + { + "plugin": "stackAlerts", + "path": "x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/index.tsx" + }, + { + "plugin": "stackAlerts", + "path": "x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/index.tsx" + }, + { + "plugin": "stackAlerts", + "path": "x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/index.tsx" + }, + { + "plugin": "stackAlerts", + "path": "x-pack/plugins/stack_alerts/public/alert_types/es_query/expression/search_source_expression_form.tsx" + }, + { + "plugin": "synthetics", + "path": "x-pack/plugins/synthetics/public/legacy_uptime/components/overview/filter_group/filter_group.tsx" + }, + { + "plugin": "synthetics", + "path": "x-pack/plugins/synthetics/public/legacy_uptime/components/overview/alerts/monitor_expressions/filters_expression_select.tsx" + }, + { + "plugin": "timelines", + "path": "x-pack/plugins/timelines/server/search_strategy/index_fields/index.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_details/step_details_form.tsx" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/wizard/wizard.tsx" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/filter_agg/components/filter_term_form.tsx" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/hooks/use_index_data.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/hooks/use_index_data.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/hooks/use_index_data.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/hooks/use_index_data.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/hooks/use_index_data.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/hooks/use_index_data.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/hooks/use_index_data.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/hooks/use_step_define_form.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/hooks/use_step_define_form.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_form.tsx" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_form.tsx" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_form.tsx" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_form.tsx" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_summary.tsx" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_summary.tsx" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_summary.tsx" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/hooks/use_search_items/common.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/services/es_index_service.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/server/routes/api/transforms.ts" + }, + { + "plugin": "upgradeAssistant", + "path": "x-pack/plugins/upgrade_assistant/public/application/components/es_deprecation_logs/fix_deprecation_logs/external_links.tsx" + }, + { + "plugin": "ux", + "path": "x-pack/plugins/ux/public/components/app/rum_dashboard/local_uifilters/use_data_view.ts" + }, + { + "plugin": "graph", + "path": "x-pack/plugins/graph/public/state_management/datasource.test.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/infra/common/dependency_mocks/index_patterns.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/infra/common/dependency_mocks/index_patterns.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/infra/common/dependency_mocks/index_patterns.ts" + }, + { + "plugin": "maps", + "path": "x-pack/plugins/maps/public/classes/tooltips/es_tooltip_property.test.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/services/new_job_capabilities/remove_nested_field_children.test.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/common.test.ts" + }, + { + "plugin": "controls", + "path": "src/plugins/controls/public/services/data_views/data_views.story.ts" + }, + { + "plugin": "dataViewManagement", + "path": "src/plugins/data_view_management/public/components/edit_index_pattern/edit_index_pattern.tsx" + }, + { + "plugin": "dataViewManagement", + "path": "src/plugins/data_view_management/public/components/edit_index_pattern/edit_index_pattern.tsx" + }, + { + "plugin": "dataViewManagement", + "path": "src/plugins/data_view_management/public/components/field_editor/components/scripting_help/test_script.tsx" + }, + { + "plugin": "dataViewManagement", + "path": "src/plugins/data_view_management/public/components/field_editor/field_editor.tsx" + }, + { + "plugin": "dataViewManagement", + "path": "src/plugins/data_view_management/public/components/edit_index_pattern/create_edit_field/create_edit_field.tsx" + }, + { + "plugin": "inputControlVis", + "path": "src/plugins/input_control_vis/public/control/list_control_factory.ts" + }, + { + "plugin": "inputControlVis", + "path": "src/plugins/input_control_vis/public/control/range_control_factory.ts" + }, + { + "plugin": "unifiedFieldList", + "path": "src/plugins/unified_field_list/server/routes/field_stats.ts" + }, + { + "plugin": "unifiedFieldList", + "path": "src/plugins/unified_field_list/server/routes/field_stats.ts" + }, + { + "plugin": "visDefaultEditor", + "path": "src/plugins/vis_default_editor/public/components/controls/field.tsx" + }, + { + "plugin": "visDefaultEditor", + "path": "src/plugins/vis_default_editor/public/components/controls/field.tsx" + }, + { + "plugin": "visDefaultEditor", + "path": "src/plugins/vis_default_editor/public/components/agg_select.tsx" + }, + { + "plugin": "inputControlVis", + "path": "src/plugins/input_control_vis/public/test_utils/get_index_pattern_mock.ts" + }, + { + "plugin": "visTypeTimelion", + "path": "src/plugins/vis_types/timelion/public/helpers/arg_value_suggestions.ts" + }, + { + "plugin": "visTypeTimelion", + "path": "src/plugins/vis_types/timelion/public/helpers/arg_value_suggestions.ts" + }, + { + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/common/index_patterns_utils.test.ts" + }, + { + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/common/index_patterns_utils.test.ts" + }, + { + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/public/application/components/lib/convert_series_to_datatable.ts" + }, + { + "plugin": "visTypeVega", + "path": "src/plugins/vis_types/vega/public/data_model/search_api.ts" + }, + { + "plugin": "discover", + "path": "src/plugins/discover/public/application/main/hooks/use_adhoc_data_views.test.ts" + }, + { + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/public/application/components/lib/convert_series_to_datatable.test.ts" + }, + { + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/public/convert_to_lens/lib/datasource/get_datasource_info.test.ts" + }, + { + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/public/convert_to_lens/lib/datasource/get_datasource_info.test.ts" + }, + { + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/public/convert_to_lens/lib/datasource/get_datasource_info.test.ts" + }, + { + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/server/lib/search_strategies/lib/cached_index_pattern_fetcher.test.ts" + }, + { + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/server/lib/search_strategies/lib/cached_index_pattern_fetcher.test.ts" + }, + { + "plugin": "discover", + "path": "src/plugins/discover/public/application/main/components/layout/__stories__/get_layout_props.ts" + }, + { + "plugin": "dataViews", + "path": "src/plugins/data_views/common/data_views/data_views.ts" + }, + { + "plugin": "lens", + "path": "x-pack/plugins/lens/public/data_views_service/loader.test.ts" + }, + { + "plugin": "lens", + "path": "x-pack/plugins/lens/public/data_views_service/loader.test.ts" + }, + { + "plugin": "lens", + "path": "x-pack/plugins/lens/public/data_views_service/loader.test.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/sourcerer/routes/index.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/sourcerer/routes/index.ts" } - ], - "returnComment": [] + ] }, { "parentPluginId": "data", - "id": "def-server.IndexPatternsFetcher.getFieldsForWildcard", - "type": "Function", - "tags": [ - "property", - "property", - "return" - ], - "label": "getFieldsForWildcard", + "id": "def-server.DataView.fieldFormatMap", + "type": "Object", + "tags": [], + "label": "fieldFormatMap", "description": [ - "\n Get a list of field objects for an index pattern that may contain wildcards\n" + "\nMap of field formats by field name" ], "signature": [ - "(options: { pattern: string | string[]; metaFields?: string[] | undefined; fieldCapsOptions?: { allow_no_indices: boolean; } | undefined; type?: string | undefined; rollupIndex?: string | undefined; filter?: ", - "QueryDslQueryContainer", - " | undefined; }) => Promise<{ fields: ", + "{ [x: string]: ", { - "pluginId": "dataViews", - "scope": "server", - "docId": "kibDataViewsPluginApi", - "section": "def-server.FieldDescriptor", - "text": "FieldDescriptor" + "pluginId": "fieldFormats", + "scope": "common", + "docId": "kibFieldFormatsPluginApi", + "section": "def-common.SerializedFieldFormat", + "text": "SerializedFieldFormat" }, - "[]; indices: string[]; }>" + "<{}, ", + "SerializableRecord", + ">; }" ], - "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", + "path": "src/plugins/data_views/common/data_views/data_view.ts", "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "data", - "id": "def-server.IndexPatternsFetcher.getFieldsForWildcard.$1", - "type": "Object", - "tags": [], - "label": "options", - "description": [], - "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "data", - "id": "def-server.IndexPatternsFetcher.getFieldsForWildcard.$1.pattern", - "type": "CompoundType", - "tags": [], - "label": "pattern", - "description": [], - "signature": [ - "string | string[]" - ], - "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "data", - "id": "def-server.IndexPatternsFetcher.getFieldsForWildcard.$1.metaFields", - "type": "Array", - "tags": [], - "label": "metaFields", - "description": [], - "signature": [ - "string[] | undefined" - ], - "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "data", - "id": "def-server.IndexPatternsFetcher.getFieldsForWildcard.$1.fieldCapsOptions", - "type": "Object", - "tags": [], - "label": "fieldCapsOptions", - "description": [], - "signature": [ - "{ allow_no_indices: boolean; } | undefined" - ], - "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "data", - "id": "def-server.IndexPatternsFetcher.getFieldsForWildcard.$1.type", - "type": "string", - "tags": [], - "label": "type", - "description": [], - "signature": [ - "string | undefined" - ], - "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "data", - "id": "def-server.IndexPatternsFetcher.getFieldsForWildcard.$1.rollupIndex", - "type": "string", - "tags": [], - "label": "rollupIndex", - "description": [], - "signature": [ - "string | undefined" - ], - "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "data", - "id": "def-server.IndexPatternsFetcher.getFieldsForWildcard.$1.filter", - "type": "Object", - "tags": [], - "label": "filter", - "description": [], - "signature": [ - "QueryDslQueryContainer", - " | undefined" - ], - "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", - "deprecated": false, - "trackAdoption": false - } - ] - } - ], - "returnComment": [] + "trackAdoption": false }, { "parentPluginId": "data", - "id": "def-server.IndexPatternsFetcher.validatePatternListActive", - "type": "Function", - "tags": [ - "return" - ], - "label": "validatePatternListActive", + "id": "def-server.DataView.typeMeta", + "type": "Object", + "tags": [], + "label": "typeMeta", "description": [ - "\n Returns an index pattern list of only those index pattern strings in the given list that return indices\n" + "\nOnly used by rollup indices, used by rollup specific endpoint to load field list." ], "signature": [ - "(patternList: string[]) => Promise" + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.TypeMeta", + "text": "TypeMeta" + }, + " | undefined" ], - "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", + "path": "src/plugins/data_views/common/data_views/data_view.ts", "deprecated": false, - "trackAdoption": false, - "children": [ + "trackAdoption": false + }, + { + "parentPluginId": "data", + "id": "def-server.DataView.fields", + "type": "CompoundType", + "tags": [], + "label": "fields", + "description": [ + "\nField list, in extended array format" + ], + "signature": [ { - "parentPluginId": "data", - "id": "def-server.IndexPatternsFetcher.validatePatternListActive.$1", - "type": "Array", - "tags": [], - "label": "patternList", - "description": [ - "string[]" - ], - "signature": [ - "string[]" - ], - "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.IIndexPatternFieldList", + "text": "IIndexPatternFieldList" + }, + " & { toSpec: () => ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewFieldMap", + "text": "DataViewFieldMap" + }, + "; }" ], - "returnComment": [] - } - ], - "initialIsOpen": false - } - ], - "functions": [ - { - "parentPluginId": "data", - "id": "def-server.getCapabilitiesForRollupIndices", - "type": "Function", - "tags": [], - "label": "getCapabilitiesForRollupIndices", - "description": [ - "\nGet rollup job capabilities" - ], - "signature": [ - "(indices: ", - "RollupGetRollupIndexCapsResponse", - ") => ", - { - "pluginId": "dataViews", - "scope": "server", - "docId": "kibDataViewsPluginApi", - "section": "def-server.RollupIndexCapability", - "text": "RollupIndexCapability" - } - ], - "path": "src/plugins/data_views/server/fetcher/lib/map_capabilities.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "data", - "id": "def-server.getCapabilitiesForRollupIndices.$1", - "type": "Object", + "id": "def-server.DataView.timeFieldName", + "type": "string", "tags": [], - "label": "indices", + "label": "timeFieldName", "description": [ - "rollup job index capabilites" + "\nTimestamp field name" ], "signature": [ - "RollupGetRollupIndexCapsResponse" + "string | undefined" ], - "path": "src/plugins/data_views/server/fetcher/lib/map_capabilities.ts", + "path": "src/plugins/data_views/common/data_views/data_view.ts", "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [], - "initialIsOpen": false - }, - { - "parentPluginId": "data", - "id": "def-server.getEsQueryConfig", - "type": "Function", - "tags": [], - "label": "getEsQueryConfig", - "description": [], - "signature": [ - "(config: KibanaConfig) => ", - "EsQueryConfig" - ], - "path": "src/plugins/data/common/es_query/get_es_query_config.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ + "trackAdoption": false + }, { "parentPluginId": "data", - "id": "def-server.getEsQueryConfig.$1", - "type": "Object", + "id": "def-server.DataView.type", + "type": "string", "tags": [], - "label": "config", - "description": [], + "label": "type", + "description": [ + "\nType is used to identify rollup index patterns." + ], "signature": [ - "KibanaConfig" + "string | undefined" ], - "path": "src/plugins/data/common/es_query/get_es_query_config.ts", + "path": "src/plugins/data_views/common/data_views/data_view.ts", "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [], - "initialIsOpen": false - }, - { - "parentPluginId": "data", - "id": "def-server.getRequestAbortedSignal", - "type": "Function", - "tags": [], - "label": "getRequestAbortedSignal", - "description": [ - "\nA simple utility function that returns an `AbortSignal` corresponding to an `AbortController`\nwhich aborts when the given request is aborted." - ], - "signature": [ - "(aborted$: ", - "Observable", - ") => AbortSignal" - ], - "path": "src/plugins/data/server/lib/get_request_aborted_signal.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ + "trackAdoption": false + }, { "parentPluginId": "data", - "id": "def-server.getRequestAbortedSignal.$1", - "type": "Object", - "tags": [], - "label": "aborted$", - "description": [ - "The observable of abort events (usually `request.events.aborted$`)" + "id": "def-server.DataView.flattenHit", + "type": "Function", + "tags": [ + "deprecated" ], + "label": "flattenHit", + "description": [], "signature": [ - "Observable", - "" + "(hit: Record, deep?: boolean | undefined) => Record" ], - "path": "src/plugins/data/server/lib/get_request_aborted_signal.ts", - "deprecated": false, + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": true, "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [], - "initialIsOpen": false - }, - { - "parentPluginId": "data", - "id": "def-server.getTime", - "type": "Function", - "tags": [], - "label": "getTime", - "description": [], - "signature": [ - "(indexPattern: ", - { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataView", - "text": "DataView" - }, - " | undefined, timeRange: ", - "TimeRange", - ", options: { forceNow?: Date | undefined; fieldName?: string | undefined; } | undefined) => ", - "RangeFilter", - " | ", - "ScriptedRangeFilter", - " | ", - "MatchAllRangeFilter", - " | undefined" - ], - "path": "src/plugins/data/common/query/timefilter/get_time.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "data", - "id": "def-server.getTime.$1", - "type": "Object", - "tags": [], - "label": "indexPattern", - "description": [], - "signature": [ + "references": [ { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataView", - "text": "DataView" + "plugin": "dataViews", + "path": "src/plugins/data_views/common/data_views/data_view.ts" }, - " | undefined" - ], - "path": "src/plugins/data/common/query/timefilter/get_time.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": false - }, - { - "parentPluginId": "data", - "id": "def-server.getTime.$2", - "type": "Object", - "tags": [], - "label": "timeRange", - "description": [], - "signature": [ - "TimeRange" + { + "plugin": "maps", + "path": "x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx" + }, + { + "plugin": "maps", + "path": "x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx" + } ], - "path": "src/plugins/data/common/query/timefilter/get_time.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - }, - { - "parentPluginId": "data", - "id": "def-server.getTime.$3", - "type": "Object", - "tags": [], - "label": "options", - "description": [], - "path": "src/plugins/data/common/query/timefilter/get_time.ts", - "deprecated": false, - "trackAdoption": false, + "returnComment": [], "children": [ { "parentPluginId": "data", - "id": "def-server.getTime.$3.forceNow", + "id": "def-server.DataView.flattenHit.$1", "type": "Object", "tags": [], - "label": "forceNow", + "label": "hit", "description": [], "signature": [ - "Date | undefined" + "{ [x: string]: unknown[]; }" ], - "path": "src/plugins/data/common/query/timefilter/get_time.ts", + "path": "src/plugins/data_views/common/data_views/data_view.ts", "deprecated": false, "trackAdoption": false }, { "parentPluginId": "data", - "id": "def-server.getTime.$3.fieldName", - "type": "string", + "id": "def-server.DataView.flattenHit.$2", + "type": "CompoundType", "tags": [], - "label": "fieldName", + "label": "deep", "description": [], "signature": [ - "string | undefined" + "boolean | undefined" ], - "path": "src/plugins/data/common/query/timefilter/get_time.ts", + "path": "src/plugins/data_views/common/data_views/data_view.ts", "deprecated": false, "trackAdoption": false } ] - } - ], - "returnComment": [], - "initialIsOpen": false - }, - { - "parentPluginId": "data", - "id": "def-server.parseInterval", - "type": "Function", - "tags": [], - "label": "parseInterval", - "description": [], - "signature": [ - "(interval: string) => moment.Duration | null" - ], - "path": "src/plugins/data/common/search/aggs/utils/date_interval_utils/parse_interval.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ + }, { "parentPluginId": "data", - "id": "def-server.parseInterval.$1", + "id": "def-server.DataView.metaFields", + "type": "Array", + "tags": [], + "label": "metaFields", + "description": [ + "\nList of meta fields by name" + ], + "signature": [ + "string[]" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "data", + "id": "def-server.DataView.version", "type": "string", "tags": [], - "label": "interval", - "description": [], + "label": "version", + "description": [ + "\nSavedObject version" + ], "signature": [ - "string" + "string | undefined" ], - "path": "src/plugins/data/common/search/aggs/utils/date_interval_utils/parse_interval.ts", + "path": "src/plugins/data_views/common/data_views/data_view.ts", "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [], - "initialIsOpen": false - } - ], - "interfaces": [ - { - "parentPluginId": "data", - "id": "def-server.DataViewsServerPluginStart", - "type": "Interface", - "tags": [], - "label": "DataViewsServerPluginStart", - "description": [ - "\nDataViews server plugin start api" - ], - "path": "src/plugins/data_views/server/types.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ + "trackAdoption": false + }, { "parentPluginId": "data", - "id": "def-server.DataViewsServerPluginStart.dataViewsServiceFactory", - "type": "Function", + "id": "def-server.DataView.sourceFilters", + "type": "Array", "tags": [], - "label": "dataViewsServiceFactory", + "label": "sourceFilters", "description": [ - "\nReturns a DataViews service instance" + "\nArray of filters - hides fields in discover" ], "signature": [ - "(savedObjectsClient: ", - "SavedObjectsClientContract", - ", elasticsearchClient: ", - "ElasticsearchClient", - ", request?: ", - "KibanaRequest", - " | undefined, byPassCapabilities?: boolean | undefined) => Promise<", { "pluginId": "dataViews", "scope": "common", "docId": "kibDataViewsPluginApi", - "section": "def-common.DataViewsService", - "text": "DataViewsService" + "section": "def-common.SourceFilter", + "text": "SourceFilter" }, - ">" + "[] | undefined" ], - "path": "src/plugins/data_views/server/types.ts", + "path": "src/plugins/data_views/common/data_views/data_view.ts", "deprecated": false, - "trackAdoption": false, - "returnComment": [], - "children": [ - { - "parentPluginId": "data", - "id": "def-server.DataViewsServerPluginStart.dataViewsServiceFactory.$1", - "type": "Object", - "tags": [], - "label": "savedObjectsClient", - "description": [], - "signature": [ - "SavedObjectsClientContract" + "trackAdoption": false + }, + { + "parentPluginId": "data", + "id": "def-server.DataView.namespaces", + "type": "Array", + "tags": [], + "label": "namespaces", + "description": [ + "\nArray of namespace ids" + ], + "signature": [ + "string[]" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "data", + "id": "def-server.DataView.allowNoIndex", + "type": "boolean", + "tags": [], + "label": "allowNoIndex", + "description": [ + "\nPrevents errors when index pattern exists before indices" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "data", + "id": "def-server.DataView.name", + "type": "string", + "tags": [], + "label": "name", + "description": [ + "\nName of the data view. Human readable name used to differentiate data view." + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "data", + "id": "def-server.DataView.matchedIndices", + "type": "Array", + "tags": [], + "label": "matchedIndices", + "description": [], + "signature": [ + "string[]" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "data", + "id": "def-server.DataView.Unnamed", + "type": "Function", + "tags": [], + "label": "Constructor", + "description": [ + "\nconstructor" + ], + "signature": [ + "any" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-server.DataView.Unnamed.$1", + "type": "Object", + "tags": [], + "label": "config", + "description": [ + "- config data and dependencies" ], - "path": "src/plugins/data_views/server/types.ts", + "signature": [ + "DataViewDeps" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", "deprecated": false, - "trackAdoption": false - }, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "data", + "id": "def-server.DataView.getName", + "type": "Function", + "tags": [], + "label": "getName", + "description": [ + "\nGet name of Data View" + ], + "signature": [ + "() => string" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "data", + "id": "def-server.DataView.getIndexPattern", + "type": "Function", + "tags": [], + "label": "getIndexPattern", + "description": [ + "\nGet index pattern" + ], + "signature": [ + "() => string" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [ + "index pattern string" + ] + }, + { + "parentPluginId": "data", + "id": "def-server.DataView.setIndexPattern", + "type": "Function", + "tags": [], + "label": "setIndexPattern", + "description": [ + "\nSet index pattern" + ], + "signature": [ + "(indexPattern: string) => void" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ { "parentPluginId": "data", - "id": "def-server.DataViewsServerPluginStart.dataViewsServiceFactory.$2", - "type": "Object", + "id": "def-server.DataView.setIndexPattern.$1", + "type": "string", "tags": [], - "label": "elasticsearchClient", + "label": "indexPattern", "description": [], "signature": [ - "{ name: string | symbol; get: { (this: That, params: ", - "GetRequest", - " | ", - "GetRequest", - ", options?: ", - "TransportRequestOptionsWithOutMeta", - " | undefined): Promise<", - "GetResponse", - ">; (this: That, params: ", - "GetRequest", - " | ", - "GetRequest", - ", options?: ", - "TransportRequestOptionsWithMeta", - " | undefined): Promise<", - "TransportResult", - "<", - "GetResponse", - ", unknown>>; (this: That, params: ", - "GetRequest", - " | ", - "GetRequest", - ", options?: ", - "TransportRequestOptions", - " | undefined): Promise<", - "GetResponse", - ">; }; delete: { (this: That, params: ", - "DeleteRequest", - " | ", - "DeleteRequest", - ", options?: ", - "TransportRequestOptionsWithOutMeta", - " | undefined): Promise<", - "WriteResponseBase", - ">; (this: That, params: ", - "DeleteRequest", - " | ", - "DeleteRequest", - ", options?: ", - "TransportRequestOptionsWithMeta", - " | undefined): Promise<", - "TransportResult", - "<", - "WriteResponseBase", - ", unknown>>; (this: That, params: ", - "DeleteRequest", - " | ", - "DeleteRequest", - ", options?: ", - "TransportRequestOptions", - " | undefined): Promise<", - "WriteResponseBase", - ">; }; cluster: ", - "default", - "; eql: ", - "default", - "; search: { >(this: That, params?: ", - "SearchRequest", - " | ", - "SearchRequest", - " | undefined, options?: ", - "TransportRequestOptionsWithOutMeta", - " | undefined): Promise<", - "SearchResponse", - ">; >(this: That, params?: ", - "SearchRequest", - " | ", - "SearchRequest", - " | undefined, options?: ", - "TransportRequestOptionsWithMeta", - " | undefined): Promise<", - "TransportResult", - "<", - "SearchResponse", - ", unknown>>; >(this: That, params?: ", - "SearchRequest", - " | ", - "SearchRequest", - " | undefined, options?: ", - "TransportRequestOptions", - " | undefined): Promise<", - "SearchResponse", - ">; }; create: { (this: That, params: ", - "CreateRequest", - " | ", - "CreateRequest", - ", options?: ", - "TransportRequestOptionsWithOutMeta", - " | undefined): Promise<", - "WriteResponseBase", - ">; (this: That, params: ", - "CreateRequest", - " | ", - "CreateRequest", - ", options?: ", - "TransportRequestOptionsWithMeta", - " | undefined): Promise<", - "TransportResult", - "<", - "WriteResponseBase", - ", unknown>>; (this: That, params: ", - "CreateRequest", - " | ", + "string" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "data", + "id": "def-server.DataView.getOriginalSavedObjectBody", + "type": "Function", + "tags": [], + "label": "getOriginalSavedObjectBody", + "description": [ + "\nGet last saved saved object fields" + ], + "signature": [ + "() => { fieldAttrs?: string | undefined; title?: string | undefined; timeFieldName?: string | undefined; fields?: string | undefined; sourceFilters?: string | undefined; fieldFormatMap?: string | undefined; typeMeta?: string | undefined; type?: string | undefined; }" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "data", + "id": "def-server.DataView.resetOriginalSavedObjectBody", + "type": "Function", + "tags": [], + "label": "resetOriginalSavedObjectBody", + "description": [ + "\nReset last saved saved object fields. Used after saving." + ], + "signature": [ + "() => void" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "data", + "id": "def-server.DataView.getFieldAttrs", + "type": "Function", + "tags": [], + "label": "getFieldAttrs", + "description": [ + "\nReturns field attributes map" + ], + "signature": [ + "() => { [x: string]: ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.FieldAttrSet", + "text": "FieldAttrSet" + }, + "; }" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "data", + "id": "def-server.DataView.getComputedFields", + "type": "Function", + "tags": [], + "label": "getComputedFields", + "description": [ + "\nReturns scripted fields" + ], + "signature": [ + "() => { storedFields: string[]; scriptFields: Record; docvalueFields: { field: string; format: string; }[]; runtimeFields: ", + "MappingRuntimeFields", + "; }" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "data", + "id": "def-server.DataView.isPersisted", + "type": "Function", + "tags": [], + "label": "isPersisted", + "description": [], + "signature": [ + "() => boolean" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "data", + "id": "def-server.DataView.toSpec", + "type": "Function", + "tags": [], + "label": "toSpec", + "description": [ + "\nCreates static representation of the data view." + ], + "signature": [ + "(includeFields?: boolean) => ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewSpec", + "text": "DataViewSpec" + } + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-server.DataView.toSpec.$1", + "type": "boolean", + "tags": [], + "label": "includeFields", + "description": [ + "Whether or not to include the `fields` list as part of this spec. If not included, the list\nwill be fetched from Elasticsearch when instantiating a new Data View with this spec." + ], + "signature": [ + "boolean" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "data", + "id": "def-server.DataView.getSourceFiltering", + "type": "Function", + "tags": [], + "label": "getSourceFiltering", + "description": [ + "\nGet the source filtering configuration for that index." + ], + "signature": [ + "() => { excludes: string[]; }" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "data", + "id": "def-server.DataView.removeScriptedField", + "type": "Function", + "tags": [ + "deprecated" + ], + "label": "removeScriptedField", + "description": [ + "\nRemoves scripted field from field list." + ], + "signature": [ + "(fieldName: string) => void" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": true, + "trackAdoption": false, + "references": [ + { + "plugin": "dataViewManagement", + "path": "src/plugins/data_view_management/public/components/edit_index_pattern/scripted_fields_table/scripted_fields_table.tsx" + }, + { + "plugin": "dataViewManagement", + "path": "src/plugins/data_view_management/public/components/field_editor/field_editor.tsx" + }, + { + "plugin": "dataViews", + "path": "src/plugins/data_views/common/data_views/data_view.test.ts" + } + ], + "children": [ + { + "parentPluginId": "data", + "id": "def-server.DataView.removeScriptedField.$1", + "type": "string", + "tags": [], + "label": "fieldName", + "description": [ + "name of scripted field to remove" + ], + "signature": [ + "string" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "data", + "id": "def-server.DataView.getNonScriptedFields", + "type": "Function", + "tags": [ + "deprecated" + ], + "label": "getNonScriptedFields", + "description": [ + "\n" + ], + "signature": [ + "() => ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewField", + "text": "DataViewField" + }, + "[]" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": true, + "trackAdoption": false, + "references": [ + { + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts" + }, + { + "plugin": "graph", + "path": "x-pack/plugins/graph/public/services/persistence/deserialize.ts" + }, + { + "plugin": "graph", + "path": "x-pack/plugins/graph/public/state_management/datasource.test.ts" + }, + { + "plugin": "graph", + "path": "x-pack/plugins/graph/public/services/persistence/deserialize.test.ts" + }, + { + "plugin": "graph", + "path": "x-pack/plugins/graph/public/services/persistence/deserialize.test.ts" + }, + { + "plugin": "dataViewManagement", + "path": "src/plugins/data_view_management/public/components/edit_index_pattern/source_filters_table/components/table/table.tsx" + }, + { + "plugin": "dataViewManagement", + "path": "src/plugins/data_view_management/public/components/edit_index_pattern/edit_index_pattern.tsx" + }, + { + "plugin": "dataViewManagement", + "path": "src/plugins/data_view_management/public/components/edit_index_pattern/edit_index_pattern.tsx" + }, + { + "plugin": "dataViewManagement", + "path": "src/plugins/data_view_management/public/components/edit_index_pattern/edit_index_pattern.tsx" + }, + { + "plugin": "dataViews", + "path": "src/plugins/data_views/common/data_views/data_view.test.ts" + }, + { + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/public/application/lib/fetch_fields.ts" + } + ], + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "data", + "id": "def-server.DataView.getScriptedFields", + "type": "Function", + "tags": [ + "deprecated" + ], + "label": "getScriptedFields", + "description": [ + "\n" + ], + "signature": [ + "() => ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewField", + "text": "DataViewField" + }, + "[]" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": true, + "trackAdoption": false, + "references": [ + { + "plugin": "dataViews", + "path": "src/plugins/data_views/common/data_views/data_view.ts" + }, + { + "plugin": "dataViews", + "path": "src/plugins/data_views/common/data_views/data_view.ts" + }, + { + "plugin": "dataViews", + "path": "src/plugins/data_views/common/data_views/data_views.ts" + }, + { + "plugin": "dataViews", + "path": "src/plugins/data_views/server/register_index_pattern_usage_collection.ts" + }, + { + "plugin": "dataViewManagement", + "path": "src/plugins/data_view_management/public/components/edit_index_pattern/scripted_fields_table/scripted_fields_table.tsx" + }, + { + "plugin": "dataViews", + "path": "src/plugins/data_views/common/data_views/data_view.test.ts" + }, + { + "plugin": "dataViews", + "path": "src/plugins/data_views/common/data_views/data_view.test.ts" + }, + { + "plugin": "dataViews", + "path": "src/plugins/data_views/common/data_views/data_view.test.ts" + }, + { + "plugin": "dataViews", + "path": "src/plugins/data_views/common/data_views/data_view.test.ts" + }, + { + "plugin": "dataViews", + "path": "src/plugins/data_views/common/data_views/data_view.test.ts" + } + ], + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "data", + "id": "def-server.DataView.isTSDBMode", + "type": "Function", + "tags": [], + "label": "isTSDBMode", + "description": [ + "\nreturns true if dataview contains TSDB fields" + ], + "signature": [ + "() => boolean" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "data", + "id": "def-server.DataView.isTimeBased", + "type": "Function", + "tags": [], + "label": "isTimeBased", + "description": [ + "\nDoes the data view have a timestamp field?" + ], + "signature": [ + "() => this is ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.TimeBasedDataView", + "text": "TimeBasedDataView" + } + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "data", + "id": "def-server.DataView.isTimeNanosBased", + "type": "Function", + "tags": [], + "label": "isTimeNanosBased", + "description": [ + "\nDoes the data view have a timestamp field and is it a date nanos field?" + ], + "signature": [ + "() => this is ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.TimeBasedDataView", + "text": "TimeBasedDataView" + } + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "data", + "id": "def-server.DataView.getTimeField", + "type": "Function", + "tags": [], + "label": "getTimeField", + "description": [ + "\nGet timestamp field as DataViewField or return undefined" + ], + "signature": [ + "() => ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewField", + "text": "DataViewField" + }, + " | undefined" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "data", + "id": "def-server.DataView.getFieldByName", + "type": "Function", + "tags": [], + "label": "getFieldByName", + "description": [ + "\nGet field by name." + ], + "signature": [ + "(name: string) => ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewField", + "text": "DataViewField" + }, + " | undefined" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-server.DataView.getFieldByName.$1", + "type": "string", + "tags": [], + "label": "name", + "description": [ + "field name" + ], + "signature": [ + "string" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "data", + "id": "def-server.DataView.getAggregationRestrictions", + "type": "Function", + "tags": [], + "label": "getAggregationRestrictions", + "description": [ + "\nGet aggregation restrictions. Rollup fields can only perform a subset of aggregations." + ], + "signature": [ + "() => Record | undefined" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "data", + "id": "def-server.DataView.getAsSavedObjectBody", + "type": "Function", + "tags": [], + "label": "getAsSavedObjectBody", + "description": [ + "\nReturns index pattern as saved object body for saving" + ], + "signature": [ + "() => ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewAttributes", + "text": "DataViewAttributes" + } + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "data", + "id": "def-server.DataView.getFormatterForField", + "type": "Function", + "tags": [], + "label": "getFormatterForField", + "description": [ + "\nProvide a field, get its formatter" + ], + "signature": [ + "(field: ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.FieldSpec", + "text": "FieldSpec" + }, + " | ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewField", + "text": "DataViewField" + }, + ") => ", + { + "pluginId": "fieldFormats", + "scope": "common", + "docId": "kibFieldFormatsPluginApi", + "section": "def-common.FieldFormat", + "text": "FieldFormat" + } + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-server.DataView.getFormatterForField.$1", + "type": "CompoundType", + "tags": [], + "label": "field", + "description": [ + "field to get formatter for" + ], + "signature": [ + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.FieldSpec", + "text": "FieldSpec" + }, + " | ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewField", + "text": "DataViewField" + } + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "data", + "id": "def-server.DataView.addRuntimeField", + "type": "Function", + "tags": [], + "label": "addRuntimeField", + "description": [ + "\nAdd a runtime field - Appended to existing mapped field or a new field is\ncreated as appropriate." + ], + "signature": [ + "(name: string, runtimeField: ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.RuntimeField", + "text": "RuntimeField" + }, + ") => ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewField", + "text": "DataViewField" + }, + "[]" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-server.DataView.addRuntimeField.$1", + "type": "string", + "tags": [], + "label": "name", + "description": [ + "Field name" + ], + "signature": [ + "string" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "data", + "id": "def-server.DataView.addRuntimeField.$2", + "type": "Object", + "tags": [], + "label": "runtimeField", + "description": [ + "Runtime field definition" + ], + "signature": [ + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.RuntimeField", + "text": "RuntimeField" + } + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "data", + "id": "def-server.DataView.hasRuntimeField", + "type": "Function", + "tags": [], + "label": "hasRuntimeField", + "description": [ + "\nChecks if runtime field exists" + ], + "signature": [ + "(name: string) => boolean" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-server.DataView.hasRuntimeField.$1", + "type": "string", + "tags": [], + "label": "name", + "description": [ + "field name" + ], + "signature": [ + "string" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "data", + "id": "def-server.DataView.getRuntimeField", + "type": "Function", + "tags": [], + "label": "getRuntimeField", + "description": [ + "\nReturns runtime field if exists" + ], + "signature": [ + "(name: string) => ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.RuntimeField", + "text": "RuntimeField" + }, + " | null" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-server.DataView.getRuntimeField.$1", + "type": "string", + "tags": [], + "label": "name", + "description": [ + "Runtime field name" + ], + "signature": [ + "string" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "data", + "id": "def-server.DataView.getAllRuntimeFields", + "type": "Function", + "tags": [], + "label": "getAllRuntimeFields", + "description": [ + "\nGet all runtime field definitions.\nNOTE: this does not strip out runtime fields that match mapped field names" + ], + "signature": [ + "() => Record" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [ + "map of runtime field definitions by field name" + ] + }, + { + "parentPluginId": "data", + "id": "def-server.DataView.getFieldsByRuntimeFieldName", + "type": "Function", + "tags": [], + "label": "getFieldsByRuntimeFieldName", + "description": [ + "\nReturns data view fields backed by runtime fields." + ], + "signature": [ + "(name: string) => Record | undefined" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-server.DataView.getFieldsByRuntimeFieldName.$1", + "type": "string", + "tags": [], + "label": "name", + "description": [ + "runtime field name" + ], + "signature": [ + "string" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [ + "map of DataViewFields (that are runtime fields) by field name" + ] + }, + { + "parentPluginId": "data", + "id": "def-server.DataView.replaceAllRuntimeFields", + "type": "Function", + "tags": [], + "label": "replaceAllRuntimeFields", + "description": [ + "\nReplaces all existing runtime fields with new fields." + ], + "signature": [ + "(newFields: Record) => void" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-server.DataView.replaceAllRuntimeFields.$1", + "type": "Object", + "tags": [], + "label": "newFields", + "description": [ + "Map of runtime field definitions by field name" + ], + "signature": [ + "Record" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "data", + "id": "def-server.DataView.removeRuntimeField", + "type": "Function", + "tags": [], + "label": "removeRuntimeField", + "description": [ + "\nRemove a runtime field - removed from mapped field or removed unmapped\nfield as appropriate. Doesn't clear associated field attributes." + ], + "signature": [ + "(name: string) => void" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-server.DataView.removeRuntimeField.$1", + "type": "string", + "tags": [], + "label": "name", + "description": [ + "- Field name to remove" + ], + "signature": [ + "string" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "data", + "id": "def-server.DataView.getRuntimeMappings", + "type": "Function", + "tags": [], + "label": "getRuntimeMappings", + "description": [ + "\nReturn the \"runtime_mappings\" section of the ES search query." + ], + "signature": [ + "() => ", + "MappingRuntimeFields" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "data", + "id": "def-server.DataView.getFormatterForFieldNoDefault", + "type": "Function", + "tags": [], + "label": "getFormatterForFieldNoDefault", + "description": [ + "\nGet formatter for a given field name. Return undefined if none exists." + ], + "signature": [ + "(fieldname: string) => ", + { + "pluginId": "fieldFormats", + "scope": "common", + "docId": "kibFieldFormatsPluginApi", + "section": "def-common.FieldFormat", + "text": "FieldFormat" + }, + " | undefined" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-server.DataView.getFormatterForFieldNoDefault.$1", + "type": "string", + "tags": [], + "label": "fieldname", + "description": [ + "name of field to get formatter for" + ], + "signature": [ + "string" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "data", + "id": "def-server.DataView.setFieldAttrs", + "type": "Function", + "tags": [], + "label": "setFieldAttrs", + "description": [ + "\nSet field attribute" + ], + "signature": [ + "(fieldName: string, attrName: K, value: ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.FieldAttrSet", + "text": "FieldAttrSet" + }, + "[K]) => void" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-server.DataView.setFieldAttrs.$1", + "type": "string", + "tags": [], + "label": "fieldName", + "description": [ + "name of field to set attribute on" + ], + "signature": [ + "string" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "data", + "id": "def-server.DataView.setFieldAttrs.$2", + "type": "Uncategorized", + "tags": [], + "label": "attrName", + "description": [ + "name of attribute to set" + ], + "signature": [ + "K" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "data", + "id": "def-server.DataView.setFieldAttrs.$3", + "type": "Uncategorized", + "tags": [], + "label": "value", + "description": [ + "value of attribute" + ], + "signature": [ + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.FieldAttrSet", + "text": "FieldAttrSet" + }, + "[K]" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "data", + "id": "def-server.DataView.setFieldCustomLabel", + "type": "Function", + "tags": [], + "label": "setFieldCustomLabel", + "description": [ + "\nSet field custom label" + ], + "signature": [ + "(fieldName: string, customLabel: string | null | undefined) => void" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-server.DataView.setFieldCustomLabel.$1", + "type": "string", + "tags": [], + "label": "fieldName", + "description": [ + "name of field to set custom label on" + ], + "signature": [ + "string" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "data", + "id": "def-server.DataView.setFieldCustomLabel.$2", + "type": "CompoundType", + "tags": [], + "label": "customLabel", + "description": [ + "custom label value. If undefined, custom label is removed" + ], + "signature": [ + "string | null | undefined" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, + { + "parentPluginId": "data", + "id": "def-server.DataView.setFieldCount", + "type": "Function", + "tags": [], + "label": "setFieldCount", + "description": [ + "\nSet field count" + ], + "signature": [ + "(fieldName: string, count: number | null | undefined) => void" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-server.DataView.setFieldCount.$1", + "type": "string", + "tags": [], + "label": "fieldName", + "description": [ + "name of field to set count on" + ], + "signature": [ + "string" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "data", + "id": "def-server.DataView.setFieldCount.$2", + "type": "CompoundType", + "tags": [], + "label": "count", + "description": [ + "count value. If undefined, count is removed" + ], + "signature": [ + "number | null | undefined" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, + { + "parentPluginId": "data", + "id": "def-server.DataView.setFieldFormat", + "type": "Function", + "tags": [], + "label": "setFieldFormat", + "description": [ + "\nSet field formatter" + ], + "signature": [ + "(fieldName: string, format: ", + { + "pluginId": "fieldFormats", + "scope": "common", + "docId": "kibFieldFormatsPluginApi", + "section": "def-common.SerializedFieldFormat", + "text": "SerializedFieldFormat" + }, + "<{}, ", + "SerializableRecord", + ">) => void" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-server.DataView.setFieldFormat.$1", + "type": "string", + "tags": [], + "label": "fieldName", + "description": [ + "name of field to set format on" + ], + "signature": [ + "string" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "data", + "id": "def-server.DataView.setFieldFormat.$2", + "type": "Object", + "tags": [], + "label": "format", + "description": [ + "field format in serialized form" + ], + "signature": [ + { + "pluginId": "fieldFormats", + "scope": "common", + "docId": "kibFieldFormatsPluginApi", + "section": "def-common.SerializedFieldFormat", + "text": "SerializedFieldFormat" + }, + "<{}, ", + "SerializableRecord", + ">" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "data", + "id": "def-server.DataView.deleteFieldFormat", + "type": "Function", + "tags": [], + "label": "deleteFieldFormat", + "description": [ + "\nRemove field format from the field format map." + ], + "signature": [ + "(fieldName: string) => void" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-server.DataView.deleteFieldFormat.$1", + "type": "string", + "tags": [], + "label": "fieldName", + "description": [ + "field name associated with the format for removal" + ], + "signature": [ + "string" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "data", + "id": "def-server.DataViewsService", + "type": "Class", + "tags": [], + "label": "DataViewsService", + "description": [ + "\nData views service, providing CRUD operations for data views." + ], + "path": "src/plugins/data_views/common/data_views/data_views.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-server.DataViewsService.getCanSave", + "type": "Function", + "tags": [], + "label": "getCanSave", + "description": [ + "\nCan the user save data views?" + ], + "signature": [ + "() => Promise" + ], + "path": "src/plugins/data_views/common/data_views/data_views.ts", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [] + }, + { + "parentPluginId": "data", + "id": "def-server.DataViewsService.Unnamed", + "type": "Function", + "tags": [], + "label": "Constructor", + "description": [ + "\nDataViewsService constructor" + ], + "signature": [ + "any" + ], + "path": "src/plugins/data_views/common/data_views/data_views.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-server.DataViewsService.Unnamed.$1", + "type": "Object", + "tags": [], + "label": "deps", + "description": [ + "Service dependencies" + ], + "signature": [ + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewsServiceDeps", + "text": "DataViewsServiceDeps" + } + ], + "path": "src/plugins/data_views/common/data_views/data_views.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "data", + "id": "def-server.DataViewsService.getIds", + "type": "Function", + "tags": [], + "label": "getIds", + "description": [ + "\nGets list of index pattern ids." + ], + "signature": [ + "(refresh?: boolean) => Promise" + ], + "path": "src/plugins/data_views/common/data_views/data_views.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-server.DataViewsService.getIds.$1", + "type": "boolean", + "tags": [], + "label": "refresh", + "description": [ + "Force refresh of index pattern list" + ], + "signature": [ + "boolean" + ], + "path": "src/plugins/data_views/common/data_views/data_views.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "data", + "id": "def-server.DataViewsService.getTitles", + "type": "Function", + "tags": [], + "label": "getTitles", + "description": [ + "\nGets list of index pattern titles." + ], + "signature": [ + "(refresh?: boolean) => Promise" + ], + "path": "src/plugins/data_views/common/data_views/data_views.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-server.DataViewsService.getTitles.$1", + "type": "boolean", + "tags": [], + "label": "refresh", + "description": [ + "Force refresh of index pattern list" + ], + "signature": [ + "boolean" + ], + "path": "src/plugins/data_views/common/data_views/data_views.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "data", + "id": "def-server.DataViewsService.find", + "type": "Function", + "tags": [], + "label": "find", + "description": [ + "\nFind and load index patterns by title." + ], + "signature": [ + "(search: string, size?: number) => Promise<", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataView", + "text": "DataView" + }, + "[]>" + ], + "path": "src/plugins/data_views/common/data_views/data_views.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-server.DataViewsService.find.$1", + "type": "string", + "tags": [], + "label": "search", + "description": [ + "Search string" + ], + "signature": [ + "string" + ], + "path": "src/plugins/data_views/common/data_views/data_views.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "data", + "id": "def-server.DataViewsService.find.$2", + "type": "number", + "tags": [], + "label": "size", + "description": [ + "Number of data views to return" + ], + "signature": [ + "number" + ], + "path": "src/plugins/data_views/common/data_views/data_views.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [ + "DataView[]" + ] + }, + { + "parentPluginId": "data", + "id": "def-server.DataViewsService.getIdsWithTitle", + "type": "Function", + "tags": [], + "label": "getIdsWithTitle", + "description": [ + "\nGets list of index pattern ids with titles." + ], + "signature": [ + "(refresh?: boolean) => Promise<", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewListItem", + "text": "DataViewListItem" + }, + "[]>" + ], + "path": "src/plugins/data_views/common/data_views/data_views.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-server.DataViewsService.getIdsWithTitle.$1", + "type": "boolean", + "tags": [], + "label": "refresh", + "description": [ + "Force refresh of index pattern list" + ], + "signature": [ + "boolean" + ], + "path": "src/plugins/data_views/common/data_views/data_views.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "data", + "id": "def-server.DataViewsService.clearCache", + "type": "Function", + "tags": [], + "label": "clearCache", + "description": [ + "\nClear index pattern saved objects cache." + ], + "signature": [ + "() => void" + ], + "path": "src/plugins/data_views/common/data_views/data_views.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "data", + "id": "def-server.DataViewsService.clearInstanceCache", + "type": "Function", + "tags": [], + "label": "clearInstanceCache", + "description": [ + "\nClear index pattern instance cache" + ], + "signature": [ + "(id?: string | undefined) => void" + ], + "path": "src/plugins/data_views/common/data_views/data_views.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-server.DataViewsService.clearInstanceCache.$1", + "type": "string", + "tags": [], + "label": "id", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "src/plugins/data_views/common/data_views/data_views.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, + { + "parentPluginId": "data", + "id": "def-server.DataViewsService.getCache", + "type": "Function", + "tags": [], + "label": "getCache", + "description": [ + "\nGet cache, contains data view saved objects." + ], + "signature": [ + "() => Promise<", + "SavedObject", + "<", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewSavedObjectAttrs", + "text": "DataViewSavedObjectAttrs" + }, + ">[] | null | undefined>" + ], + "path": "src/plugins/data_views/common/data_views/data_views.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "data", + "id": "def-server.DataViewsService.getDefault", + "type": "Function", + "tags": [], + "label": "getDefault", + "description": [ + "\nGet default index pattern" + ], + "signature": [ + "() => Promise<", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataView", + "text": "DataView" + }, + " | null>" + ], + "path": "src/plugins/data_views/common/data_views/data_views.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "data", + "id": "def-server.DataViewsService.getDefaultId", + "type": "Function", + "tags": [], + "label": "getDefaultId", + "description": [ + "\nGet default index pattern id" + ], + "signature": [ + "() => Promise" + ], + "path": "src/plugins/data_views/common/data_views/data_views.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "data", + "id": "def-server.DataViewsService.setDefault", + "type": "Function", + "tags": [], + "label": "setDefault", + "description": [ + "\nOptionally set default index pattern, unless force = true" + ], + "signature": [ + "(id: string | null, force?: boolean) => Promise" + ], + "path": "src/plugins/data_views/common/data_views/data_views.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-server.DataViewsService.setDefault.$1", + "type": "CompoundType", + "tags": [], + "label": "id", + "description": [ + "data view id" + ], + "signature": [ + "string | null" + ], + "path": "src/plugins/data_views/common/data_views/data_views.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + }, + { + "parentPluginId": "data", + "id": "def-server.DataViewsService.setDefault.$2", + "type": "boolean", + "tags": [], + "label": "force", + "description": [ + "set default data view even if there's an existing default" + ], + "signature": [ + "boolean" + ], + "path": "src/plugins/data_views/common/data_views/data_views.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "data", + "id": "def-server.DataViewsService.hasUserDataView", + "type": "Function", + "tags": [], + "label": "hasUserDataView", + "description": [ + "\nChecks if current user has a user created index pattern ignoring fleet's server default index patterns." + ], + "signature": [ + "() => Promise" + ], + "path": "src/plugins/data_views/common/data_views/data_views.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "data", + "id": "def-server.DataViewsService.getFieldsForWildcard", + "type": "Function", + "tags": [], + "label": "getFieldsForWildcard", + "description": [ + "\nGet field list by providing { pattern }." + ], + "signature": [ + "(options: ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.GetFieldsOptions", + "text": "GetFieldsOptions" + }, + ") => Promise<", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.FieldSpec", + "text": "FieldSpec" + }, + "[]>" + ], + "path": "src/plugins/data_views/common/data_views/data_views.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-server.DataViewsService.getFieldsForWildcard.$1", + "type": "Object", + "tags": [], + "label": "options", + "description": [ + "options for getting field list" + ], + "signature": [ + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.GetFieldsOptions", + "text": "GetFieldsOptions" + } + ], + "path": "src/plugins/data_views/common/data_views/data_views.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [ + "FieldSpec[]" + ] + }, + { + "parentPluginId": "data", + "id": "def-server.DataViewsService.getFieldsForIndexPattern", + "type": "Function", + "tags": [], + "label": "getFieldsForIndexPattern", + "description": [ + "\nGet field list by providing an index patttern (or spec)." + ], + "signature": [ + "(indexPattern: ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataView", + "text": "DataView" + }, + " | ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewSpec", + "text": "DataViewSpec" + }, + ", options?: ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.GetFieldsOptions", + "text": "GetFieldsOptions" + }, + " | undefined) => Promise<", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.FieldSpec", + "text": "FieldSpec" + }, + "[]>" + ], + "path": "src/plugins/data_views/common/data_views/data_views.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-server.DataViewsService.getFieldsForIndexPattern.$1", + "type": "CompoundType", + "tags": [], + "label": "indexPattern", + "description": [], + "signature": [ + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataView", + "text": "DataView" + }, + " | ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewSpec", + "text": "DataViewSpec" + } + ], + "path": "src/plugins/data_views/common/data_views/data_views.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "data", + "id": "def-server.DataViewsService.getFieldsForIndexPattern.$2", + "type": "Object", + "tags": [], + "label": "options", + "description": [ + "options for getting field list" + ], + "signature": [ + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.GetFieldsOptions", + "text": "GetFieldsOptions" + }, + " | undefined" + ], + "path": "src/plugins/data_views/common/data_views/data_views.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [ + "FieldSpec[]" + ] + }, + { + "parentPluginId": "data", + "id": "def-server.DataViewsService.refreshFields", + "type": "Function", + "tags": [], + "label": "refreshFields", + "description": [ + "\nRefresh field list for a given index pattern." + ], + "signature": [ + "(indexPattern: ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataView", + "text": "DataView" + }, + ") => Promise" + ], + "path": "src/plugins/data_views/common/data_views/data_views.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-server.DataViewsService.refreshFields.$1", + "type": "Object", + "tags": [], + "label": "indexPattern", + "description": [], + "signature": [ + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataView", + "text": "DataView" + } + ], + "path": "src/plugins/data_views/common/data_views/data_views.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "data", + "id": "def-server.DataViewsService.fieldArrayToMap", + "type": "Function", + "tags": [], + "label": "fieldArrayToMap", + "description": [ + "\nConverts field array to map." + ], + "signature": [ + "(fields: ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.FieldSpec", + "text": "FieldSpec" + }, + "[], fieldAttrs?: ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.FieldAttrs", + "text": "FieldAttrs" + }, + " | undefined) => ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewFieldMap", + "text": "DataViewFieldMap" + } + ], + "path": "src/plugins/data_views/common/data_views/data_views.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-server.DataViewsService.fieldArrayToMap.$1", + "type": "Array", + "tags": [], + "label": "fields", + "description": [ + ": FieldSpec[]" + ], + "signature": [ + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.FieldSpec", + "text": "FieldSpec" + }, + "[]" + ], + "path": "src/plugins/data_views/common/data_views/data_views.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "data", + "id": "def-server.DataViewsService.fieldArrayToMap.$2", + "type": "Object", + "tags": [], + "label": "fieldAttrs", + "description": [ + ": FieldAttrs" + ], + "signature": [ + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.FieldAttrs", + "text": "FieldAttrs" + }, + " | undefined" + ], + "path": "src/plugins/data_views/common/data_views/data_views.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [ + "Record" + ] + }, + { + "parentPluginId": "data", + "id": "def-server.DataViewsService.savedObjectToSpec", + "type": "Function", + "tags": [], + "label": "savedObjectToSpec", + "description": [ + "\nConverts data view saved object to data view spec." + ], + "signature": [ + "(savedObject: ", + "SavedObject", + "<", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewAttributes", + "text": "DataViewAttributes" + }, + ">) => ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewSpec", + "text": "DataViewSpec" + } + ], + "path": "src/plugins/data_views/common/data_views/data_views.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-server.DataViewsService.savedObjectToSpec.$1", + "type": "Object", + "tags": [], + "label": "savedObject", + "description": [], + "signature": [ + "SavedObject", + "<", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewAttributes", + "text": "DataViewAttributes" + }, + ">" + ], + "path": "src/plugins/data_views/common/data_views/data_views.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [ + "DataViewSpec" + ] + }, + { + "parentPluginId": "data", + "id": "def-server.DataViewsService.get", + "type": "Function", + "tags": [], + "label": "get", + "description": [ + "\nGet an index pattern by id, cache optimized." + ], + "signature": [ + "(id: string) => Promise<", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataView", + "text": "DataView" + }, + ">" + ], + "path": "src/plugins/data_views/common/data_views/data_views.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-server.DataViewsService.get.$1", + "type": "string", + "tags": [], + "label": "id", + "description": [], + "signature": [ + "string" + ], + "path": "src/plugins/data_views/common/data_views/data_views.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "data", + "id": "def-server.DataViewsService.create", + "type": "Function", + "tags": [], + "label": "create", + "description": [ + "\nCreate a new data view instance." + ], + "signature": [ + "({ id, name, title, ...restOfSpec }: ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewSpec", + "text": "DataViewSpec" + }, + ", skipFetchFields?: boolean) => Promise<", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataView", + "text": "DataView" + }, + ">" + ], + "path": "src/plugins/data_views/common/data_views/data_views.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-server.DataViewsService.create.$1", + "type": "Object", + "tags": [], + "label": "{ id, name, title, ...restOfSpec }", + "description": [], + "signature": [ + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewSpec", + "text": "DataViewSpec" + } + ], + "path": "src/plugins/data_views/common/data_views/data_views.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "data", + "id": "def-server.DataViewsService.create.$2", + "type": "boolean", + "tags": [], + "label": "skipFetchFields", + "description": [ + "if true, will not fetch fields" + ], + "signature": [ + "boolean" + ], + "path": "src/plugins/data_views/common/data_views/data_views.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [ + "DataView" + ] + }, + { + "parentPluginId": "data", + "id": "def-server.DataViewsService.createAndSave", + "type": "Function", + "tags": [], + "label": "createAndSave", + "description": [ + "\nCreate a new data view and save it right away." + ], + "signature": [ + "(spec: ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewSpec", + "text": "DataViewSpec" + }, + ", override?: boolean, skipFetchFields?: boolean) => Promise<", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataView", + "text": "DataView" + }, + ">" + ], + "path": "src/plugins/data_views/common/data_views/data_views.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-server.DataViewsService.createAndSave.$1", + "type": "Object", + "tags": [], + "label": "spec", + "description": [ + "data view spec" + ], + "signature": [ + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewSpec", + "text": "DataViewSpec" + } + ], + "path": "src/plugins/data_views/common/data_views/data_views.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "data", + "id": "def-server.DataViewsService.createAndSave.$2", + "type": "boolean", + "tags": [], + "label": "override", + "description": [ + "Overwrite if existing index pattern exists." + ], + "signature": [ + "boolean" + ], + "path": "src/plugins/data_views/common/data_views/data_views.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "data", + "id": "def-server.DataViewsService.createAndSave.$3", + "type": "boolean", + "tags": [], + "label": "skipFetchFields", + "description": [ + "Whether to skip field refresh step." + ], + "signature": [ + "boolean" + ], + "path": "src/plugins/data_views/common/data_views/data_views.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "data", + "id": "def-server.DataViewsService.createSavedObject", + "type": "Function", + "tags": [], + "label": "createSavedObject", + "description": [ + "\nSave a new data view." + ], + "signature": [ + "(dataView: ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataView", + "text": "DataView" + }, + ", override?: boolean) => Promise<", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataView", + "text": "DataView" + }, + ">" + ], + "path": "src/plugins/data_views/common/data_views/data_views.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-server.DataViewsService.createSavedObject.$1", + "type": "Object", + "tags": [], + "label": "dataView", + "description": [ + "data view instance" + ], + "signature": [ + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataView", + "text": "DataView" + } + ], + "path": "src/plugins/data_views/common/data_views/data_views.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "data", + "id": "def-server.DataViewsService.createSavedObject.$2", + "type": "boolean", + "tags": [], + "label": "override", + "description": [ + "Overwrite if existing index pattern exists" + ], + "signature": [ + "boolean" + ], + "path": "src/plugins/data_views/common/data_views/data_views.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "data", + "id": "def-server.DataViewsService.updateSavedObject", + "type": "Function", + "tags": [], + "label": "updateSavedObject", + "description": [ + "\nSave existing data view. Will attempt to merge differences if there are conflicts." + ], + "signature": [ + "(indexPattern: ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataView", + "text": "DataView" + }, + ", saveAttempts?: number, ignoreErrors?: boolean) => Promise" + ], + "path": "src/plugins/data_views/common/data_views/data_views.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-server.DataViewsService.updateSavedObject.$1", + "type": "Object", + "tags": [], + "label": "indexPattern", + "description": [], + "signature": [ + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataView", + "text": "DataView" + } + ], + "path": "src/plugins/data_views/common/data_views/data_views.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "data", + "id": "def-server.DataViewsService.updateSavedObject.$2", + "type": "number", + "tags": [], + "label": "saveAttempts", + "description": [], + "signature": [ + "number" + ], + "path": "src/plugins/data_views/common/data_views/data_views.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "data", + "id": "def-server.DataViewsService.updateSavedObject.$3", + "type": "boolean", + "tags": [], + "label": "ignoreErrors", + "description": [], + "signature": [ + "boolean" + ], + "path": "src/plugins/data_views/common/data_views/data_views.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "data", + "id": "def-server.DataViewsService.delete", + "type": "Function", + "tags": [], + "label": "delete", + "description": [ + "\nDeletes an index pattern from .kibana index." + ], + "signature": [ + "(indexPatternId: string) => Promise<{}>" + ], + "path": "src/plugins/data_views/common/data_views/data_views.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-server.DataViewsService.delete.$1", + "type": "string", + "tags": [], + "label": "indexPatternId", + "description": [ + ": Id of kibana Index Pattern to delete" + ], + "signature": [ + "string" + ], + "path": "src/plugins/data_views/common/data_views/data_views.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "data", + "id": "def-server.DataViewsService.getDefaultDataView", + "type": "Function", + "tags": [], + "label": "getDefaultDataView", + "description": [ + "\nReturns the default data view as an object.\nIf no default is found, or it is missing\nanother data view is selected as default and returned.\nIf no possible data view found to become a default returns null.\n" + ], + "signature": [ + "() => Promise<", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataView", + "text": "DataView" + }, + " | null>" + ], + "path": "src/plugins/data_views/common/data_views/data_views.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [ + "default data view" + ] + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "data", + "id": "def-server.IndexPatternsFetcher", + "type": "Class", + "tags": [], + "label": "IndexPatternsFetcher", + "description": [], + "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-server.IndexPatternsFetcher.Unnamed", + "type": "Function", + "tags": [], + "label": "Constructor", + "description": [], + "signature": [ + "any" + ], + "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-server.IndexPatternsFetcher.Unnamed.$1", + "type": "Object", + "tags": [], + "label": "elasticsearchClient", + "description": [], + "signature": [ + "ElasticsearchClient" + ], + "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "data", + "id": "def-server.IndexPatternsFetcher.Unnamed.$2", + "type": "boolean", + "tags": [], + "label": "allowNoIndices", + "description": [], + "signature": [ + "boolean" + ], + "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "data", + "id": "def-server.IndexPatternsFetcher.getFieldsForWildcard", + "type": "Function", + "tags": [ + "property", + "property", + "return" + ], + "label": "getFieldsForWildcard", + "description": [ + "\n Get a list of field objects for an index pattern that may contain wildcards\n" + ], + "signature": [ + "(options: { pattern: string | string[]; metaFields?: string[] | undefined; fieldCapsOptions?: { allow_no_indices: boolean; } | undefined; type?: string | undefined; rollupIndex?: string | undefined; filter?: ", + "QueryDslQueryContainer", + " | undefined; }) => Promise<{ fields: ", + { + "pluginId": "dataViews", + "scope": "server", + "docId": "kibDataViewsPluginApi", + "section": "def-server.FieldDescriptor", + "text": "FieldDescriptor" + }, + "[]; indices: string[]; }>" + ], + "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-server.IndexPatternsFetcher.getFieldsForWildcard.$1", + "type": "Object", + "tags": [], + "label": "options", + "description": [], + "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-server.IndexPatternsFetcher.getFieldsForWildcard.$1.pattern", + "type": "CompoundType", + "tags": [], + "label": "pattern", + "description": [], + "signature": [ + "string | string[]" + ], + "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "data", + "id": "def-server.IndexPatternsFetcher.getFieldsForWildcard.$1.metaFields", + "type": "Array", + "tags": [], + "label": "metaFields", + "description": [], + "signature": [ + "string[] | undefined" + ], + "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "data", + "id": "def-server.IndexPatternsFetcher.getFieldsForWildcard.$1.fieldCapsOptions", + "type": "Object", + "tags": [], + "label": "fieldCapsOptions", + "description": [], + "signature": [ + "{ allow_no_indices: boolean; } | undefined" + ], + "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "data", + "id": "def-server.IndexPatternsFetcher.getFieldsForWildcard.$1.type", + "type": "string", + "tags": [], + "label": "type", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "data", + "id": "def-server.IndexPatternsFetcher.getFieldsForWildcard.$1.rollupIndex", + "type": "string", + "tags": [], + "label": "rollupIndex", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "data", + "id": "def-server.IndexPatternsFetcher.getFieldsForWildcard.$1.filter", + "type": "Object", + "tags": [], + "label": "filter", + "description": [], + "signature": [ + "QueryDslQueryContainer", + " | undefined" + ], + "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", + "deprecated": false, + "trackAdoption": false + } + ] + } + ], + "returnComment": [] + }, + { + "parentPluginId": "data", + "id": "def-server.IndexPatternsFetcher.validatePatternListActive", + "type": "Function", + "tags": [ + "return" + ], + "label": "validatePatternListActive", + "description": [ + "\n Returns an index pattern list of only those index pattern strings in the given list that return indices\n" + ], + "signature": [ + "(patternList: string[]) => Promise" + ], + "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-server.IndexPatternsFetcher.validatePatternListActive.$1", + "type": "Array", + "tags": [], + "label": "patternList", + "description": [ + "string[]" + ], + "signature": [ + "string[]" + ], + "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + } + ], + "initialIsOpen": false + } + ], + "functions": [ + { + "parentPluginId": "data", + "id": "def-server.getCapabilitiesForRollupIndices", + "type": "Function", + "tags": [], + "label": "getCapabilitiesForRollupIndices", + "description": [ + "\nGet rollup job capabilities" + ], + "signature": [ + "(indices: ", + "RollupGetRollupIndexCapsResponse", + ") => ", + { + "pluginId": "dataViews", + "scope": "server", + "docId": "kibDataViewsPluginApi", + "section": "def-server.RollupIndexCapability", + "text": "RollupIndexCapability" + } + ], + "path": "src/plugins/data_views/server/fetcher/lib/map_capabilities.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-server.getCapabilitiesForRollupIndices.$1", + "type": "Object", + "tags": [], + "label": "indices", + "description": [ + "rollup job index capabilites" + ], + "signature": [ + "RollupGetRollupIndexCapsResponse" + ], + "path": "src/plugins/data_views/server/fetcher/lib/map_capabilities.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "data", + "id": "def-server.getEsQueryConfig", + "type": "Function", + "tags": [], + "label": "getEsQueryConfig", + "description": [], + "signature": [ + "(config: KibanaConfig) => ", + "EsQueryConfig" + ], + "path": "src/plugins/data/common/es_query/get_es_query_config.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-server.getEsQueryConfig.$1", + "type": "Object", + "tags": [], + "label": "config", + "description": [], + "signature": [ + "KibanaConfig" + ], + "path": "src/plugins/data/common/es_query/get_es_query_config.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "data", + "id": "def-server.getRequestAbortedSignal", + "type": "Function", + "tags": [], + "label": "getRequestAbortedSignal", + "description": [ + "\nA simple utility function that returns an `AbortSignal` corresponding to an `AbortController`\nwhich aborts when the given request is aborted." + ], + "signature": [ + "(aborted$: ", + "Observable", + ") => AbortSignal" + ], + "path": "src/plugins/data/server/lib/get_request_aborted_signal.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-server.getRequestAbortedSignal.$1", + "type": "Object", + "tags": [], + "label": "aborted$", + "description": [ + "The observable of abort events (usually `request.events.aborted$`)" + ], + "signature": [ + "Observable", + "" + ], + "path": "src/plugins/data/server/lib/get_request_aborted_signal.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "data", + "id": "def-server.getTime", + "type": "Function", + "tags": [], + "label": "getTime", + "description": [], + "signature": [ + "(indexPattern: ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataView", + "text": "DataView" + }, + " | undefined, timeRange: ", + "TimeRange", + ", options: { forceNow?: Date | undefined; fieldName?: string | undefined; } | undefined) => ", + "RangeFilter", + " | ", + "ScriptedRangeFilter", + " | ", + "MatchAllRangeFilter", + " | undefined" + ], + "path": "src/plugins/data/common/query/timefilter/get_time.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-server.getTime.$1", + "type": "Object", + "tags": [], + "label": "indexPattern", + "description": [], + "signature": [ + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataView", + "text": "DataView" + }, + " | undefined" + ], + "path": "src/plugins/data/common/query/timefilter/get_time.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + }, + { + "parentPluginId": "data", + "id": "def-server.getTime.$2", + "type": "Object", + "tags": [], + "label": "timeRange", + "description": [], + "signature": [ + "TimeRange" + ], + "path": "src/plugins/data/common/query/timefilter/get_time.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "data", + "id": "def-server.getTime.$3", + "type": "Object", + "tags": [], + "label": "options", + "description": [], + "path": "src/plugins/data/common/query/timefilter/get_time.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-server.getTime.$3.forceNow", + "type": "Object", + "tags": [], + "label": "forceNow", + "description": [], + "signature": [ + "Date | undefined" + ], + "path": "src/plugins/data/common/query/timefilter/get_time.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "data", + "id": "def-server.getTime.$3.fieldName", + "type": "string", + "tags": [], + "label": "fieldName", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "src/plugins/data/common/query/timefilter/get_time.ts", + "deprecated": false, + "trackAdoption": false + } + ] + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "data", + "id": "def-server.parseInterval", + "type": "Function", + "tags": [], + "label": "parseInterval", + "description": [], + "signature": [ + "(interval: string) => moment.Duration | null" + ], + "path": "src/plugins/data/common/search/aggs/utils/date_interval_utils/parse_interval.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-server.parseInterval.$1", + "type": "string", + "tags": [], + "label": "interval", + "description": [], + "signature": [ + "string" + ], + "path": "src/plugins/data/common/search/aggs/utils/date_interval_utils/parse_interval.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + } + ], + "interfaces": [ + { + "parentPluginId": "data", + "id": "def-server.DataViewsServerPluginStart", + "type": "Interface", + "tags": [], + "label": "DataViewsServerPluginStart", + "description": [ + "\nDataViews server plugin start api" + ], + "path": "src/plugins/data_views/server/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-server.DataViewsServerPluginStart.dataViewsServiceFactory", + "type": "Function", + "tags": [], + "label": "dataViewsServiceFactory", + "description": [ + "\nReturns a DataViews service instance" + ], + "signature": [ + "(savedObjectsClient: ", + "SavedObjectsClientContract", + ", elasticsearchClient: ", + "ElasticsearchClient", + ", request?: ", + "KibanaRequest", + " | undefined, byPassCapabilities?: boolean | undefined) => Promise<", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewsService", + "text": "DataViewsService" + }, + ">" + ], + "path": "src/plugins/data_views/server/types.ts", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "data", + "id": "def-server.DataViewsServerPluginStart.dataViewsServiceFactory.$1", + "type": "Object", + "tags": [], + "label": "savedObjectsClient", + "description": [], + "signature": [ + "SavedObjectsClientContract" + ], + "path": "src/plugins/data_views/server/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "data", + "id": "def-server.DataViewsServerPluginStart.dataViewsServiceFactory.$2", + "type": "Object", + "tags": [], + "label": "elasticsearchClient", + "description": [], + "signature": [ + "{ name: string | symbol; get: { (this: That, params: ", + "GetRequest", + " | ", + "GetRequest", + ", options?: ", + "TransportRequestOptionsWithOutMeta", + " | undefined): Promise<", + "GetResponse", + ">; (this: That, params: ", + "GetRequest", + " | ", + "GetRequest", + ", options?: ", + "TransportRequestOptionsWithMeta", + " | undefined): Promise<", + "TransportResult", + "<", + "GetResponse", + ", unknown>>; (this: That, params: ", + "GetRequest", + " | ", + "GetRequest", + ", options?: ", + "TransportRequestOptions", + " | undefined): Promise<", + "GetResponse", + ">; }; delete: { (this: That, params: ", + "DeleteRequest", + " | ", + "DeleteRequest", + ", options?: ", + "TransportRequestOptionsWithOutMeta", + " | undefined): Promise<", + "WriteResponseBase", + ">; (this: That, params: ", + "DeleteRequest", + " | ", + "DeleteRequest", + ", options?: ", + "TransportRequestOptionsWithMeta", + " | undefined): Promise<", + "TransportResult", + "<", + "WriteResponseBase", + ", unknown>>; (this: That, params: ", + "DeleteRequest", + " | ", + "DeleteRequest", + ", options?: ", + "TransportRequestOptions", + " | undefined): Promise<", + "WriteResponseBase", + ">; }; cluster: ", + "default", + "; eql: ", + "default", + "; search: { >(this: That, params?: ", + "SearchRequest", + " | ", + "SearchRequest", + " | undefined, options?: ", + "TransportRequestOptionsWithOutMeta", + " | undefined): Promise<", + "SearchResponse", + ">; >(this: That, params?: ", + "SearchRequest", + " | ", + "SearchRequest", + " | undefined, options?: ", + "TransportRequestOptionsWithMeta", + " | undefined): Promise<", + "TransportResult", + "<", + "SearchResponse", + ", unknown>>; >(this: That, params?: ", + "SearchRequest", + " | ", + "SearchRequest", + " | undefined, options?: ", + "TransportRequestOptions", + " | undefined): Promise<", + "SearchResponse", + ">; }; create: { (this: That, params: ", + "CreateRequest", + " | ", + "CreateRequest", + ", options?: ", + "TransportRequestOptionsWithOutMeta", + " | undefined): Promise<", + "WriteResponseBase", + ">; (this: That, params: ", + "CreateRequest", + " | ", + "CreateRequest", + ", options?: ", + "TransportRequestOptionsWithMeta", + " | undefined): Promise<", + "TransportResult", + "<", + "WriteResponseBase", + ", unknown>>; (this: That, params: ", + "CreateRequest", + " | ", "CreateRequest", ", options?: ", "TransportRequestOptions", @@ -15691,7 +16593,9 @@ "TransportRequestOptions", " | undefined): Promise<", "UpdateResponse", - ">; }; [kInternal]: symbol | null; [kAsyncSearch]: symbol | null; [kAutoscaling]: symbol | null; [kCat]: symbol | null; [kCcr]: symbol | null; [kCluster]: symbol | null; [kDanglingIndices]: symbol | null; [kEnrich]: symbol | null; [kEql]: symbol | null; [kFeatures]: symbol | null; [kFleet]: symbol | null; [kGraph]: symbol | null; [kIlm]: symbol | null; [kIndices]: symbol | null; [kIngest]: symbol | null; [kLicense]: symbol | null; [kLogstash]: symbol | null; [kMigration]: symbol | null; [kMl]: symbol | null; [kMonitoring]: symbol | null; [kNodes]: symbol | null; [kRollup]: symbol | null; [kSearchableSnapshots]: symbol | null; [kSecurity]: symbol | null; [kShutdown]: symbol | null; [kSlm]: symbol | null; [kSnapshot]: symbol | null; [kSql]: symbol | null; [kSsl]: symbol | null; [kTasks]: symbol | null; [kTextStructure]: symbol | null; [kTransform]: symbol | null; [kWatcher]: symbol | null; [kXpack]: symbol | null; transport: ", + ">; }; asyncSearch: ", + "default", + "; [kInternal]: symbol | null; [kAsyncSearch]: symbol | null; [kAutoscaling]: symbol | null; [kCat]: symbol | null; [kCcr]: symbol | null; [kCluster]: symbol | null; [kDanglingIndices]: symbol | null; [kEnrich]: symbol | null; [kEql]: symbol | null; [kFeatures]: symbol | null; [kFleet]: symbol | null; [kGraph]: symbol | null; [kIlm]: symbol | null; [kIndices]: symbol | null; [kIngest]: symbol | null; [kLicense]: symbol | null; [kLogstash]: symbol | null; [kMigration]: symbol | null; [kMl]: symbol | null; [kMonitoring]: symbol | null; [kNodes]: symbol | null; [kRollup]: symbol | null; [kSearchableSnapshots]: symbol | null; [kSecurity]: symbol | null; [kShutdown]: symbol | null; [kSlm]: symbol | null; [kSnapshot]: symbol | null; [kSql]: symbol | null; [kSsl]: symbol | null; [kTasks]: symbol | null; [kTextStructure]: symbol | null; [kTransform]: symbol | null; [kWatcher]: symbol | null; [kXpack]: symbol | null; transport: ", "default", "; helpers: ", "default", @@ -15701,8 +16605,6 @@ "default", "; Internal: ", "default", - "; asyncSearch: ", - "default", "; autoscaling: ", "default", "; bulk: { (this: That, params: ", @@ -16717,584 +17619,1581 @@ }, { "parentPluginId": "data", - "id": "def-server.DataViewsServerPluginStart.dataViewsServiceFactory.$3", + "id": "def-server.DataViewsServerPluginStart.dataViewsServiceFactory.$3", + "type": "Object", + "tags": [], + "label": "request", + "description": [], + "signature": [ + "KibanaRequest", + " | undefined" + ], + "path": "src/plugins/data_views/server/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "data", + "id": "def-server.DataViewsServerPluginStart.dataViewsServiceFactory.$4", + "type": "CompoundType", + "tags": [], + "label": "byPassCapabilities", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "src/plugins/data_views/server/types.ts", + "deprecated": false, + "trackAdoption": false + } + ] + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "data", + "id": "def-server.FieldDescriptor", + "type": "Interface", + "tags": [], + "label": "FieldDescriptor", + "description": [], + "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-server.FieldDescriptor.aggregatable", + "type": "boolean", + "tags": [], + "label": "aggregatable", + "description": [], + "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "data", + "id": "def-server.FieldDescriptor.name", + "type": "string", + "tags": [], + "label": "name", + "description": [], + "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "data", + "id": "def-server.FieldDescriptor.readFromDocValues", + "type": "boolean", + "tags": [], + "label": "readFromDocValues", + "description": [], + "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "data", + "id": "def-server.FieldDescriptor.searchable", + "type": "boolean", + "tags": [], + "label": "searchable", + "description": [], + "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "data", + "id": "def-server.FieldDescriptor.type", + "type": "string", + "tags": [], + "label": "type", + "description": [], + "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "data", + "id": "def-server.FieldDescriptor.esTypes", + "type": "Array", + "tags": [], + "label": "esTypes", + "description": [], + "signature": [ + "string[]" + ], + "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "data", + "id": "def-server.FieldDescriptor.subType", + "type": "Object", + "tags": [], + "label": "subType", + "description": [], + "signature": [ + "FieldSubType | undefined" + ], + "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "data", + "id": "def-server.FieldDescriptor.metadata_field", + "type": "CompoundType", + "tags": [], + "label": "metadata_field", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "data", + "id": "def-server.FieldDescriptor.fixedInterval", + "type": "Array", + "tags": [], + "label": "fixedInterval", + "description": [], + "signature": [ + "string[] | undefined" + ], + "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "data", + "id": "def-server.FieldDescriptor.timeZone", + "type": "Array", + "tags": [], + "label": "timeZone", + "description": [], + "signature": [ + "string[] | undefined" + ], + "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "data", + "id": "def-server.FieldDescriptor.timeSeriesMetric", + "type": "CompoundType", + "tags": [], + "label": "timeSeriesMetric", + "description": [], + "signature": [ + "\"gauge\" | \"histogram\" | \"summary\" | \"counter\" | undefined" + ], + "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "data", + "id": "def-server.FieldDescriptor.timeSeriesDimension", + "type": "CompoundType", + "tags": [], + "label": "timeSeriesDimension", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "data", + "id": "def-server.IEsSearchRequest", + "type": "Interface", + "tags": [], + "label": "IEsSearchRequest", + "description": [], + "signature": [ + { + "pluginId": "data", + "scope": "common", + "docId": "kibDataSearchPluginApi", + "section": "def-common.IEsSearchRequest", + "text": "IEsSearchRequest" + }, + " extends ", + { + "pluginId": "data", + "scope": "common", + "docId": "kibDataSearchPluginApi", + "section": "def-common.IKibanaSearchRequest", + "text": "IKibanaSearchRequest" + }, + "<", + { + "pluginId": "data", + "scope": "common", + "docId": "kibDataSearchPluginApi", + "section": "def-common.ISearchRequestParams", + "text": "ISearchRequestParams" + }, + ">" + ], + "path": "src/plugins/data/common/search/strategies/es_search/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-server.IEsSearchRequest.indexType", + "type": "string", + "tags": [], + "label": "indexType", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "src/plugins/data/common/search/strategies/es_search/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "data", + "id": "def-server.ISearchOptions", + "type": "Interface", + "tags": [], + "label": "ISearchOptions", + "description": [], + "path": "src/plugins/data/common/search/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-server.ISearchOptions.abortSignal", + "type": "Object", + "tags": [], + "label": "abortSignal", + "description": [ + "\nAn `AbortSignal` that allows the caller of `search` to abort a search request." + ], + "signature": [ + "AbortSignal | undefined" + ], + "path": "src/plugins/data/common/search/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "data", + "id": "def-server.ISearchOptions.strategy", + "type": "string", + "tags": [], + "label": "strategy", + "description": [ + "\nUse this option to force using a specific server side search strategy. Leave empty to use the default strategy." + ], + "signature": [ + "string | undefined" + ], + "path": "src/plugins/data/common/search/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "data", + "id": "def-server.ISearchOptions.legacyHitsTotal", + "type": "CompoundType", + "tags": [], + "label": "legacyHitsTotal", + "description": [ + "\nRequest the legacy format for the total number of hits. If sending `rest_total_hits_as_int` to\nsomething other than `true`, this should be set to `false`." + ], + "signature": [ + "boolean | undefined" + ], + "path": "src/plugins/data/common/search/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "data", + "id": "def-server.ISearchOptions.sessionId", + "type": "string", + "tags": [], + "label": "sessionId", + "description": [ + "\nA session ID, grouping multiple search requests into a single session." + ], + "signature": [ + "string | undefined" + ], + "path": "src/plugins/data/common/search/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "data", + "id": "def-server.ISearchOptions.isStored", + "type": "CompoundType", + "tags": [], + "label": "isStored", + "description": [ + "\nWhether the session is already saved (i.e. sent to background)" + ], + "signature": [ + "boolean | undefined" + ], + "path": "src/plugins/data/common/search/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "data", + "id": "def-server.ISearchOptions.isSearchStored", + "type": "CompoundType", + "tags": [], + "label": "isSearchStored", + "description": [ + "\nWhether the search was successfully polled after session was saved. Search was added to a session saved object and keepAlive extended." + ], + "signature": [ + "boolean | undefined" + ], + "path": "src/plugins/data/common/search/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "data", + "id": "def-server.ISearchOptions.isRestore", + "type": "CompoundType", + "tags": [], + "label": "isRestore", + "description": [ + "\nWhether the session is restored (i.e. search requests should re-use the stored search IDs,\nrather than starting from scratch)" + ], + "signature": [ + "boolean | undefined" + ], + "path": "src/plugins/data/common/search/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "data", + "id": "def-server.ISearchOptions.executionContext", + "type": "Object", + "tags": [], + "label": "executionContext", + "description": [ + "\nRepresents a meta-information about a Kibana entity intitating a saerch request." + ], + "signature": [ + "KibanaExecutionContext", + " | undefined" + ], + "path": "src/plugins/data/common/search/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "data", + "id": "def-server.ISearchOptions.indexPattern", + "type": "Object", + "tags": [], + "label": "indexPattern", + "description": [ + "\nIndex pattern reference is used for better error messages" + ], + "signature": [ + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataView", + "text": "DataView" + }, + " | undefined" + ], + "path": "src/plugins/data/common/search/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "data", + "id": "def-server.ISearchOptions.transport", + "type": "Object", + "tags": [], + "label": "transport", + "description": [ + "\nTransportRequestOptions, other than `signal`, to pass through to the ES client.\nTo pass an abort signal, use {@link ISearchOptions.abortSignal}" + ], + "signature": [ + "Omit<", + "TransportRequestOptions", + ", \"signal\"> | undefined" + ], + "path": "src/plugins/data/common/search/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + } + ], + "enums": [ + { + "parentPluginId": "data", + "id": "def-server.ES_FIELD_TYPES", + "type": "Enum", + "tags": [], + "label": "ES_FIELD_TYPES", + "description": [], + "signature": [ + "ES_FIELD_TYPES" + ], + "path": "node_modules/@types/kbn__field-types/index.d.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "data", + "id": "def-server.KBN_FIELD_TYPES", + "type": "Enum", + "tags": [], + "label": "KBN_FIELD_TYPES", + "description": [], + "signature": [ + "KBN_FIELD_TYPES" + ], + "path": "node_modules/@types/kbn__field-types/index.d.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "data", + "id": "def-server.METRIC_TYPES", + "type": "Enum", + "tags": [], + "label": "METRIC_TYPES", + "description": [], + "path": "src/plugins/data/common/search/aggs/metrics/metric_agg_types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + } + ], + "misc": [ + { + "parentPluginId": "data", + "id": "def-server.DEFAULT_QUERY_LANGUAGE", + "type": "string", + "tags": [], + "label": "DEFAULT_QUERY_LANGUAGE", + "description": [], + "signature": [ + "\"kuery\"" + ], + "path": "src/plugins/data/common/constants.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "data", + "id": "def-server.ES_SEARCH_STRATEGY", + "type": "string", + "tags": [], + "label": "ES_SEARCH_STRATEGY", + "description": [], + "signature": [ + "\"es\"" + ], + "path": "src/plugins/data/common/search/strategies/es_search/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "data", + "id": "def-server.IEsSearchResponse", + "type": "Type", + "tags": [], + "label": "IEsSearchResponse", + "description": [], + "signature": [ + { + "pluginId": "data", + "scope": "common", + "docId": "kibDataSearchPluginApi", + "section": "def-common.IKibanaSearchResponse", + "text": "IKibanaSearchResponse" + }, + "<", + "SearchResponse", + ">>" + ], + "path": "src/plugins/data/common/search/strategies/es_search/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "data", + "id": "def-server.ParsedInterval", + "type": "Type", + "tags": [], + "label": "ParsedInterval", + "description": [], + "signature": [ + "{ value: number; unit: ", + "Unit", + "; type: \"fixed\" | \"calendar\"; }" + ], + "path": "src/plugins/data/common/search/aggs/utils/date_interval_utils/parse_es_interval.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + } + ], + "objects": [ + { + "parentPluginId": "data", + "id": "def-server.exporters", + "type": "Object", + "tags": [], + "label": "exporters", + "description": [], + "path": "src/plugins/data/server/index.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-server.exporters.datatableToCSV", + "type": "Function", + "tags": [], + "label": "datatableToCSV", + "description": [], + "signature": [ + "({ columns, rows }: ", + { + "pluginId": "expressions", + "scope": "common", + "docId": "kibExpressionsPluginApi", + "section": "def-common.Datatable", + "text": "Datatable" + }, + ", { csvSeparator, quoteValues, formatFactory, raw, escapeFormulaValues }: CSVOptions) => string" + ], + "path": "src/plugins/data/server/index.ts", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "data", + "id": "def-server.exporters.datatableToCSV.$1", "type": "Object", "tags": [], - "label": "request", + "label": "__0", "description": [], "signature": [ - "KibanaRequest", - " | undefined" + { + "pluginId": "expressions", + "scope": "common", + "docId": "kibExpressionsPluginApi", + "section": "def-common.Datatable", + "text": "Datatable" + } ], - "path": "src/plugins/data_views/server/types.ts", + "path": "src/plugins/data/common/exports/export_csv.tsx", "deprecated": false, "trackAdoption": false }, { "parentPluginId": "data", - "id": "def-server.DataViewsServerPluginStart.dataViewsServiceFactory.$4", - "type": "CompoundType", + "id": "def-server.exporters.datatableToCSV.$2", + "type": "Object", "tags": [], - "label": "byPassCapabilities", + "label": "__1", "description": [], "signature": [ - "boolean | undefined" + "CSVOptions" ], - "path": "src/plugins/data_views/server/types.ts", + "path": "src/plugins/data/common/exports/export_csv.tsx", "deprecated": false, "trackAdoption": false } ] + }, + { + "parentPluginId": "data", + "id": "def-server.exporters.CSV_MIME_TYPE", + "type": "string", + "tags": [], + "label": "CSV_MIME_TYPE", + "description": [], + "path": "src/plugins/data/server/index.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false }, { "parentPluginId": "data", - "id": "def-server.FieldDescriptor", - "type": "Interface", + "id": "def-server.search", + "type": "Object", "tags": [], - "label": "FieldDescriptor", + "label": "search", "description": [], - "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", + "path": "src/plugins/data/server/index.ts", "deprecated": false, "trackAdoption": false, "children": [ { "parentPluginId": "data", - "id": "def-server.FieldDescriptor.aggregatable", - "type": "boolean", - "tags": [], - "label": "aggregatable", - "description": [], - "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "data", - "id": "def-server.FieldDescriptor.name", - "type": "string", - "tags": [], - "label": "name", - "description": [], - "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "data", - "id": "def-server.FieldDescriptor.readFromDocValues", - "type": "boolean", - "tags": [], - "label": "readFromDocValues", - "description": [], - "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "data", - "id": "def-server.FieldDescriptor.searchable", - "type": "boolean", - "tags": [], - "label": "searchable", - "description": [], - "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "data", - "id": "def-server.FieldDescriptor.type", - "type": "string", - "tags": [], - "label": "type", - "description": [], - "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "data", - "id": "def-server.FieldDescriptor.esTypes", - "type": "Array", - "tags": [], - "label": "esTypes", - "description": [], - "signature": [ - "string[]" - ], - "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "data", - "id": "def-server.FieldDescriptor.subType", + "id": "def-server.search.aggs", "type": "Object", "tags": [], - "label": "subType", - "description": [], - "signature": [ - "FieldSubType | undefined" - ], - "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "data", - "id": "def-server.FieldDescriptor.metadata_field", - "type": "CompoundType", - "tags": [], - "label": "metadata_field", - "description": [], - "signature": [ - "boolean | undefined" - ], - "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "data", - "id": "def-server.FieldDescriptor.fixedInterval", - "type": "Array", - "tags": [], - "label": "fixedInterval", - "description": [], - "signature": [ - "string[] | undefined" - ], - "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "data", - "id": "def-server.FieldDescriptor.timeZone", - "type": "Array", - "tags": [], - "label": "timeZone", - "description": [], - "signature": [ - "string[] | undefined" - ], - "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "data", - "id": "def-server.FieldDescriptor.timeSeriesMetric", - "type": "CompoundType", - "tags": [], - "label": "timeSeriesMetric", - "description": [], - "signature": [ - "\"gauge\" | \"histogram\" | \"summary\" | \"counter\" | undefined" - ], - "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "data", - "id": "def-server.FieldDescriptor.timeSeriesDimension", - "type": "CompoundType", - "tags": [], - "label": "timeSeriesDimension", + "label": "aggs", "description": [], - "signature": [ - "boolean | undefined" - ], - "path": "src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts", + "path": "src/plugins/data/server/index.ts", "deprecated": false, - "trackAdoption": false + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-server.search.aggs.CidrMask", + "type": "Object", + "tags": [], + "label": "CidrMask", + "description": [], + "signature": [ + "typeof ", + { + "pluginId": "data", + "scope": "common", + "docId": "kibDataSearchPluginApi", + "section": "def-common.CidrMask", + "text": "CidrMask" + } + ], + "path": "src/plugins/data/server/index.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "data", + "id": "def-server.search.aggs.dateHistogramInterval", + "type": "Function", + "tags": [], + "label": "dateHistogramInterval", + "description": [], + "signature": [ + "(interval: string, shouldForceFixed?: boolean | undefined) => Interval" + ], + "path": "src/plugins/data/server/index.ts", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "data", + "id": "def-server.search.aggs.dateHistogramInterval.$1", + "type": "string", + "tags": [], + "label": "interval", + "description": [], + "path": "src/plugins/data/common/search/aggs/utils/date_interval_utils/date_histogram_interval.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "data", + "id": "def-server.search.aggs.dateHistogramInterval.$2", + "type": "CompoundType", + "tags": [], + "label": "shouldForceFixed", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "src/plugins/data/common/search/aggs/utils/date_interval_utils/date_histogram_interval.ts", + "deprecated": false, + "trackAdoption": false + } + ] + }, + { + "parentPluginId": "data", + "id": "def-server.search.aggs.IpAddress", + "type": "Object", + "tags": [], + "label": "IpAddress", + "description": [], + "signature": [ + "typeof ", + { + "pluginId": "data", + "scope": "common", + "docId": "kibDataSearchPluginApi", + "section": "def-common.IpAddress", + "text": "IpAddress" + } + ], + "path": "src/plugins/data/server/index.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "data", + "id": "def-server.search.aggs.parseInterval", + "type": "Function", + "tags": [], + "label": "parseInterval", + "description": [], + "signature": [ + "(interval: string) => moment.Duration | null" + ], + "path": "src/plugins/data/server/index.ts", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "data", + "id": "def-server.search.aggs.parseInterval.$1", + "type": "string", + "tags": [], + "label": "interval", + "description": [], + "path": "src/plugins/data/common/search/aggs/utils/date_interval_utils/parse_interval.ts", + "deprecated": false, + "trackAdoption": false + } + ] + }, + { + "parentPluginId": "data", + "id": "def-server.search.aggs.calcAutoIntervalLessThan", + "type": "Function", + "tags": [], + "label": "calcAutoIntervalLessThan", + "description": [], + "signature": [ + "(maxBucketCount: number, duration: number) => moment.Duration" + ], + "path": "src/plugins/data/server/index.ts", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "data", + "id": "def-server.search.aggs.calcAutoIntervalLessThan.$1", + "type": "number", + "tags": [], + "label": "maxBucketCount", + "description": [], + "path": "src/plugins/data/common/search/aggs/buckets/lib/time_buckets/calc_auto_interval.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "data", + "id": "def-server.search.aggs.calcAutoIntervalLessThan.$2", + "type": "number", + "tags": [], + "label": "duration", + "description": [], + "path": "src/plugins/data/common/search/aggs/buckets/lib/time_buckets/calc_auto_interval.ts", + "deprecated": false, + "trackAdoption": false + } + ] + } + ] } ], "initialIsOpen": false }, { "parentPluginId": "data", - "id": "def-server.IEsSearchRequest", - "type": "Interface", + "id": "def-server.UI_SETTINGS", + "type": "Object", + "tags": [], + "label": "UI_SETTINGS", + "description": [], + "signature": [ + "{ readonly META_FIELDS: \"metaFields\"; readonly DOC_HIGHLIGHT: \"doc_table:highlight\"; readonly QUERY_STRING_OPTIONS: \"query:queryString:options\"; readonly QUERY_ALLOW_LEADING_WILDCARDS: \"query:allowLeadingWildcards\"; readonly SEARCH_QUERY_LANGUAGE: \"search:queryLanguage\"; readonly SORT_OPTIONS: \"sort:options\"; readonly COURIER_IGNORE_FILTER_IF_FIELD_NOT_IN_INDEX: \"courier:ignoreFilterIfFieldNotInIndex\"; readonly COURIER_SET_REQUEST_PREFERENCE: \"courier:setRequestPreference\"; readonly COURIER_CUSTOM_REQUEST_PREFERENCE: \"courier:customRequestPreference\"; readonly COURIER_MAX_CONCURRENT_SHARD_REQUESTS: \"courier:maxConcurrentShardRequests\"; readonly SEARCH_INCLUDE_FROZEN: \"search:includeFrozen\"; readonly SEARCH_TIMEOUT: \"search:timeout\"; readonly HISTOGRAM_BAR_TARGET: \"histogram:barTarget\"; readonly HISTOGRAM_MAX_BARS: \"histogram:maxBars\"; readonly HISTORY_LIMIT: \"history:limit\"; readonly TIMEPICKER_REFRESH_INTERVAL_DEFAULTS: \"timepicker:refreshIntervalDefaults\"; readonly TIMEPICKER_QUICK_RANGES: \"timepicker:quickRanges\"; readonly TIMEPICKER_TIME_DEFAULTS: \"timepicker:timeDefaults\"; readonly FILTERS_PINNED_BY_DEFAULT: \"filters:pinnedByDefault\"; readonly FILTERS_EDITOR_SUGGEST_VALUES: \"filterEditor:suggestValues\"; readonly AUTOCOMPLETE_USE_TIMERANGE: \"autocomplete:useTimeRange\"; readonly AUTOCOMPLETE_VALUE_SUGGESTION_METHOD: \"autocomplete:valueSuggestionMethod\"; readonly DATE_FORMAT: \"dateFormat\"; readonly DATEFORMAT_TZ: \"dateFormat:tz\"; }" + ], + "path": "src/plugins/data/common/constants.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + } + ], + "setup": { + "parentPluginId": "data", + "id": "def-server.DataPluginSetup", + "type": "Interface", + "tags": [], + "label": "DataPluginSetup", + "description": [], + "path": "src/plugins/data/server/plugin.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-server.DataPluginSetup.search", + "type": "Object", + "tags": [], + "label": "search", + "description": [], + "signature": [ + "ISearchSetup" + ], + "path": "src/plugins/data/server/plugin.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "data", + "id": "def-server.DataPluginSetup.query", + "type": "Object", + "tags": [], + "label": "query", + "description": [], + "signature": [ + "QuerySetup" + ], + "path": "src/plugins/data/server/plugin.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "data", + "id": "def-server.DataPluginSetup.fieldFormats", + "type": "Object", + "tags": [ + "deprecated" + ], + "label": "fieldFormats", + "description": [], + "signature": [ + { + "pluginId": "fieldFormats", + "scope": "server", + "docId": "kibFieldFormatsPluginApi", + "section": "def-server.FieldFormatsSetup", + "text": "FieldFormatsSetup" + } + ], + "path": "src/plugins/data/server/plugin.ts", + "deprecated": true, + "trackAdoption": false, + "references": [] + } + ], + "lifecycle": "setup", + "initialIsOpen": true + }, + "start": { + "parentPluginId": "data", + "id": "def-server.DataPluginStart", + "type": "Interface", + "tags": [], + "label": "DataPluginStart", + "description": [], + "path": "src/plugins/data/server/plugin.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-server.DataPluginStart.search", + "type": "Object", + "tags": [], + "label": "search", + "description": [], + "signature": [ + "ISearchStart", + "<", + { + "pluginId": "data", + "scope": "common", + "docId": "kibDataSearchPluginApi", + "section": "def-common.IEsSearchRequest", + "text": "IEsSearchRequest" + }, + ", ", + { + "pluginId": "data", + "scope": "common", + "docId": "kibDataSearchPluginApi", + "section": "def-common.IEsSearchResponse", + "text": "IEsSearchResponse" + }, + ">" + ], + "path": "src/plugins/data/server/plugin.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "data", + "id": "def-server.DataPluginStart.fieldFormats", + "type": "Object", + "tags": [ + "deprecated" + ], + "label": "fieldFormats", + "description": [], + "signature": [ + { + "pluginId": "fieldFormats", + "scope": "server", + "docId": "kibFieldFormatsPluginApi", + "section": "def-server.FieldFormatsStart", + "text": "FieldFormatsStart" + } + ], + "path": "src/plugins/data/server/plugin.ts", + "deprecated": true, + "trackAdoption": false, + "references": [] + }, + { + "parentPluginId": "data", + "id": "def-server.DataPluginStart.indexPatterns", + "type": "Object", + "tags": [], + "label": "indexPatterns", + "description": [], + "signature": [ + { + "pluginId": "dataViews", + "scope": "server", + "docId": "kibDataViewsPluginApi", + "section": "def-server.DataViewsServerPluginStart", + "text": "DataViewsServerPluginStart" + } + ], + "path": "src/plugins/data/server/plugin.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "data", + "id": "def-server.DataPluginStart.datatableUtilities", + "type": "Object", + "tags": [], + "label": "datatableUtilities", + "description": [ + "\nDatatable type utility functions." + ], + "signature": [ + "DatatableUtilitiesService" + ], + "path": "src/plugins/data/server/plugin.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "lifecycle": "start", + "initialIsOpen": true + } + }, + "common": { + "classes": [ + { + "parentPluginId": "data", + "id": "def-common.DatatableUtilitiesService", + "type": "Class", "tags": [], - "label": "IEsSearchRequest", + "label": "DatatableUtilitiesService", "description": [], - "signature": [ - { - "pluginId": "data", - "scope": "common", - "docId": "kibDataSearchPluginApi", - "section": "def-common.IEsSearchRequest", - "text": "IEsSearchRequest" - }, - " extends ", - { - "pluginId": "data", - "scope": "common", - "docId": "kibDataSearchPluginApi", - "section": "def-common.IKibanaSearchRequest", - "text": "IKibanaSearchRequest" - }, - "<", - { - "pluginId": "data", - "scope": "common", - "docId": "kibDataSearchPluginApi", - "section": "def-common.ISearchRequestParams", - "text": "ISearchRequestParams" - }, - ">" - ], - "path": "src/plugins/data/common/search/strategies/es_search/types.ts", + "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", "deprecated": false, "trackAdoption": false, "children": [ { "parentPluginId": "data", - "id": "def-server.IEsSearchRequest.indexType", - "type": "string", + "id": "def-common.DatatableUtilitiesService.Unnamed", + "type": "Function", "tags": [], - "label": "indexType", + "label": "Constructor", "description": [], "signature": [ - "string | undefined" + "any" ], - "path": "src/plugins/data/common/search/strategies/es_search/types.ts", + "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", "deprecated": false, - "trackAdoption": false - } - ], - "initialIsOpen": false - }, - { - "parentPluginId": "data", - "id": "def-server.ISearchOptions", - "type": "Interface", - "tags": [], - "label": "ISearchOptions", - "description": [], - "path": "src/plugins/data/common/search/types.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "data", - "id": "def-server.ISearchOptions.abortSignal", - "type": "Object", - "tags": [], - "label": "abortSignal", - "description": [ - "\nAn `AbortSignal` that allows the caller of `search` to abort a search request." - ], - "signature": [ - "AbortSignal | undefined" + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-common.DatatableUtilitiesService.Unnamed.$1", + "type": "Object", + "tags": [], + "label": "aggs", + "description": [], + "signature": [ + { + "pluginId": "data", + "scope": "common", + "docId": "kibDataSearchPluginApi", + "section": "def-common.AggsCommonStart", + "text": "AggsCommonStart" + } + ], + "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "data", + "id": "def-common.DatatableUtilitiesService.Unnamed.$2", + "type": "Object", + "tags": [], + "label": "dataViews", + "description": [], + "signature": [ + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewsContract", + "text": "DataViewsContract" + } + ], + "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "data", + "id": "def-common.DatatableUtilitiesService.Unnamed.$3", + "type": "Object", + "tags": [], + "label": "fieldFormats", + "description": [], + "signature": [ + { + "pluginId": "fieldFormats", + "scope": "common", + "docId": "kibFieldFormatsPluginApi", + "section": "def-common.FieldFormatsStartCommon", + "text": "FieldFormatsStartCommon" + } + ], + "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } ], - "path": "src/plugins/data/common/search/types.ts", - "deprecated": false, - "trackAdoption": false + "returnComment": [] }, { "parentPluginId": "data", - "id": "def-server.ISearchOptions.strategy", - "type": "string", + "id": "def-common.DatatableUtilitiesService.clearField", + "type": "Function", "tags": [], - "label": "strategy", - "description": [ - "\nUse this option to force using a specific server side search strategy. Leave empty to use the default strategy." - ], + "label": "clearField", + "description": [], "signature": [ - "string | undefined" + "(column: ", + { + "pluginId": "expressions", + "scope": "common", + "docId": "kibExpressionsPluginApi", + "section": "def-common.DatatableColumn", + "text": "DatatableColumn" + }, + ") => void" ], - "path": "src/plugins/data/common/search/types.ts", + "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", "deprecated": false, - "trackAdoption": false + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-common.DatatableUtilitiesService.clearField.$1", + "type": "Object", + "tags": [], + "label": "column", + "description": [], + "signature": [ + { + "pluginId": "expressions", + "scope": "common", + "docId": "kibExpressionsPluginApi", + "section": "def-common.DatatableColumn", + "text": "DatatableColumn" + } + ], + "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] }, { "parentPluginId": "data", - "id": "def-server.ISearchOptions.legacyHitsTotal", - "type": "CompoundType", + "id": "def-common.DatatableUtilitiesService.clearFieldFormat", + "type": "Function", "tags": [], - "label": "legacyHitsTotal", - "description": [ - "\nRequest the legacy format for the total number of hits. If sending `rest_total_hits_as_int` to\nsomething other than `true`, this should be set to `false`." - ], + "label": "clearFieldFormat", + "description": [], "signature": [ - "boolean | undefined" + "(column: ", + { + "pluginId": "expressions", + "scope": "common", + "docId": "kibExpressionsPluginApi", + "section": "def-common.DatatableColumn", + "text": "DatatableColumn" + }, + ") => void" + ], + "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-common.DatatableUtilitiesService.clearFieldFormat.$1", + "type": "Object", + "tags": [], + "label": "column", + "description": [], + "signature": [ + { + "pluginId": "expressions", + "scope": "common", + "docId": "kibExpressionsPluginApi", + "section": "def-common.DatatableColumn", + "text": "DatatableColumn" + } + ], + "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } ], - "path": "src/plugins/data/common/search/types.ts", - "deprecated": false, - "trackAdoption": false + "returnComment": [] }, { "parentPluginId": "data", - "id": "def-server.ISearchOptions.sessionId", - "type": "string", + "id": "def-common.DatatableUtilitiesService.getAggConfig", + "type": "Function", "tags": [], - "label": "sessionId", - "description": [ - "\nA session ID, grouping multiple search requests into a single session." - ], + "label": "getAggConfig", + "description": [], "signature": [ - "string | undefined" + "(column: ", + { + "pluginId": "expressions", + "scope": "common", + "docId": "kibExpressionsPluginApi", + "section": "def-common.DatatableColumn", + "text": "DatatableColumn" + }, + ") => Promise<", + { + "pluginId": "data", + "scope": "common", + "docId": "kibDataSearchPluginApi", + "section": "def-common.AggConfig", + "text": "AggConfig" + }, + " | undefined>" ], - "path": "src/plugins/data/common/search/types.ts", + "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", "deprecated": false, - "trackAdoption": false + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-common.DatatableUtilitiesService.getAggConfig.$1", + "type": "Object", + "tags": [], + "label": "column", + "description": [], + "signature": [ + { + "pluginId": "expressions", + "scope": "common", + "docId": "kibExpressionsPluginApi", + "section": "def-common.DatatableColumn", + "text": "DatatableColumn" + } + ], + "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] }, { "parentPluginId": "data", - "id": "def-server.ISearchOptions.isStored", - "type": "CompoundType", + "id": "def-common.DatatableUtilitiesService.getDateHistogramMeta", + "type": "Function", "tags": [], - "label": "isStored", + "label": "getDateHistogramMeta", "description": [ - "\nWhether the session is already saved (i.e. sent to background)" + "\nHelper function returning the used interval, used time zone and applied time filters for data table column created by the date_histogramm agg type.\n\"auto\" will get expanded to the actually used interval.\nIf the column is not a column created by a date_histogram aggregation of the esaggs data source,\nthis function will return undefined." ], "signature": [ - "boolean | undefined" + "(column: ", + { + "pluginId": "expressions", + "scope": "common", + "docId": "kibExpressionsPluginApi", + "section": "def-common.DatatableColumn", + "text": "DatatableColumn" + }, + ", defaults?: Partial<{ timeZone: string; }>) => DateHistogramMeta | undefined" ], - "path": "src/plugins/data/common/search/types.ts", + "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", "deprecated": false, - "trackAdoption": false + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-common.DatatableUtilitiesService.getDateHistogramMeta.$1", + "type": "Object", + "tags": [], + "label": "column", + "description": [], + "signature": [ + { + "pluginId": "expressions", + "scope": "common", + "docId": "kibExpressionsPluginApi", + "section": "def-common.DatatableColumn", + "text": "DatatableColumn" + } + ], + "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "data", + "id": "def-common.DatatableUtilitiesService.getDateHistogramMeta.$2", + "type": "Object", + "tags": [], + "label": "defaults", + "description": [], + "signature": [ + "Partial<{ timeZone: string; }>" + ], + "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] }, { "parentPluginId": "data", - "id": "def-server.ISearchOptions.isSearchStored", - "type": "CompoundType", + "id": "def-common.DatatableUtilitiesService.getDataView", + "type": "Function", "tags": [], - "label": "isSearchStored", - "description": [ - "\nWhether the search was successfully polled after session was saved. Search was added to a session saved object and keepAlive extended." - ], + "label": "getDataView", + "description": [], "signature": [ - "boolean | undefined" + "(column: ", + { + "pluginId": "expressions", + "scope": "common", + "docId": "kibExpressionsPluginApi", + "section": "def-common.DatatableColumn", + "text": "DatatableColumn" + }, + ") => Promise<", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataView", + "text": "DataView" + }, + " | undefined>" ], - "path": "src/plugins/data/common/search/types.ts", + "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", "deprecated": false, - "trackAdoption": false + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-common.DatatableUtilitiesService.getDataView.$1", + "type": "Object", + "tags": [], + "label": "column", + "description": [], + "signature": [ + { + "pluginId": "expressions", + "scope": "common", + "docId": "kibExpressionsPluginApi", + "section": "def-common.DatatableColumn", + "text": "DatatableColumn" + } + ], + "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] }, { "parentPluginId": "data", - "id": "def-server.ISearchOptions.isRestore", - "type": "CompoundType", + "id": "def-common.DatatableUtilitiesService.getField", + "type": "Function", "tags": [], - "label": "isRestore", - "description": [ - "\nWhether the session is restored (i.e. search requests should re-use the stored search IDs,\nrather than starting from scratch)" - ], + "label": "getField", + "description": [], "signature": [ - "boolean | undefined" + "(column: ", + { + "pluginId": "expressions", + "scope": "common", + "docId": "kibExpressionsPluginApi", + "section": "def-common.DatatableColumn", + "text": "DatatableColumn" + }, + ") => Promise<", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewField", + "text": "DataViewField" + }, + " | undefined>" ], - "path": "src/plugins/data/common/search/types.ts", + "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", "deprecated": false, - "trackAdoption": false + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-common.DatatableUtilitiesService.getField.$1", + "type": "Object", + "tags": [], + "label": "column", + "description": [], + "signature": [ + { + "pluginId": "expressions", + "scope": "common", + "docId": "kibExpressionsPluginApi", + "section": "def-common.DatatableColumn", + "text": "DatatableColumn" + } + ], + "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] }, { "parentPluginId": "data", - "id": "def-server.ISearchOptions.executionContext", - "type": "Object", + "id": "def-common.DatatableUtilitiesService.getFieldFormat", + "type": "Function", "tags": [], - "label": "executionContext", - "description": [ - "\nRepresents a meta-information about a Kibana entity intitating a saerch request." - ], + "label": "getFieldFormat", + "description": [], "signature": [ - "KibanaExecutionContext", + "(column: ", + { + "pluginId": "expressions", + "scope": "common", + "docId": "kibExpressionsPluginApi", + "section": "def-common.DatatableColumn", + "text": "DatatableColumn" + }, + ") => ", + { + "pluginId": "fieldFormats", + "scope": "common", + "docId": "kibFieldFormatsPluginApi", + "section": "def-common.FieldFormat", + "text": "FieldFormat" + }, " | undefined" ], - "path": "src/plugins/data/common/search/types.ts", + "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", "deprecated": false, - "trackAdoption": false + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-common.DatatableUtilitiesService.getFieldFormat.$1", + "type": "Object", + "tags": [], + "label": "column", + "description": [], + "signature": [ + { + "pluginId": "expressions", + "scope": "common", + "docId": "kibExpressionsPluginApi", + "section": "def-common.DatatableColumn", + "text": "DatatableColumn" + } + ], + "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] }, { "parentPluginId": "data", - "id": "def-server.ISearchOptions.indexPattern", - "type": "Object", + "id": "def-common.DatatableUtilitiesService.getInterval", + "type": "Function", "tags": [], - "label": "indexPattern", - "description": [ - "\nIndex pattern reference is used for better error messages" - ], + "label": "getInterval", + "description": [], "signature": [ + "(column: ", { - "pluginId": "dataViews", + "pluginId": "expressions", "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataView", - "text": "DataView" + "docId": "kibExpressionsPluginApi", + "section": "def-common.DatatableColumn", + "text": "DatatableColumn" }, - " | undefined" + ") => string | undefined" ], - "path": "src/plugins/data/common/search/types.ts", + "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", "deprecated": false, - "trackAdoption": false + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-common.DatatableUtilitiesService.getInterval.$1", + "type": "Object", + "tags": [], + "label": "column", + "description": [], + "signature": [ + { + "pluginId": "expressions", + "scope": "common", + "docId": "kibExpressionsPluginApi", + "section": "def-common.DatatableColumn", + "text": "DatatableColumn" + } + ], + "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] }, { "parentPluginId": "data", - "id": "def-server.ISearchOptions.transport", - "type": "Object", + "id": "def-common.DatatableUtilitiesService.getNumberHistogramInterval", + "type": "Function", "tags": [], - "label": "transport", + "label": "getNumberHistogramInterval", "description": [ - "\nTransportRequestOptions, other than `signal`, to pass through to the ES client.\nTo pass an abort signal, use {@link ISearchOptions.abortSignal}" + "\nHelper function returning the used interval for data table column created by the histogramm agg type.\n\"auto\" will get expanded to the actually used interval.\nIf the column is not a column created by a histogram aggregation of the esaggs data source,\nthis function will return undefined." ], "signature": [ - "Omit<", - "TransportRequestOptions", - ", \"signal\"> | undefined" + "(column: ", + { + "pluginId": "expressions", + "scope": "common", + "docId": "kibExpressionsPluginApi", + "section": "def-common.DatatableColumn", + "text": "DatatableColumn" + }, + ") => number | undefined" ], - "path": "src/plugins/data/common/search/types.ts", + "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", "deprecated": false, - "trackAdoption": false - } - ], - "initialIsOpen": false - } - ], - "enums": [ - { - "parentPluginId": "data", - "id": "def-server.ES_FIELD_TYPES", - "type": "Enum", - "tags": [], - "label": "ES_FIELD_TYPES", - "description": [], - "signature": [ - "ES_FIELD_TYPES" - ], - "path": "node_modules/@types/kbn__field-types/index.d.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - }, - { - "parentPluginId": "data", - "id": "def-server.KBN_FIELD_TYPES", - "type": "Enum", - "tags": [], - "label": "KBN_FIELD_TYPES", - "description": [], - "signature": [ - "KBN_FIELD_TYPES" - ], - "path": "node_modules/@types/kbn__field-types/index.d.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - }, - { - "parentPluginId": "data", - "id": "def-server.METRIC_TYPES", - "type": "Enum", - "tags": [], - "label": "METRIC_TYPES", - "description": [], - "path": "src/plugins/data/common/search/aggs/metrics/metric_agg_types.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - } - ], - "misc": [ - { - "parentPluginId": "data", - "id": "def-server.DEFAULT_QUERY_LANGUAGE", - "type": "string", - "tags": [], - "label": "DEFAULT_QUERY_LANGUAGE", - "description": [], - "signature": [ - "\"kuery\"" - ], - "path": "src/plugins/data/common/constants.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - }, - { - "parentPluginId": "data", - "id": "def-server.ES_SEARCH_STRATEGY", - "type": "string", - "tags": [], - "label": "ES_SEARCH_STRATEGY", - "description": [], - "signature": [ - "\"es\"" - ], - "path": "src/plugins/data/common/search/strategies/es_search/types.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - }, - { - "parentPluginId": "data", - "id": "def-server.IEsSearchResponse", - "type": "Type", - "tags": [], - "label": "IEsSearchResponse", - "description": [], - "signature": [ - { - "pluginId": "data", - "scope": "common", - "docId": "kibDataSearchPluginApi", - "section": "def-common.IKibanaSearchResponse", - "text": "IKibanaSearchResponse" - }, - "<", - "SearchResponse", - ">>" - ], - "path": "src/plugins/data/common/search/strategies/es_search/types.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - }, - { - "parentPluginId": "data", - "id": "def-server.ParsedInterval", - "type": "Type", - "tags": [], - "label": "ParsedInterval", - "description": [], - "signature": [ - "{ value: number; unit: ", - "Unit", - "; type: \"fixed\" | \"calendar\"; }" - ], - "path": "src/plugins/data/common/search/aggs/utils/date_interval_utils/parse_es_interval.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - } - ], - "objects": [ - { - "parentPluginId": "data", - "id": "def-server.exporters", - "type": "Object", - "tags": [], - "label": "exporters", - "description": [], - "path": "src/plugins/data/server/index.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-common.DatatableUtilitiesService.getNumberHistogramInterval.$1", + "type": "Object", + "tags": [], + "label": "column", + "description": [], + "signature": [ + { + "pluginId": "expressions", + "scope": "common", + "docId": "kibExpressionsPluginApi", + "section": "def-common.DatatableColumn", + "text": "DatatableColumn" + } + ], + "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, { "parentPluginId": "data", - "id": "def-server.exporters.datatableToCSV", + "id": "def-common.DatatableUtilitiesService.getTotalCount", "type": "Function", "tags": [], - "label": "datatableToCSV", + "label": "getTotalCount", "description": [], "signature": [ - "({ columns, rows }: ", + "(table: ", { "pluginId": "expressions", "scope": "common", @@ -17302,19 +19201,18 @@ "section": "def-common.Datatable", "text": "Datatable" }, - ", { csvSeparator, quoteValues, formatFactory, raw, escapeFormulaValues }: CSVOptions) => string" + ") => number | undefined" ], - "path": "src/plugins/data/server/index.ts", + "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", "deprecated": false, "trackAdoption": false, - "returnComment": [], "children": [ { "parentPluginId": "data", - "id": "def-server.exporters.datatableToCSV.$1", + "id": "def-common.DatatableUtilitiesService.getTotalCount.$1", "type": "Object", "tags": [], - "label": "__0", + "label": "table", "description": [], "signature": [ { @@ -17325,1233 +19223,1085 @@ "text": "Datatable" } ], - "path": "src/plugins/data/common/exports/export_csv.tsx", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "data", - "id": "def-server.exporters.datatableToCSV.$2", - "type": "Object", - "tags": [], - "label": "__1", - "description": [], - "signature": [ - "CSVOptions" - ], - "path": "src/plugins/data/common/exports/export_csv.tsx", + "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", "deprecated": false, - "trackAdoption": false + "trackAdoption": false, + "isRequired": true } - ] + ], + "returnComment": [] }, { "parentPluginId": "data", - "id": "def-server.exporters.CSV_MIME_TYPE", - "type": "string", - "tags": [], - "label": "CSV_MIME_TYPE", - "description": [], - "path": "src/plugins/data/server/index.ts", - "deprecated": false, - "trackAdoption": false - } - ], - "initialIsOpen": false - }, - { - "parentPluginId": "data", - "id": "def-server.search", - "type": "Object", - "tags": [], - "label": "search", - "description": [], - "path": "src/plugins/data/server/index.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "data", - "id": "def-server.search.aggs", - "type": "Object", + "id": "def-common.DatatableUtilitiesService.hasPrecisionError", + "type": "Function", "tags": [], - "label": "aggs", + "label": "hasPrecisionError", "description": [], - "path": "src/plugins/data/server/index.ts", + "signature": [ + "(column: ", + { + "pluginId": "expressions", + "scope": "common", + "docId": "kibExpressionsPluginApi", + "section": "def-common.DatatableColumn", + "text": "DatatableColumn" + }, + ") => ", + "Serializable" + ], + "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", "deprecated": false, "trackAdoption": false, "children": [ { "parentPluginId": "data", - "id": "def-server.search.aggs.CidrMask", + "id": "def-common.DatatableUtilitiesService.hasPrecisionError.$1", "type": "Object", "tags": [], - "label": "CidrMask", + "label": "column", "description": [], "signature": [ - "typeof ", { - "pluginId": "data", + "pluginId": "expressions", "scope": "common", - "docId": "kibDataSearchPluginApi", - "section": "def-common.CidrMask", - "text": "CidrMask" + "docId": "kibExpressionsPluginApi", + "section": "def-common.DatatableColumn", + "text": "DatatableColumn" } ], - "path": "src/plugins/data/server/index.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "data", - "id": "def-server.search.aggs.dateHistogramInterval", - "type": "Function", - "tags": [], - "label": "dateHistogramInterval", - "description": [], - "signature": [ - "(interval: string, shouldForceFixed?: boolean | undefined) => Interval" - ], - "path": "src/plugins/data/server/index.ts", + "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", "deprecated": false, "trackAdoption": false, - "returnComment": [], - "children": [ - { - "parentPluginId": "data", - "id": "def-server.search.aggs.dateHistogramInterval.$1", - "type": "string", - "tags": [], - "label": "interval", - "description": [], - "path": "src/plugins/data/common/search/aggs/utils/date_interval_utils/date_histogram_interval.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "data", - "id": "def-server.search.aggs.dateHistogramInterval.$2", - "type": "CompoundType", - "tags": [], - "label": "shouldForceFixed", - "description": [], - "signature": [ - "boolean | undefined" - ], - "path": "src/plugins/data/common/search/aggs/utils/date_interval_utils/date_histogram_interval.ts", - "deprecated": false, - "trackAdoption": false - } - ] + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "data", + "id": "def-common.DatatableUtilitiesService.isFilterable", + "type": "Function", + "tags": [], + "label": "isFilterable", + "description": [], + "signature": [ + "(column: ", + { + "pluginId": "expressions", + "scope": "common", + "docId": "kibExpressionsPluginApi", + "section": "def-common.DatatableColumn", + "text": "DatatableColumn" }, + ") => boolean" + ], + "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ { "parentPluginId": "data", - "id": "def-server.search.aggs.IpAddress", + "id": "def-common.DatatableUtilitiesService.isFilterable.$1", "type": "Object", "tags": [], - "label": "IpAddress", + "label": "column", "description": [], "signature": [ - "typeof ", { - "pluginId": "data", + "pluginId": "expressions", "scope": "common", - "docId": "kibDataSearchPluginApi", - "section": "def-common.IpAddress", - "text": "IpAddress" + "docId": "kibExpressionsPluginApi", + "section": "def-common.DatatableColumn", + "text": "DatatableColumn" } ], - "path": "src/plugins/data/server/index.ts", + "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", "deprecated": false, - "trackAdoption": false + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "data", + "id": "def-common.DatatableUtilitiesService.setFieldFormat", + "type": "Function", + "tags": [], + "label": "setFieldFormat", + "description": [], + "signature": [ + "(column: ", + { + "pluginId": "expressions", + "scope": "common", + "docId": "kibExpressionsPluginApi", + "section": "def-common.DatatableColumn", + "text": "DatatableColumn" + }, + ", fieldFormat: ", + { + "pluginId": "fieldFormats", + "scope": "common", + "docId": "kibFieldFormatsPluginApi", + "section": "def-common.FieldFormat", + "text": "FieldFormat" }, + ") => void" + ], + "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ { "parentPluginId": "data", - "id": "def-server.search.aggs.parseInterval", - "type": "Function", + "id": "def-common.DatatableUtilitiesService.setFieldFormat.$1", + "type": "Object", "tags": [], - "label": "parseInterval", + "label": "column", "description": [], "signature": [ - "(interval: string) => moment.Duration | null" - ], - "path": "src/plugins/data/server/index.ts", - "deprecated": false, - "trackAdoption": false, - "returnComment": [], - "children": [ { - "parentPluginId": "data", - "id": "def-server.search.aggs.parseInterval.$1", - "type": "string", - "tags": [], - "label": "interval", - "description": [], - "path": "src/plugins/data/common/search/aggs/utils/date_interval_utils/parse_interval.ts", - "deprecated": false, - "trackAdoption": false + "pluginId": "expressions", + "scope": "common", + "docId": "kibExpressionsPluginApi", + "section": "def-common.DatatableColumn", + "text": "DatatableColumn" } - ] + ], + "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true }, { "parentPluginId": "data", - "id": "def-server.search.aggs.calcAutoIntervalLessThan", - "type": "Function", + "id": "def-common.DatatableUtilitiesService.setFieldFormat.$2", + "type": "Object", "tags": [], - "label": "calcAutoIntervalLessThan", + "label": "fieldFormat", "description": [], "signature": [ - "(maxBucketCount: number, duration: number) => moment.Duration" + { + "pluginId": "fieldFormats", + "scope": "common", + "docId": "kibFieldFormatsPluginApi", + "section": "def-common.FieldFormat", + "text": "FieldFormat" + } ], - "path": "src/plugins/data/server/index.ts", + "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", "deprecated": false, "trackAdoption": false, - "returnComment": [], - "children": [ - { - "parentPluginId": "data", - "id": "def-server.search.aggs.calcAutoIntervalLessThan.$1", - "type": "number", - "tags": [], - "label": "maxBucketCount", - "description": [], - "path": "src/plugins/data/common/search/aggs/buckets/lib/time_buckets/calc_auto_interval.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "data", - "id": "def-server.search.aggs.calcAutoIntervalLessThan.$2", - "type": "number", - "tags": [], - "label": "duration", - "description": [], - "path": "src/plugins/data/common/search/aggs/buckets/lib/time_buckets/calc_auto_interval.ts", - "deprecated": false, - "trackAdoption": false - } - ] + "isRequired": true } - ] + ], + "returnComment": [] } ], "initialIsOpen": false }, { "parentPluginId": "data", - "id": "def-server.UI_SETTINGS", - "type": "Object", - "tags": [], - "label": "UI_SETTINGS", - "description": [], - "signature": [ - "{ readonly META_FIELDS: \"metaFields\"; readonly DOC_HIGHLIGHT: \"doc_table:highlight\"; readonly QUERY_STRING_OPTIONS: \"query:queryString:options\"; readonly QUERY_ALLOW_LEADING_WILDCARDS: \"query:allowLeadingWildcards\"; readonly SEARCH_QUERY_LANGUAGE: \"search:queryLanguage\"; readonly SORT_OPTIONS: \"sort:options\"; readonly COURIER_IGNORE_FILTER_IF_FIELD_NOT_IN_INDEX: \"courier:ignoreFilterIfFieldNotInIndex\"; readonly COURIER_SET_REQUEST_PREFERENCE: \"courier:setRequestPreference\"; readonly COURIER_CUSTOM_REQUEST_PREFERENCE: \"courier:customRequestPreference\"; readonly COURIER_MAX_CONCURRENT_SHARD_REQUESTS: \"courier:maxConcurrentShardRequests\"; readonly SEARCH_INCLUDE_FROZEN: \"search:includeFrozen\"; readonly SEARCH_TIMEOUT: \"search:timeout\"; readonly HISTOGRAM_BAR_TARGET: \"histogram:barTarget\"; readonly HISTOGRAM_MAX_BARS: \"histogram:maxBars\"; readonly HISTORY_LIMIT: \"history:limit\"; readonly TIMEPICKER_REFRESH_INTERVAL_DEFAULTS: \"timepicker:refreshIntervalDefaults\"; readonly TIMEPICKER_QUICK_RANGES: \"timepicker:quickRanges\"; readonly TIMEPICKER_TIME_DEFAULTS: \"timepicker:timeDefaults\"; readonly FILTERS_PINNED_BY_DEFAULT: \"filters:pinnedByDefault\"; readonly FILTERS_EDITOR_SUGGEST_VALUES: \"filterEditor:suggestValues\"; readonly AUTOCOMPLETE_USE_TIMERANGE: \"autocomplete:useTimeRange\"; readonly AUTOCOMPLETE_VALUE_SUGGESTION_METHOD: \"autocomplete:valueSuggestionMethod\"; readonly DATE_FORMAT: \"dateFormat\"; readonly DATEFORMAT_TZ: \"dateFormat:tz\"; }" - ], - "path": "src/plugins/data/common/constants.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - } - ], - "setup": { - "parentPluginId": "data", - "id": "def-server.DataPluginSetup", - "type": "Interface", - "tags": [], - "label": "DataPluginSetup", - "description": [], - "path": "src/plugins/data/server/plugin.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "data", - "id": "def-server.DataPluginSetup.search", - "type": "Object", - "tags": [], - "label": "search", - "description": [], - "signature": [ - "ISearchSetup" - ], - "path": "src/plugins/data/server/plugin.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "data", - "id": "def-server.DataPluginSetup.query", - "type": "Object", - "tags": [], - "label": "query", - "description": [], - "signature": [ - "QuerySetup" - ], - "path": "src/plugins/data/server/plugin.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "data", - "id": "def-server.DataPluginSetup.fieldFormats", - "type": "Object", - "tags": [ - "deprecated" - ], - "label": "fieldFormats", - "description": [], - "signature": [ - { - "pluginId": "fieldFormats", - "scope": "server", - "docId": "kibFieldFormatsPluginApi", - "section": "def-server.FieldFormatsSetup", - "text": "FieldFormatsSetup" - } - ], - "path": "src/plugins/data/server/plugin.ts", - "deprecated": true, - "trackAdoption": false, - "references": [] - } - ], - "lifecycle": "setup", - "initialIsOpen": true - }, - "start": { - "parentPluginId": "data", - "id": "def-server.DataPluginStart", - "type": "Interface", - "tags": [], - "label": "DataPluginStart", - "description": [], - "path": "src/plugins/data/server/plugin.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "data", - "id": "def-server.DataPluginStart.search", - "type": "Object", - "tags": [], - "label": "search", - "description": [], - "signature": [ - "ISearchStart", - "<", - { - "pluginId": "data", - "scope": "common", - "docId": "kibDataSearchPluginApi", - "section": "def-common.IEsSearchRequest", - "text": "IEsSearchRequest" - }, - ", ", - { - "pluginId": "data", - "scope": "common", - "docId": "kibDataSearchPluginApi", - "section": "def-common.IEsSearchResponse", - "text": "IEsSearchResponse" - }, - ">" - ], - "path": "src/plugins/data/server/plugin.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "data", - "id": "def-server.DataPluginStart.fieldFormats", - "type": "Object", - "tags": [ - "deprecated" - ], - "label": "fieldFormats", - "description": [], - "signature": [ - { - "pluginId": "fieldFormats", - "scope": "server", - "docId": "kibFieldFormatsPluginApi", - "section": "def-server.FieldFormatsStart", - "text": "FieldFormatsStart" - } - ], - "path": "src/plugins/data/server/plugin.ts", - "deprecated": true, - "trackAdoption": false, - "references": [] - }, - { - "parentPluginId": "data", - "id": "def-server.DataPluginStart.indexPatterns", - "type": "Object", - "tags": [], - "label": "indexPatterns", - "description": [], - "signature": [ - { - "pluginId": "dataViews", - "scope": "server", - "docId": "kibDataViewsPluginApi", - "section": "def-server.DataViewsServerPluginStart", - "text": "DataViewsServerPluginStart" - } - ], - "path": "src/plugins/data/server/plugin.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "data", - "id": "def-server.DataPluginStart.datatableUtilities", - "type": "Object", - "tags": [], - "label": "datatableUtilities", - "description": [ - "\nDatatable type utility functions." - ], - "signature": [ - "DatatableUtilitiesService" - ], - "path": "src/plugins/data/server/plugin.ts", - "deprecated": false, - "trackAdoption": false - } - ], - "lifecycle": "start", - "initialIsOpen": true - } - }, - "common": { - "classes": [ - { - "parentPluginId": "data", - "id": "def-common.DatatableUtilitiesService", + "id": "def-common.DataView", "type": "Class", "tags": [], - "label": "DatatableUtilitiesService", - "description": [], - "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", + "label": "DataView", + "description": [ + "\nData view class. Central kibana abstraction around multiple indices." + ], + "signature": [ + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataView", + "text": "DataView" + }, + " implements ", + "DataViewBase" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", "deprecated": false, "trackAdoption": false, "children": [ { "parentPluginId": "data", - "id": "def-common.DatatableUtilitiesService.Unnamed", - "type": "Function", + "id": "def-common.DataView.id", + "type": "string", "tags": [], - "label": "Constructor", - "description": [], + "label": "id", + "description": [ + "\nSaved object id" + ], "signature": [ - "any" + "string | undefined" ], - "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", + "path": "src/plugins/data_views/common/data_views/data_view.ts", "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "data", + "id": "def-common.DataView.title", + "type": "string", + "tags": [ + "deprecated" + ], + "label": "title", + "description": [ + "\nTitle of data view" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": true, "trackAdoption": false, - "children": [ + "references": [ + { + "plugin": "timelines", + "path": "x-pack/plugins/timelines/public/container/source/index.tsx" + }, + { + "plugin": "timelines", + "path": "x-pack/plugins/timelines/public/container/source/index.tsx" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/containers/source/index.tsx" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/containers/source/index.tsx" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/detections/containers/detection_engine/exceptions/get_es_query_filter.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/utils.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/signals/get_query_filter.ts" + }, + { + "plugin": "timelines", + "path": "x-pack/plugins/timelines/public/mock/index_pattern.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/mock/index_pattern.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts" + }, + { + "plugin": "threatIntelligence", + "path": "x-pack/plugins/threat_intelligence/public/common/mocks/mock_security_context.tsx" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/flyout_components/alerts_actions/utils.test.ts" + }, + { + "plugin": "dataViews", + "path": "src/plugins/data_views/common/data_views/data_view.ts" + }, + { + "plugin": "dataViews", + "path": "src/plugins/data_views/common/data_views/data_view.ts" + }, + { + "plugin": "dataViews", + "path": "src/plugins/data_views/common/data_views/data_view.ts" + }, + { + "plugin": "dataViews", + "path": "src/plugins/data_views/common/data_views/data_view.ts" + }, + { + "plugin": "dataViewEditor", + "path": "src/plugins/data_view_editor/public/components/data_view_editor_flyout_content.tsx" + }, + { + "plugin": "unifiedSearch", + "path": "src/plugins/unified_search/public/autocomplete/providers/value_suggestion_provider.ts" + }, + { + "plugin": "unifiedSearch", + "path": "src/plugins/unified_search/public/query_string_input/fetch_index_patterns.ts" + }, + { + "plugin": "unifiedSearch", + "path": "src/plugins/unified_search/public/dataview_picker/change_dataview.tsx" + }, + { + "plugin": "dataViews", + "path": "src/plugins/data_views/server/rest_api_routes/update_data_view.ts" + }, + { + "plugin": "dataViews", + "path": "src/plugins/data_views/server/rest_api_routes/update_data_view.ts" + }, + { + "plugin": "triggersActionsUi", + "path": "x-pack/plugins/triggers_actions_ui/public/common/lib/data_apis.ts" + }, + { + "plugin": "savedObjectsManagement", + "path": "src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx" + }, + { + "plugin": "savedObjectsManagement", + "path": "src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx" + }, + { + "plugin": "unifiedFieldList", + "path": "src/plugins/unified_field_list/public/services/field_stats/load_field_stats.ts" + }, + { + "plugin": "unifiedFieldList", + "path": "src/plugins/unified_field_list/common/utils/field_existing_utils.ts" + }, + { + "plugin": "unifiedFieldList", + "path": "src/plugins/unified_field_list/common/utils/field_existing_utils.ts" + }, + { + "plugin": "unifiedFieldList", + "path": "src/plugins/unified_field_list/common/utils/field_existing_utils.ts" + }, + { + "plugin": "discover", + "path": "src/plugins/discover/public/hooks/use_es_doc_search.ts" + }, + { + "plugin": "discover", + "path": "src/plugins/discover/public/application/main/utils/resolve_data_view.ts" + }, + { + "plugin": "discover", + "path": "src/plugins/discover/public/application/main/utils/resolve_data_view.ts" + }, + { + "plugin": "discover", + "path": "src/plugins/discover/public/application/main/components/sidebar/discover_sidebar.tsx" + }, + { + "plugin": "discover", + "path": "src/plugins/discover/public/application/main/components/top_nav/discover_topnav.tsx" + }, + { + "plugin": "aiops", + "path": "x-pack/plugins/aiops/public/hooks/use_data.ts" + }, + { + "plugin": "aiops", + "path": "x-pack/plugins/aiops/public/components/full_time_range_selector/full_time_range_selector_service.ts" + }, + { + "plugin": "aiops", + "path": "x-pack/plugins/aiops/public/components/explain_log_rate_spikes/explain_log_rate_spikes_analysis.tsx" + }, + { + "plugin": "aiops", + "path": "x-pack/plugins/aiops/public/components/log_categorization/log_categorization_page.tsx" + }, + { + "plugin": "presentationUtil", + "path": "src/plugins/presentation_util/public/services/storybook/data_views.ts" + }, + { + "plugin": "controls", + "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" + }, + { + "plugin": "controls", + "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" + }, + { + "plugin": "lens", + "path": "x-pack/plugins/lens/public/data_views_service/loader.ts" + }, + { + "plugin": "lens", + "path": "x-pack/plugins/lens/public/app_plugin/lens_top_nav.tsx" + }, + { + "plugin": "observability", + "path": "x-pack/plugins/observability/public/utils/observability_data_views/observability_data_views.ts" + }, + { + "plugin": "observability", + "path": "x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/report_definition_field.tsx" + }, + { + "plugin": "observability", + "path": "x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/use_filter_values.ts" + }, + { + "plugin": "observability", + "path": "x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/filter_value_btn.tsx" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/infra/common/log_views/resolved_log_view.ts" + }, + { + "plugin": "maps", + "path": "x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.tsx" + }, + { + "plugin": "maps", + "path": "x-pack/plugins/maps/public/classes/sources/es_search_source/util/scaling_form.tsx" + }, + { + "plugin": "maps", + "path": "x-pack/plugins/maps/public/classes/sources/es_search_source/top_hits/top_hits_form.tsx" + }, + { + "plugin": "maps", + "path": "x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx" + }, + { + "plugin": "maps", + "path": "x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx" + }, + { + "plugin": "maps", + "path": "x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx" + }, + { + "plugin": "maps", + "path": "x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx" + }, + { + "plugin": "maps", + "path": "x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx" + }, + { + "plugin": "maps", + "path": "x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx" + }, + { + "plugin": "maps", + "path": "x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx" + }, + { + "plugin": "maps", + "path": "x-pack/plugins/maps/public/trigger_actions/visualize_geo_field_action.ts" + }, + { + "plugin": "dataVisualizer", + "path": "x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/full_time_range_selector/full_time_range_selector_service.ts" + }, + { + "plugin": "dataVisualizer", + "path": "x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/actions_panel/actions_panel.tsx" + }, + { + "plugin": "dataVisualizer", + "path": "x-pack/plugins/data_visualizer/public/application/index_data_visualizer/hooks/use_data_visualizer_grid_data.ts" + }, + { + "plugin": "dataVisualizer", + "path": "x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/index_data_visualizer_view.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/util/index_utils.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/util/index_utils.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/util/index_utils.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/services/new_job_capabilities/new_job_capabilities_service_analytics.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/services/new_job_capabilities/new_job_capabilities_service_analytics.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_details.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/datavisualizer/index_based/data_loader/data_loader.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/page.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_clone/clone_action_name.tsx" + }, { - "parentPluginId": "data", - "id": "def-common.DatatableUtilitiesService.Unnamed.$1", - "type": "Object", - "tags": [], - "label": "aggs", - "description": [], - "signature": [ - { - "pluginId": "data", - "scope": "common", - "docId": "kibDataSearchPluginApi", - "section": "def-common.AggsCommonStart", - "text": "AggsCommonStart" - } - ], - "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/index_or_search/preconfigured_job_redirect.ts" }, { - "parentPluginId": "data", - "id": "def-common.DatatableUtilitiesService.Unnamed.$2", - "type": "Object", - "tags": [], - "label": "dataViews", - "description": [], - "signature": [ - { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataViewsContract", - "text": "DataViewsContract" - } - ], - "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/job_type/page.tsx" }, { - "parentPluginId": "data", - "id": "def-common.DatatableUtilitiesService.Unnamed.$3", - "type": "Object", - "tags": [], - "label": "fieldFormats", - "description": [], - "signature": [ - { - "pluginId": "fieldFormats", - "scope": "common", - "docId": "kibFieldFormatsPluginApi", - "section": "def-common.FieldFormatsStartCommon", - "text": "FieldFormatsStartCommon" - } - ], - "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "data", - "id": "def-common.DatatableUtilitiesService.clearField", - "type": "Function", - "tags": [], - "label": "clearField", - "description": [], - "signature": [ - "(column: ", + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/job_type/page.tsx" + }, { - "pluginId": "expressions", - "scope": "common", - "docId": "kibExpressionsPluginApi", - "section": "def-common.DatatableColumn", - "text": "DatatableColumn" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/job_type/page.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/services/new_job_capabilities/new_job_capabilities_service.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/services/new_job_capabilities/new_job_capabilities_service.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/job_creator.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/common/chart_loader/chart_loader.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/common/results_loader/categorization_examples_loader.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/components/full_time_range_selector/full_time_range_selector_service.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/bucket_span_estimator/estimate_bucket_span.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/components/datafeed_step/components/data_view/change_data_view.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/new_job/wizard_steps.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/recognize/components/job_settings_form.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/recognize/page.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/recognize/page.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/quick_create_job.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/use_outlier_data.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/use_exploration_results.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/source_selection/source_selection.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/embeddables/anomaly_charts/anomaly_charts_embeddable.tsx" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/infra/public/pages/logs/settings/validation_errors.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/infra/public/pages/logs/settings/validation_errors.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/infra/public/pages/logs/settings/validation_errors.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/infra/public/pages/logs/settings/validation_errors.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/filter_dataset.tsx" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/filter_log_level.tsx" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/query_bar.tsx" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/public/applications/fleet/components/search_bar.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/server/models/data_frame_analytics/index_patterns.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/server/models/job_service/new_job_caps/rollup.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/server/lib/alerts/alerting_service.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.ts" + }, + { + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/common/index_patterns_utils.ts" + }, + { + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/common/index_patterns_utils.ts" + }, + { + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/server/lib/get_fields.ts" + }, + { + "plugin": "apm", + "path": "x-pack/plugins/apm/server/routes/data_view/create_static_data_view.ts" + }, + { + "plugin": "reporting", + "path": "x-pack/plugins/reporting/server/export_types/csv_searchsource/generate_csv/generate_csv.ts" + }, + { + "plugin": "graph", + "path": "x-pack/plugins/graph/public/state_management/datasource.sagas.ts" + }, + { + "plugin": "graph", + "path": "x-pack/plugins/graph/public/state_management/persistence.ts" + }, + { + "plugin": "graph", + "path": "x-pack/plugins/graph/public/state_management/persistence.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/detections/components/rules/eql_query_bar/validators.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/detections/components/rules/step_define_rule/index.tsx" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/index.tsx" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/sourcerer/routes/index.ts" + }, + { + "plugin": "stackAlerts", + "path": "x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/expressions/boundary_index_expression.tsx" + }, + { + "plugin": "stackAlerts", + "path": "x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/expressions/entity_index_expression.tsx" + }, + { + "plugin": "stackAlerts", + "path": "x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/index.tsx" + }, + { + "plugin": "stackAlerts", + "path": "x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/index.tsx" + }, + { + "plugin": "stackAlerts", + "path": "x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/index.tsx" + }, + { + "plugin": "stackAlerts", + "path": "x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/index.tsx" + }, + { + "plugin": "stackAlerts", + "path": "x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/index.tsx" + }, + { + "plugin": "stackAlerts", + "path": "x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/index.tsx" + }, + { + "plugin": "stackAlerts", + "path": "x-pack/plugins/stack_alerts/public/alert_types/es_query/expression/search_source_expression_form.tsx" + }, + { + "plugin": "synthetics", + "path": "x-pack/plugins/synthetics/public/legacy_uptime/components/overview/filter_group/filter_group.tsx" + }, + { + "plugin": "synthetics", + "path": "x-pack/plugins/synthetics/public/legacy_uptime/components/overview/alerts/monitor_expressions/filters_expression_select.tsx" + }, + { + "plugin": "timelines", + "path": "x-pack/plugins/timelines/server/search_strategy/index_fields/index.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_details/step_details_form.tsx" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/wizard/wizard.tsx" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/filter_agg/components/filter_term_form.tsx" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/hooks/use_index_data.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/hooks/use_index_data.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/hooks/use_index_data.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/hooks/use_index_data.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/hooks/use_index_data.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/hooks/use_index_data.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/hooks/use_index_data.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/hooks/use_step_define_form.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/hooks/use_step_define_form.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_form.tsx" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_form.tsx" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_form.tsx" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_form.tsx" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_summary.tsx" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_summary.tsx" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_summary.tsx" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/hooks/use_search_items/common.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/services/es_index_service.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/server/routes/api/transforms.ts" + }, + { + "plugin": "upgradeAssistant", + "path": "x-pack/plugins/upgrade_assistant/public/application/components/es_deprecation_logs/fix_deprecation_logs/external_links.tsx" + }, + { + "plugin": "ux", + "path": "x-pack/plugins/ux/public/components/app/rum_dashboard/local_uifilters/use_data_view.ts" + }, + { + "plugin": "graph", + "path": "x-pack/plugins/graph/public/state_management/datasource.test.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/infra/common/dependency_mocks/index_patterns.ts" }, - ") => void" - ], - "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ { - "parentPluginId": "data", - "id": "def-common.DatatableUtilitiesService.clearField.$1", - "type": "Object", - "tags": [], - "label": "column", - "description": [], - "signature": [ - { - "pluginId": "expressions", - "scope": "common", - "docId": "kibExpressionsPluginApi", - "section": "def-common.DatatableColumn", - "text": "DatatableColumn" - } - ], - "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "data", - "id": "def-common.DatatableUtilitiesService.clearFieldFormat", - "type": "Function", - "tags": [], - "label": "clearFieldFormat", - "description": [], - "signature": [ - "(column: ", + "plugin": "infra", + "path": "x-pack/plugins/infra/common/dependency_mocks/index_patterns.ts" + }, { - "pluginId": "expressions", - "scope": "common", - "docId": "kibExpressionsPluginApi", - "section": "def-common.DatatableColumn", - "text": "DatatableColumn" + "plugin": "infra", + "path": "x-pack/plugins/infra/common/dependency_mocks/index_patterns.ts" }, - ") => void" - ], - "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ { - "parentPluginId": "data", - "id": "def-common.DatatableUtilitiesService.clearFieldFormat.$1", - "type": "Object", - "tags": [], - "label": "column", - "description": [], - "signature": [ - { - "pluginId": "expressions", - "scope": "common", - "docId": "kibExpressionsPluginApi", - "section": "def-common.DatatableColumn", - "text": "DatatableColumn" - } - ], - "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "data", - "id": "def-common.DatatableUtilitiesService.getAggConfig", - "type": "Function", - "tags": [], - "label": "getAggConfig", - "description": [], - "signature": [ - "(column: ", + "plugin": "maps", + "path": "x-pack/plugins/maps/public/classes/tooltips/es_tooltip_property.test.ts" + }, { - "pluginId": "expressions", - "scope": "common", - "docId": "kibExpressionsPluginApi", - "section": "def-common.DatatableColumn", - "text": "DatatableColumn" + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/services/new_job_capabilities/remove_nested_field_children.test.ts" }, - ") => Promise<", { - "pluginId": "data", - "scope": "common", - "docId": "kibDataSearchPluginApi", - "section": "def-common.AggConfig", - "text": "AggConfig" + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/common.test.ts" }, - " | undefined>" - ], - "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ { - "parentPluginId": "data", - "id": "def-common.DatatableUtilitiesService.getAggConfig.$1", - "type": "Object", - "tags": [], - "label": "column", - "description": [], - "signature": [ - { - "pluginId": "expressions", - "scope": "common", - "docId": "kibExpressionsPluginApi", - "section": "def-common.DatatableColumn", - "text": "DatatableColumn" - } - ], - "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "data", - "id": "def-common.DatatableUtilitiesService.getDateHistogramMeta", - "type": "Function", - "tags": [], - "label": "getDateHistogramMeta", - "description": [ - "\nHelper function returning the used interval, used time zone and applied time filters for data table column created by the date_histogramm agg type.\n\"auto\" will get expanded to the actually used interval.\nIf the column is not a column created by a date_histogram aggregation of the esaggs data source,\nthis function will return undefined." - ], - "signature": [ - "(column: ", + "plugin": "controls", + "path": "src/plugins/controls/public/services/data_views/data_views.story.ts" + }, { - "pluginId": "expressions", - "scope": "common", - "docId": "kibExpressionsPluginApi", - "section": "def-common.DatatableColumn", - "text": "DatatableColumn" + "plugin": "dataViewManagement", + "path": "src/plugins/data_view_management/public/components/edit_index_pattern/edit_index_pattern.tsx" }, - ", defaults?: Partial<{ timeZone: string; }>) => DateHistogramMeta | undefined" - ], - "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ { - "parentPluginId": "data", - "id": "def-common.DatatableUtilitiesService.getDateHistogramMeta.$1", - "type": "Object", - "tags": [], - "label": "column", - "description": [], - "signature": [ - { - "pluginId": "expressions", - "scope": "common", - "docId": "kibExpressionsPluginApi", - "section": "def-common.DatatableColumn", - "text": "DatatableColumn" - } - ], - "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true + "plugin": "dataViewManagement", + "path": "src/plugins/data_view_management/public/components/edit_index_pattern/edit_index_pattern.tsx" }, { - "parentPluginId": "data", - "id": "def-common.DatatableUtilitiesService.getDateHistogramMeta.$2", - "type": "Object", - "tags": [], - "label": "defaults", - "description": [], - "signature": [ - "Partial<{ timeZone: string; }>" - ], - "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "data", - "id": "def-common.DatatableUtilitiesService.getDataView", - "type": "Function", - "tags": [], - "label": "getDataView", - "description": [], - "signature": [ - "(column: ", + "plugin": "dataViewManagement", + "path": "src/plugins/data_view_management/public/components/field_editor/components/scripting_help/test_script.tsx" + }, { - "pluginId": "expressions", - "scope": "common", - "docId": "kibExpressionsPluginApi", - "section": "def-common.DatatableColumn", - "text": "DatatableColumn" + "plugin": "dataViewManagement", + "path": "src/plugins/data_view_management/public/components/field_editor/field_editor.tsx" }, - ") => Promise<", { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataView", - "text": "DataView" + "plugin": "dataViewManagement", + "path": "src/plugins/data_view_management/public/components/edit_index_pattern/create_edit_field/create_edit_field.tsx" }, - " | undefined>" - ], - "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ { - "parentPluginId": "data", - "id": "def-common.DatatableUtilitiesService.getDataView.$1", - "type": "Object", - "tags": [], - "label": "column", - "description": [], - "signature": [ - { - "pluginId": "expressions", - "scope": "common", - "docId": "kibExpressionsPluginApi", - "section": "def-common.DatatableColumn", - "text": "DatatableColumn" - } - ], - "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "data", - "id": "def-common.DatatableUtilitiesService.getField", - "type": "Function", - "tags": [], - "label": "getField", - "description": [], - "signature": [ - "(column: ", + "plugin": "inputControlVis", + "path": "src/plugins/input_control_vis/public/control/list_control_factory.ts" + }, + { + "plugin": "inputControlVis", + "path": "src/plugins/input_control_vis/public/control/range_control_factory.ts" + }, { - "pluginId": "expressions", - "scope": "common", - "docId": "kibExpressionsPluginApi", - "section": "def-common.DatatableColumn", - "text": "DatatableColumn" + "plugin": "unifiedFieldList", + "path": "src/plugins/unified_field_list/server/routes/field_stats.ts" }, - ") => Promise<", { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataViewField", - "text": "DataViewField" + "plugin": "unifiedFieldList", + "path": "src/plugins/unified_field_list/server/routes/field_stats.ts" }, - " | undefined>" - ], - "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ { - "parentPluginId": "data", - "id": "def-common.DatatableUtilitiesService.getField.$1", - "type": "Object", - "tags": [], - "label": "column", - "description": [], - "signature": [ - { - "pluginId": "expressions", - "scope": "common", - "docId": "kibExpressionsPluginApi", - "section": "def-common.DatatableColumn", - "text": "DatatableColumn" - } - ], - "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "data", - "id": "def-common.DatatableUtilitiesService.getFieldFormat", - "type": "Function", - "tags": [], - "label": "getFieldFormat", - "description": [], - "signature": [ - "(column: ", + "plugin": "visDefaultEditor", + "path": "src/plugins/vis_default_editor/public/components/controls/field.tsx" + }, { - "pluginId": "expressions", - "scope": "common", - "docId": "kibExpressionsPluginApi", - "section": "def-common.DatatableColumn", - "text": "DatatableColumn" + "plugin": "visDefaultEditor", + "path": "src/plugins/vis_default_editor/public/components/controls/field.tsx" }, - ") => ", { - "pluginId": "fieldFormats", - "scope": "common", - "docId": "kibFieldFormatsPluginApi", - "section": "def-common.FieldFormat", - "text": "FieldFormat" + "plugin": "visDefaultEditor", + "path": "src/plugins/vis_default_editor/public/components/agg_select.tsx" }, - " | undefined" - ], - "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ { - "parentPluginId": "data", - "id": "def-common.DatatableUtilitiesService.getFieldFormat.$1", - "type": "Object", - "tags": [], - "label": "column", - "description": [], - "signature": [ - { - "pluginId": "expressions", - "scope": "common", - "docId": "kibExpressionsPluginApi", - "section": "def-common.DatatableColumn", - "text": "DatatableColumn" - } - ], - "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "data", - "id": "def-common.DatatableUtilitiesService.getInterval", - "type": "Function", - "tags": [], - "label": "getInterval", - "description": [], - "signature": [ - "(column: ", + "plugin": "inputControlVis", + "path": "src/plugins/input_control_vis/public/test_utils/get_index_pattern_mock.ts" + }, { - "pluginId": "expressions", - "scope": "common", - "docId": "kibExpressionsPluginApi", - "section": "def-common.DatatableColumn", - "text": "DatatableColumn" + "plugin": "visTypeTimelion", + "path": "src/plugins/vis_types/timelion/public/helpers/arg_value_suggestions.ts" }, - ") => string | undefined" - ], - "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ { - "parentPluginId": "data", - "id": "def-common.DatatableUtilitiesService.getInterval.$1", - "type": "Object", - "tags": [], - "label": "column", - "description": [], - "signature": [ - { - "pluginId": "expressions", - "scope": "common", - "docId": "kibExpressionsPluginApi", - "section": "def-common.DatatableColumn", - "text": "DatatableColumn" - } - ], - "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "data", - "id": "def-common.DatatableUtilitiesService.getNumberHistogramInterval", - "type": "Function", - "tags": [], - "label": "getNumberHistogramInterval", - "description": [ - "\nHelper function returning the used interval for data table column created by the histogramm agg type.\n\"auto\" will get expanded to the actually used interval.\nIf the column is not a column created by a histogram aggregation of the esaggs data source,\nthis function will return undefined." - ], - "signature": [ - "(column: ", + "plugin": "visTypeTimelion", + "path": "src/plugins/vis_types/timelion/public/helpers/arg_value_suggestions.ts" + }, { - "pluginId": "expressions", - "scope": "common", - "docId": "kibExpressionsPluginApi", - "section": "def-common.DatatableColumn", - "text": "DatatableColumn" + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/common/index_patterns_utils.test.ts" }, - ") => number | undefined" - ], - "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ { - "parentPluginId": "data", - "id": "def-common.DatatableUtilitiesService.getNumberHistogramInterval.$1", - "type": "Object", - "tags": [], - "label": "column", - "description": [], - "signature": [ - { - "pluginId": "expressions", - "scope": "common", - "docId": "kibExpressionsPluginApi", - "section": "def-common.DatatableColumn", - "text": "DatatableColumn" - } - ], - "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "data", - "id": "def-common.DatatableUtilitiesService.getTotalCount", - "type": "Function", - "tags": [], - "label": "getTotalCount", - "description": [], - "signature": [ - "(table: ", + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/common/index_patterns_utils.test.ts" + }, { - "pluginId": "expressions", - "scope": "common", - "docId": "kibExpressionsPluginApi", - "section": "def-common.Datatable", - "text": "Datatable" + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/public/application/components/lib/convert_series_to_datatable.ts" }, - ") => number | undefined" - ], - "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ { - "parentPluginId": "data", - "id": "def-common.DatatableUtilitiesService.getTotalCount.$1", - "type": "Object", - "tags": [], - "label": "table", - "description": [], - "signature": [ - { - "pluginId": "expressions", - "scope": "common", - "docId": "kibExpressionsPluginApi", - "section": "def-common.Datatable", - "text": "Datatable" - } - ], - "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "data", - "id": "def-common.DatatableUtilitiesService.hasPrecisionError", - "type": "Function", - "tags": [], - "label": "hasPrecisionError", - "description": [], - "signature": [ - "(column: ", + "plugin": "visTypeVega", + "path": "src/plugins/vis_types/vega/public/data_model/search_api.ts" + }, + { + "plugin": "discover", + "path": "src/plugins/discover/public/application/main/hooks/use_adhoc_data_views.test.ts" + }, + { + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/public/application/components/lib/convert_series_to_datatable.test.ts" + }, + { + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/public/convert_to_lens/lib/datasource/get_datasource_info.test.ts" + }, + { + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/public/convert_to_lens/lib/datasource/get_datasource_info.test.ts" + }, + { + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/public/convert_to_lens/lib/datasource/get_datasource_info.test.ts" + }, + { + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/server/lib/search_strategies/lib/cached_index_pattern_fetcher.test.ts" + }, { - "pluginId": "expressions", - "scope": "common", - "docId": "kibExpressionsPluginApi", - "section": "def-common.DatatableColumn", - "text": "DatatableColumn" + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/server/lib/search_strategies/lib/cached_index_pattern_fetcher.test.ts" }, - ") => ", - "Serializable" - ], - "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ { - "parentPluginId": "data", - "id": "def-common.DatatableUtilitiesService.hasPrecisionError.$1", - "type": "Object", - "tags": [], - "label": "column", - "description": [], - "signature": [ - { - "pluginId": "expressions", - "scope": "common", - "docId": "kibExpressionsPluginApi", - "section": "def-common.DatatableColumn", - "text": "DatatableColumn" - } - ], - "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "data", - "id": "def-common.DatatableUtilitiesService.isFilterable", - "type": "Function", - "tags": [], - "label": "isFilterable", - "description": [], - "signature": [ - "(column: ", + "plugin": "discover", + "path": "src/plugins/discover/public/application/main/components/layout/__stories__/get_layout_props.ts" + }, { - "pluginId": "expressions", - "scope": "common", - "docId": "kibExpressionsPluginApi", - "section": "def-common.DatatableColumn", - "text": "DatatableColumn" + "plugin": "dataViews", + "path": "src/plugins/data_views/common/data_views/data_views.ts" }, - ") => boolean" - ], - "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ { - "parentPluginId": "data", - "id": "def-common.DatatableUtilitiesService.isFilterable.$1", - "type": "Object", - "tags": [], - "label": "column", - "description": [], - "signature": [ - { - "pluginId": "expressions", - "scope": "common", - "docId": "kibExpressionsPluginApi", - "section": "def-common.DatatableColumn", - "text": "DatatableColumn" - } - ], - "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "data", - "id": "def-common.DatatableUtilitiesService.setFieldFormat", - "type": "Function", - "tags": [], - "label": "setFieldFormat", - "description": [], - "signature": [ - "(column: ", + "plugin": "lens", + "path": "x-pack/plugins/lens/public/data_views_service/loader.test.ts" + }, { - "pluginId": "expressions", - "scope": "common", - "docId": "kibExpressionsPluginApi", - "section": "def-common.DatatableColumn", - "text": "DatatableColumn" + "plugin": "lens", + "path": "x-pack/plugins/lens/public/data_views_service/loader.test.ts" }, - ", fieldFormat: ", { - "pluginId": "fieldFormats", - "scope": "common", - "docId": "kibFieldFormatsPluginApi", - "section": "def-common.FieldFormat", - "text": "FieldFormat" + "plugin": "lens", + "path": "x-pack/plugins/lens/public/data_views_service/loader.test.ts" }, - ") => void" - ], - "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ { - "parentPluginId": "data", - "id": "def-common.DatatableUtilitiesService.setFieldFormat.$1", - "type": "Object", - "tags": [], - "label": "column", - "description": [], - "signature": [ - { - "pluginId": "expressions", - "scope": "common", - "docId": "kibExpressionsPluginApi", - "section": "def-common.DatatableColumn", - "text": "DatatableColumn" - } - ], - "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/sourcerer/routes/index.ts" }, { - "parentPluginId": "data", - "id": "def-common.DatatableUtilitiesService.setFieldFormat.$2", - "type": "Object", - "tags": [], - "label": "fieldFormat", - "description": [], - "signature": [ - { - "pluginId": "fieldFormats", - "scope": "common", - "docId": "kibFieldFormatsPluginApi", - "section": "def-common.FieldFormat", - "text": "FieldFormat" - } - ], - "path": "src/plugins/data/common/datatable_utilities/datatable_utilities_service.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/sourcerer/routes/index.ts" } - ], - "returnComment": [] - } - ], - "initialIsOpen": false - }, - { - "parentPluginId": "data", - "id": "def-common.DataView", - "type": "Class", - "tags": [], - "label": "DataView", - "description": [ - "\nData view class. Central kibana abstraction around multiple indices." - ], - "signature": [ - { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataView", - "text": "DataView" - }, - " implements ", - "DataViewBase" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "data", - "id": "def-common.DataView.id", - "type": "string", - "tags": [], - "label": "id", - "description": [ - "\nSaved object id" - ], - "signature": [ - "string | undefined" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "data", - "id": "def-common.DataView.title", - "type": "string", - "tags": [], - "label": "title", - "description": [ - "\nTitle of data view" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false + ] }, { "parentPluginId": "data", @@ -18891,6 +20641,60 @@ "children": [], "returnComment": [] }, + { + "parentPluginId": "data", + "id": "def-common.DataView.getIndexPattern", + "type": "Function", + "tags": [], + "label": "getIndexPattern", + "description": [ + "\nGet index pattern" + ], + "signature": [ + "() => string" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [ + "index pattern string" + ] + }, + { + "parentPluginId": "data", + "id": "def-common.DataView.setIndexPattern", + "type": "Function", + "tags": [], + "label": "setIndexPattern", + "description": [ + "\nSet index pattern" + ], + "signature": [ + "(indexPattern: string) => void" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "data", + "id": "def-common.DataView.setIndexPattern.$1", + "type": "string", + "tags": [], + "label": "indexPattern", + "description": [], + "signature": [ + "string" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, { "parentPluginId": "data", "id": "def-common.DataView.getOriginalSavedObjectBody", diff --git a/api_docs/data.mdx b/api_docs/data.mdx index 705e1202dd7a7..f0bff0b9a136c 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-10 +date: 2022-10-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data'] --- import dataObj from './data.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 | |-------------------|-----------|------------------------|-----------------| -| 3221 | 33 | 2513 | 24 | +| 3228 | 33 | 2516 | 24 | ## Client diff --git a/api_docs/data_query.mdx b/api_docs/data_query.mdx index 4f27bd7c26453..bec826bee2d2d 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-10 +date: 2022-10-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data.query'] --- import dataQueryObj from './data_query.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 | |-------------------|-----------|------------------------|-----------------| -| 3221 | 33 | 2513 | 24 | +| 3228 | 33 | 2516 | 24 | ## Client diff --git a/api_docs/data_search.devdocs.json b/api_docs/data_search.devdocs.json index 08d6314c52ffe..a48ebb4f806f4 100644 --- a/api_docs/data_search.devdocs.json +++ b/api_docs/data_search.devdocs.json @@ -1485,7 +1485,7 @@ "label": "config", "description": [], "signature": [ - "Readonly<{} & { search: Readonly<{} & { aggs: Readonly<{} & { shardDelay: Readonly<{} & { enabled: boolean; }>; }>; sessions: Readonly<{} & { enabled: boolean; notTouchedTimeout: moment.Duration; maxUpdateRetries: number; defaultExpiration: moment.Duration; management: Readonly<{} & { refreshInterval: moment.Duration; maxSessions: number; refreshTimeout: moment.Duration; expiresSoonWarning: moment.Duration; }>; }>; }>; }>" + "Readonly<{} & { search: Readonly<{} & { aggs: Readonly<{} & { shardDelay: Readonly<{} & { enabled: boolean; }>; }>; asyncSearch: Readonly<{} & { waitForCompletion: moment.Duration; keepAlive: moment.Duration; batchedReduceSize: number; }>; sessions: Readonly<{} & { enabled: boolean; notTouchedTimeout: moment.Duration; maxUpdateRetries: number; defaultExpiration: moment.Duration; management: Readonly<{} & { refreshInterval: moment.Duration; maxSessions: number; refreshTimeout: moment.Duration; expiresSoonWarning: moment.Duration; }>; }>; }>; }>" ], "path": "src/plugins/data/server/search/session/session_service.ts", "deprecated": false, @@ -1685,7 +1685,7 @@ "section": "def-common.SearchSessionSavedObjectAttributes", "text": "SearchSessionSavedObjectAttributes" }, - "> | undefined>" + ">>" ], "path": "src/plugins/data/server/search/session/session_service.ts", "deprecated": false, @@ -2575,7 +2575,7 @@ "section": "def-common.SearchSessionSavedObjectAttributes", "text": "SearchSessionSavedObjectAttributes" }, - "> | undefined>; get: (sessionId: string) => Promise<", + ">>; get: (sessionId: string) => Promise<", "SavedObject", "<", { @@ -6730,7 +6730,7 @@ "section": "def-common.RequestAdapter", "text": "RequestAdapter" }, - " | undefined, abortSignal?: AbortSignal | undefined, searchSessionId?: string | undefined) => Promise<", + " | undefined, abortSignal?: AbortSignal | undefined, searchSessionId?: string | undefined, disableShardFailureWarning?: boolean | undefined) => Promise<", "SearchResponse", "; }" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "dataViews", - "id": "def-public.DataView.typeMeta", - "type": "Object", - "tags": [], - "label": "typeMeta", - "description": [ - "\nOnly used by rollup indices, used by rollup specific endpoint to load field list." - ], - "signature": [ { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.TypeMeta", - "text": "TypeMeta" + "plugin": "timelines", + "path": "x-pack/plugins/timelines/public/container/source/index.tsx" }, - " | undefined" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "dataViews", - "id": "def-public.DataView.fields", - "type": "CompoundType", - "tags": [], - "label": "fields", - "description": [ - "\nField list, in extended array format" - ], - "signature": [ { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.IIndexPatternFieldList", - "text": "IIndexPatternFieldList" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/containers/source/index.tsx" }, - " & { toSpec: () => ", { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataViewFieldMap", - "text": "DataViewFieldMap" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/containers/source/index.tsx" }, - "; }" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "dataViews", - "id": "def-public.DataView.timeFieldName", - "type": "string", - "tags": [], - "label": "timeFieldName", - "description": [ - "\nTimestamp field name" - ], - "signature": [ - "string | undefined" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "dataViews", - "id": "def-public.DataView.type", - "type": "string", - "tags": [], - "label": "type", - "description": [ - "\nType is used to identify rollup index patterns." - ], - "signature": [ - "string | undefined" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "dataViews", - "id": "def-public.DataView.flattenHit", - "type": "Function", - "tags": [ - "deprecated" - ], - "label": "flattenHit", - "description": [], - "signature": [ - "(hit: Record, deep?: boolean | undefined) => Record" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": true, - "trackAdoption": false, - "references": [ { - "plugin": "maps", - "path": "x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/detections/containers/detection_engine/exceptions/get_es_query_filter.ts" }, { - "plugin": "maps", - "path": "x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx" - } - ], - "returnComment": [], - "children": [ + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts" + }, { - "parentPluginId": "dataViews", - "id": "def-public.DataView.flattenHit.$1", - "type": "Object", - "tags": [], - "label": "hit", - "description": [], - "signature": [ - "{ [x: string]: unknown[]; }" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/utils.ts" }, { - "parentPluginId": "dataViews", - "id": "def-public.DataView.flattenHit.$2", - "type": "CompoundType", - "tags": [], - "label": "deep", - "description": [], - "signature": [ - "boolean | undefined" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false - } - ] - }, - { - "parentPluginId": "dataViews", - "id": "def-public.DataView.metaFields", - "type": "Array", - "tags": [], - "label": "metaFields", - "description": [ - "\nList of meta fields by name" - ], - "signature": [ - "string[]" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "dataViews", - "id": "def-public.DataView.version", - "type": "string", - "tags": [], - "label": "version", - "description": [ - "\nSavedObject version" - ], - "signature": [ - "string | undefined" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "dataViews", - "id": "def-public.DataView.sourceFilters", - "type": "Array", - "tags": [], - "label": "sourceFilters", - "description": [ - "\nArray of filters - hides fields in discover" - ], - "signature": [ + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/signals/get_query_filter.ts" + }, { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.SourceFilter", - "text": "SourceFilter" + "plugin": "timelines", + "path": "x-pack/plugins/timelines/public/mock/index_pattern.ts" }, - "[] | undefined" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "dataViews", - "id": "def-public.DataView.namespaces", - "type": "Array", - "tags": [], - "label": "namespaces", - "description": [ - "\nArray of namespace ids" - ], - "signature": [ - "string[]" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "dataViews", - "id": "def-public.DataView.allowNoIndex", - "type": "boolean", - "tags": [], - "label": "allowNoIndex", - "description": [ - "\nPrevents errors when index pattern exists before indices" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "dataViews", - "id": "def-public.DataView.name", - "type": "string", - "tags": [], - "label": "name", - "description": [ - "\nName of the data view. Human readable name used to differentiate data view." - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "dataViews", - "id": "def-public.DataView.matchedIndices", - "type": "Array", - "tags": [], - "label": "matchedIndices", - "description": [], - "signature": [ - "string[]" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "dataViews", - "id": "def-public.DataView.Unnamed", - "type": "Function", - "tags": [], - "label": "Constructor", - "description": [ - "\nconstructor" - ], - "signature": [ - "any" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ { - "parentPluginId": "dataViews", - "id": "def-public.DataView.Unnamed.$1", - "type": "Object", - "tags": [], - "label": "config", - "description": [ - "- config data and dependencies" - ], - "signature": [ - "DataViewDeps" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "dataViews", - "id": "def-public.DataView.getName", - "type": "Function", - "tags": [], - "label": "getName", - "description": [ - "\nGet name of Data View" - ], - "signature": [ - "() => string" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [] - }, - { - "parentPluginId": "dataViews", - "id": "def-public.DataView.getOriginalSavedObjectBody", - "type": "Function", - "tags": [], - "label": "getOriginalSavedObjectBody", - "description": [ - "\nGet last saved saved object fields" - ], - "signature": [ - "() => { fieldAttrs?: string | undefined; title?: string | undefined; timeFieldName?: string | undefined; fields?: string | undefined; sourceFilters?: string | undefined; fieldFormatMap?: string | undefined; typeMeta?: string | undefined; type?: string | undefined; }" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [] - }, - { - "parentPluginId": "dataViews", - "id": "def-public.DataView.resetOriginalSavedObjectBody", - "type": "Function", - "tags": [], - "label": "resetOriginalSavedObjectBody", - "description": [ - "\nReset last saved saved object fields. Used after saving." - ], - "signature": [ - "() => void" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [] - }, - { - "parentPluginId": "dataViews", - "id": "def-public.DataView.getFieldAttrs", - "type": "Function", - "tags": [], - "label": "getFieldAttrs", - "description": [ - "\nReturns field attributes map" - ], - "signature": [ - "() => { [x: string]: ", + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/mock/index_pattern.ts" + }, { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.FieldAttrSet", - "text": "FieldAttrSet" + "plugin": "lists", + "path": "x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts" }, - "; }" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [] - }, - { - "parentPluginId": "dataViews", - "id": "def-public.DataView.getComputedFields", - "type": "Function", - "tags": [], - "label": "getComputedFields", - "description": [ - "\nReturns scripted fields" - ], - "signature": [ - "() => { storedFields: string[]; scriptFields: Record; docvalueFields: { field: string; format: string; }[]; runtimeFields: ", - "MappingRuntimeFields", - "; }" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [] - }, - { - "parentPluginId": "dataViews", - "id": "def-public.DataView.isPersisted", - "type": "Function", - "tags": [], - "label": "isPersisted", - "description": [], - "signature": [ - "() => boolean" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [] - }, - { - "parentPluginId": "dataViews", - "id": "def-public.DataView.toSpec", - "type": "Function", - "tags": [], - "label": "toSpec", - "description": [ - "\nCreates static representation of the data view." - ], - "signature": [ - "(includeFields?: boolean) => ", { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataViewSpec", - "text": "DataViewSpec" - } - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ + "plugin": "lists", + "path": "x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts" + }, { - "parentPluginId": "dataViews", - "id": "def-public.DataView.toSpec.$1", - "type": "boolean", - "tags": [], - "label": "includeFields", - "description": [ - "Whether or not to include the `fields` list as part of this spec. If not included, the list\nwill be fetched from Elasticsearch when instantiating a new Data View with this spec." - ], - "signature": [ - "boolean" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "dataViews", - "id": "def-public.DataView.getSourceFiltering", - "type": "Function", - "tags": [], - "label": "getSourceFiltering", - "description": [ - "\nGet the source filtering configuration for that index." - ], - "signature": [ - "() => { excludes: string[]; }" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [] - }, - { - "parentPluginId": "dataViews", - "id": "def-public.DataView.removeScriptedField", - "type": "Function", - "tags": [ - "deprecated" - ], - "label": "removeScriptedField", - "description": [ - "\nRemoves scripted field from field list." - ], - "signature": [ - "(fieldName: string) => void" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": true, - "trackAdoption": false, - "references": [ + "plugin": "lists", + "path": "x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts" + }, { - "plugin": "dataViewManagement", - "path": "src/plugins/data_view_management/public/components/edit_index_pattern/scripted_fields_table/scripted_fields_table.tsx" + "plugin": "lists", + "path": "x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts" }, { - "plugin": "dataViewManagement", - "path": "src/plugins/data_view_management/public/components/field_editor/field_editor.tsx" - } - ], - "children": [ + "plugin": "lists", + "path": "x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts" + }, { - "parentPluginId": "dataViews", - "id": "def-public.DataView.removeScriptedField.$1", - "type": "string", - "tags": [], - "label": "fieldName", - "description": [ - "name of scripted field to remove" - ], - "signature": [ - "string" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "dataViews", - "id": "def-public.DataView.getNonScriptedFields", - "type": "Function", - "tags": [ - "deprecated" - ], - "label": "getNonScriptedFields", - "description": [ - "\n" - ], - "signature": [ - "() => ", + "plugin": "lists", + "path": "x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts" + }, { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataViewField", - "text": "DataViewField" + "plugin": "lists", + "path": "x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts" }, - "[]" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": true, - "trackAdoption": false, - "references": [ { - "plugin": "visTypeTimeseries", - "path": "src/plugins/vis_types/timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts" + "plugin": "lists", + "path": "x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts" }, { - "plugin": "graph", - "path": "x-pack/plugins/graph/public/services/persistence/deserialize.ts" + "plugin": "lists", + "path": "x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts" }, { - "plugin": "graph", - "path": "x-pack/plugins/graph/public/state_management/datasource.test.ts" + "plugin": "threatIntelligence", + "path": "x-pack/plugins/threat_intelligence/public/common/mocks/mock_security_context.tsx" }, { - "plugin": "graph", - "path": "x-pack/plugins/graph/public/services/persistence/deserialize.test.ts" + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/flyout_components/alerts_actions/utils.test.ts" }, { - "plugin": "graph", - "path": "x-pack/plugins/graph/public/services/persistence/deserialize.test.ts" + "plugin": "data", + "path": "src/plugins/data/common/search/expressions/kibana_context.test.ts" }, { - "plugin": "dataViewManagement", - "path": "src/plugins/data_view_management/public/components/edit_index_pattern/source_filters_table/components/table/table.tsx" + "plugin": "data", + "path": "src/plugins/data/common/search/expressions/kibana_context.test.ts" }, { - "plugin": "dataViewManagement", - "path": "src/plugins/data_view_management/public/components/edit_index_pattern/edit_index_pattern.tsx" + "plugin": "data", + "path": "src/plugins/data/common/search/expressions/kibana_context.test.ts" }, { - "plugin": "dataViewManagement", - "path": "src/plugins/data_view_management/public/components/edit_index_pattern/edit_index_pattern.tsx" + "plugin": "data", + "path": "src/plugins/data/public/query/filter_manager/lib/get_display_value.ts" }, { - "plugin": "dataViewManagement", - "path": "src/plugins/data_view_management/public/components/edit_index_pattern/edit_index_pattern.tsx" + "plugin": "data", + "path": "src/plugins/data/common/search/search_source/inspect/inspector_stats.ts" }, { - "plugin": "visTypeTimeseries", - "path": "src/plugins/vis_types/timeseries/public/application/lib/fetch_fields.ts" - } - ], - "children": [], - "returnComment": [] - }, - { - "parentPluginId": "dataViews", - "id": "def-public.DataView.getScriptedFields", - "type": "Function", - "tags": [ - "deprecated" - ], - "label": "getScriptedFields", - "description": [ - "\n" - ], - "signature": [ - "() => ", + "plugin": "data", + "path": "src/plugins/data/common/search/tabify/response_writer.ts" + }, { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataViewField", - "text": "DataViewField" + "plugin": "data", + "path": "src/plugins/data/public/search/errors/painless_error.tsx" }, - "[]" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": true, - "trackAdoption": false, - "references": [ { - "plugin": "dataViewManagement", - "path": "src/plugins/data_view_management/public/components/edit_index_pattern/scripted_fields_table/scripted_fields_table.tsx" - } - ], - "children": [], - "returnComment": [] - }, - { - "parentPluginId": "dataViews", - "id": "def-public.DataView.isTSDBMode", - "type": "Function", - "tags": [], - "label": "isTSDBMode", - "description": [ - "\nreturns true if dataview contains TSDB fields" - ], - "signature": [ - "() => boolean" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [] - }, - { - "parentPluginId": "dataViews", - "id": "def-public.DataView.isTimeBased", - "type": "Function", - "tags": [], - "label": "isTimeBased", - "description": [ - "\nDoes the data view have a timestamp field?" - ], - "signature": [ - "() => this is ", + "plugin": "data", + "path": "src/plugins/data/common/search/aggs/param_types/field.ts" + }, { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.TimeBasedDataView", - "text": "TimeBasedDataView" - } - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [] - }, - { - "parentPluginId": "dataViews", - "id": "def-public.DataView.isTimeNanosBased", - "type": "Function", - "tags": [], - "label": "isTimeNanosBased", - "description": [ - "\nDoes the data view have a timestamp field and is it a date nanos field?" - ], - "signature": [ - "() => this is ", + "plugin": "dataViewEditor", + "path": "src/plugins/data_view_editor/public/components/data_view_editor_flyout_content.tsx" + }, { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.TimeBasedDataView", - "text": "TimeBasedDataView" - } - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [] - }, - { - "parentPluginId": "dataViews", - "id": "def-public.DataView.getTimeField", - "type": "Function", - "tags": [], - "label": "getTimeField", - "description": [ - "\nGet timestamp field as DataViewField or return undefined" - ], - "signature": [ - "() => ", + "plugin": "unifiedSearch", + "path": "src/plugins/unified_search/public/autocomplete/providers/value_suggestion_provider.ts" + }, { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataViewField", - "text": "DataViewField" + "plugin": "unifiedSearch", + "path": "src/plugins/unified_search/public/query_string_input/fetch_index_patterns.ts" }, - " | undefined" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [] - }, - { - "parentPluginId": "dataViews", - "id": "def-public.DataView.getFieldByName", - "type": "Function", - "tags": [], - "label": "getFieldByName", - "description": [ - "\nGet field by name." - ], - "signature": [ - "(name: string) => ", { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataViewField", - "text": "DataViewField" + "plugin": "unifiedSearch", + "path": "src/plugins/unified_search/public/dataview_picker/change_dataview.tsx" }, - " | undefined" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ { - "parentPluginId": "dataViews", - "id": "def-public.DataView.getFieldByName.$1", - "type": "string", - "tags": [], - "label": "name", - "description": [ - "field name" - ], - "signature": [ - "string" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "dataViews", - "id": "def-public.DataView.getAggregationRestrictions", - "type": "Function", - "tags": [], - "label": "getAggregationRestrictions", - "description": [ - "\nGet aggregation restrictions. Rollup fields can only perform a subset of aggregations." - ], - "signature": [ - "() => Record | undefined" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [] - }, - { - "parentPluginId": "dataViews", - "id": "def-public.DataView.getAsSavedObjectBody", - "type": "Function", - "tags": [], - "label": "getAsSavedObjectBody", - "description": [ - "\nReturns index pattern as saved object body for saving" - ], - "signature": [ - "() => ", { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataViewAttributes", - "text": "DataViewAttributes" - } - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [] - }, - { - "parentPluginId": "dataViews", - "id": "def-public.DataView.getFormatterForField", - "type": "Function", - "tags": [], - "label": "getFormatterForField", - "description": [ - "\nProvide a field, get its formatter" - ], - "signature": [ - "(field: ", + "plugin": "savedObjectsManagement", + "path": "src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx" + }, { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.FieldSpec", - "text": "FieldSpec" + "plugin": "unifiedFieldList", + "path": "src/plugins/unified_field_list/public/services/field_stats/load_field_stats.ts" }, - " | ", { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataViewField", - "text": "DataViewField" + "plugin": "unifiedFieldList", + "path": "src/plugins/unified_field_list/common/utils/field_existing_utils.ts" }, - ") => ", { - "pluginId": "fieldFormats", - "scope": "common", - "docId": "kibFieldFormatsPluginApi", - "section": "def-common.FieldFormat", - "text": "FieldFormat" - } - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ + "plugin": "unifiedFieldList", + "path": "src/plugins/unified_field_list/common/utils/field_existing_utils.ts" + }, { - "parentPluginId": "dataViews", - "id": "def-public.DataView.getFormatterForField.$1", - "type": "CompoundType", - "tags": [], - "label": "field", - "description": [ - "field to get formatter for" - ], - "signature": [ - { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.FieldSpec", - "text": "FieldSpec" - }, - " | ", - { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataViewField", - "text": "DataViewField" - } - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "dataViews", - "id": "def-public.DataView.addRuntimeField", - "type": "Function", - "tags": [], - "label": "addRuntimeField", - "description": [ - "\nAdd a runtime field - Appended to existing mapped field or a new field is\ncreated as appropriate." - ], - "signature": [ - "(name: string, runtimeField: ", + "plugin": "unifiedFieldList", + "path": "src/plugins/unified_field_list/common/utils/field_existing_utils.ts" + }, { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.RuntimeField", - "text": "RuntimeField" + "plugin": "discover", + "path": "src/plugins/discover/public/hooks/use_es_doc_search.ts" }, - ") => ", { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataViewField", - "text": "DataViewField" + "plugin": "discover", + "path": "src/plugins/discover/public/application/main/utils/resolve_data_view.ts" }, - "[]" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ { - "parentPluginId": "dataViews", - "id": "def-public.DataView.addRuntimeField.$1", - "type": "string", - "tags": [], - "label": "name", - "description": [ - "Field name" - ], - "signature": [ - "string" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true + "plugin": "discover", + "path": "src/plugins/discover/public/application/main/utils/resolve_data_view.ts" }, { - "parentPluginId": "dataViews", - "id": "def-public.DataView.addRuntimeField.$2", - "type": "Object", - "tags": [], - "label": "runtimeField", - "description": [ - "Runtime field definition" - ], - "signature": [ - { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.RuntimeField", - "text": "RuntimeField" - } - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "dataViews", - "id": "def-public.DataView.hasRuntimeField", - "type": "Function", - "tags": [], - "label": "hasRuntimeField", - "description": [ - "\nChecks if runtime field exists" - ], - "signature": [ - "(name: string) => boolean" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ + "plugin": "discover", + "path": "src/plugins/discover/public/application/main/components/sidebar/discover_sidebar.tsx" + }, { - "parentPluginId": "dataViews", - "id": "def-public.DataView.hasRuntimeField.$1", - "type": "string", - "tags": [], - "label": "name", - "description": [ - "field name" - ], - "signature": [ - "string" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "dataViews", - "id": "def-public.DataView.getRuntimeField", - "type": "Function", - "tags": [], - "label": "getRuntimeField", - "description": [ - "\nReturns runtime field if exists" - ], - "signature": [ - "(name: string) => ", + "plugin": "discover", + "path": "src/plugins/discover/public/application/main/components/top_nav/discover_topnav.tsx" + }, { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.RuntimeField", - "text": "RuntimeField" + "plugin": "aiops", + "path": "x-pack/plugins/aiops/public/hooks/use_data.ts" }, - " | null" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ { - "parentPluginId": "dataViews", - "id": "def-public.DataView.getRuntimeField.$1", - "type": "string", - "tags": [], - "label": "name", - "description": [ - "Runtime field name" - ], - "signature": [ - "string" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "dataViews", - "id": "def-public.DataView.getAllRuntimeFields", - "type": "Function", - "tags": [], - "label": "getAllRuntimeFields", - "description": [ - "\nGet all runtime field definitions.\nNOTE: this does not strip out runtime fields that match mapped field names" - ], - "signature": [ - "() => Record" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [ - "map of runtime field definitions by field name" - ] - }, - { - "parentPluginId": "dataViews", - "id": "def-public.DataView.getFieldsByRuntimeFieldName", - "type": "Function", - "tags": [], - "label": "getFieldsByRuntimeFieldName", - "description": [ - "\nReturns data view fields backed by runtime fields." - ], - "signature": [ - "(name: string) => Record | undefined" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ { - "parentPluginId": "dataViews", - "id": "def-public.DataView.getFieldsByRuntimeFieldName.$1", - "type": "string", - "tags": [], - "label": "name", - "description": [ - "runtime field name" - ], - "signature": [ - "string" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [ - "map of DataViewFields (that are runtime fields) by field name" - ] - }, - { - "parentPluginId": "dataViews", - "id": "def-public.DataView.replaceAllRuntimeFields", - "type": "Function", - "tags": [], - "label": "replaceAllRuntimeFields", - "description": [ - "\nReplaces all existing runtime fields with new fields." - ], - "signature": [ - "(newFields: Record) => void" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ { - "parentPluginId": "dataViews", - "id": "def-public.DataView.replaceAllRuntimeFields.$1", - "type": "Object", - "tags": [], - "label": "newFields", - "description": [ - "Map of runtime field definitions by field name" - ], - "signature": [ - "Record" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "dataViews", - "id": "def-public.DataView.removeRuntimeField", - "type": "Function", - "tags": [], - "label": "removeRuntimeField", - "description": [ - "\nRemove a runtime field - removed from mapped field or removed unmapped\nfield as appropriate. Doesn't clear associated field attributes." - ], - "signature": [ - "(name: string) => void" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ + "plugin": "controls", + "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" + }, { - "parentPluginId": "dataViews", - "id": "def-public.DataView.removeRuntimeField.$1", - "type": "string", - "tags": [], - "label": "name", - "description": [ - "- Field name to remove" - ], - "signature": [ - "string" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "dataViews", - "id": "def-public.DataView.getRuntimeMappings", - "type": "Function", - "tags": [], - "label": "getRuntimeMappings", - "description": [ - "\nReturn the \"runtime_mappings\" section of the ES search query." - ], - "signature": [ - "() => ", - "MappingRuntimeFields" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [] - }, - { - "parentPluginId": "dataViews", - "id": "def-public.DataView.getFormatterForFieldNoDefault", - "type": "Function", - "tags": [], - "label": "getFormatterForFieldNoDefault", - "description": [ - "\nGet formatter for a given field name. Return undefined if none exists." - ], - "signature": [ - "(fieldname: string) => ", + "plugin": "lens", + "path": "x-pack/plugins/lens/public/data_views_service/loader.ts" + }, { - "pluginId": "fieldFormats", - "scope": "common", - "docId": "kibFieldFormatsPluginApi", - "section": "def-common.FieldFormat", - "text": "FieldFormat" + "plugin": "lens", + "path": "x-pack/plugins/lens/public/app_plugin/lens_top_nav.tsx" }, - " | undefined" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ { - "parentPluginId": "dataViews", - "id": "def-public.DataView.getFormatterForFieldNoDefault.$1", - "type": "string", - "tags": [], - "label": "fieldname", - "description": [ - "name of field to get formatter for" - ], - "signature": [ - "string" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "dataViews", - "id": "def-public.DataView.setFieldAttrs", - "type": "Function", - "tags": [], - "label": "setFieldAttrs", - "description": [ - "\nSet field attribute" - ], - "signature": [ - "(fieldName: string, attrName: K, value: ", { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.FieldAttrSet", - "text": "FieldAttrSet" + "plugin": "observability", + "path": "x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/use_filter_values.ts" }, - "[K]) => void" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ { - "parentPluginId": "dataViews", - "id": "def-public.DataView.setFieldAttrs.$1", - "type": "string", - "tags": [], - "label": "fieldName", - "description": [ - "name of field to set attribute on" - ], - "signature": [ - "string" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true + "plugin": "observability", + "path": "x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/filter_value_btn.tsx" }, { - "parentPluginId": "dataViews", - "id": "def-public.DataView.setFieldAttrs.$2", - "type": "Uncategorized", - "tags": [], - "label": "attrName", - "description": [ - "name of attribute to set" - ], - "signature": [ - "K" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true + "plugin": "infra", + "path": "x-pack/plugins/infra/common/log_views/resolved_log_view.ts" }, { - "parentPluginId": "dataViews", - "id": "def-public.DataView.setFieldAttrs.$3", - "type": "Uncategorized", - "tags": [], - "label": "value", - "description": [ - "value of attribute" - ], - "signature": [ - { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.FieldAttrSet", - "text": "FieldAttrSet" - }, - "[K]" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "dataViews", - "id": "def-public.DataView.setFieldCustomLabel", - "type": "Function", - "tags": [], - "label": "setFieldCustomLabel", - "description": [ - "\nSet field custom label" - ], - "signature": [ - "(fieldName: string, customLabel: string | null | undefined) => void" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ + "plugin": "maps", + "path": "x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.tsx" + }, { - "parentPluginId": "dataViews", - "id": "def-public.DataView.setFieldCustomLabel.$1", - "type": "string", - "tags": [], - "label": "fieldName", - "description": [ - "name of field to set custom label on" - ], - "signature": [ - "string" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true + "plugin": "maps", + "path": "x-pack/plugins/maps/public/classes/sources/es_search_source/util/scaling_form.tsx" }, { - "parentPluginId": "dataViews", - "id": "def-public.DataView.setFieldCustomLabel.$2", - "type": "CompoundType", - "tags": [], - "label": "customLabel", - "description": [ - "custom label value. If undefined, custom label is removed" - ], - "signature": [ - "string | null | undefined" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": false - } - ], - "returnComment": [] - }, - { - "parentPluginId": "dataViews", - "id": "def-public.DataView.setFieldCount", - "type": "Function", - "tags": [], - "label": "setFieldCount", - "description": [ - "\nSet field count" - ], - "signature": [ - "(fieldName: string, count: number | null | undefined) => void" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ + "plugin": "maps", + "path": "x-pack/plugins/maps/public/classes/sources/es_search_source/top_hits/top_hits_form.tsx" + }, { - "parentPluginId": "dataViews", - "id": "def-public.DataView.setFieldCount.$1", - "type": "string", - "tags": [], - "label": "fieldName", - "description": [ - "name of field to set count on" - ], - "signature": [ - "string" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true + "plugin": "maps", + "path": "x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx" }, { - "parentPluginId": "dataViews", - "id": "def-public.DataView.setFieldCount.$2", - "type": "CompoundType", - "tags": [], - "label": "count", - "description": [ - "count value. If undefined, count is removed" - ], - "signature": [ - "number | null | undefined" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": false - } - ], - "returnComment": [] - }, - { - "parentPluginId": "dataViews", - "id": "def-public.DataView.setFieldFormat", - "type": "Function", - "tags": [], - "label": "setFieldFormat", - "description": [ - "\nSet field formatter" - ], - "signature": [ - "(fieldName: string, format: ", + "plugin": "maps", + "path": "x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx" + }, { - "pluginId": "fieldFormats", - "scope": "common", - "docId": "kibFieldFormatsPluginApi", - "section": "def-common.SerializedFieldFormat", - "text": "SerializedFieldFormat" + "plugin": "maps", + "path": "x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx" }, - "<{}, ", - "SerializableRecord", - ">) => void" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ { - "parentPluginId": "dataViews", - "id": "def-public.DataView.setFieldFormat.$1", - "type": "string", - "tags": [], - "label": "fieldName", - "description": [ - "name of field to set format on" - ], - "signature": [ - "string" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true + "plugin": "maps", + "path": "x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx" }, { - "parentPluginId": "dataViews", - "id": "def-public.DataView.setFieldFormat.$2", - "type": "Object", - "tags": [], - "label": "format", - "description": [ - "field format in serialized form" - ], - "signature": [ - { - "pluginId": "fieldFormats", - "scope": "common", - "docId": "kibFieldFormatsPluginApi", - "section": "def-common.SerializedFieldFormat", - "text": "SerializedFieldFormat" - }, - "<{}, ", - "SerializableRecord", - ">" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "dataViews", - "id": "def-public.DataView.deleteFieldFormat", - "type": "Function", - "tags": [], - "label": "deleteFieldFormat", - "description": [ - "\nRemove field format from the field format map." - ], - "signature": [ - "(fieldName: string) => void" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ + "plugin": "maps", + "path": "x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx" + }, { - "parentPluginId": "dataViews", - "id": "def-public.DataView.deleteFieldFormat.$1", - "type": "string", - "tags": [], - "label": "fieldName", - "description": [ - "field name associated with the format for removal" - ], - "signature": [ - "string" - ], - "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - } - ], - "initialIsOpen": false - }, - { - "parentPluginId": "dataViews", - "id": "def-public.DataViewField", - "type": "Class", - "tags": [], - "label": "DataViewField", - "description": [ - "\nData view field class" - ], - "signature": [ - { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataViewField", - "text": "DataViewField" - }, - " implements ", - "DataViewFieldBase" - ], - "path": "src/plugins/data_views/common/fields/data_view_field.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "dataViews", - "id": "def-public.DataViewField.spec", - "type": "CompoundType", - "tags": [], - "label": "spec", - "description": [], - "signature": [ - "DataViewFieldBase", - " & { count?: number | undefined; conflictDescriptions?: Record | undefined; format?: ", + "plugin": "maps", + "path": "x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx" + }, { - "pluginId": "fieldFormats", - "scope": "common", - "docId": "kibFieldFormatsPluginApi", - "section": "def-common.SerializedFieldFormat", - "text": "SerializedFieldFormat" + "plugin": "maps", + "path": "x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx" }, - "<{}, ", - "SerializableRecord", - "> | undefined; esTypes?: string[] | undefined; searchable: boolean; aggregatable: boolean; readFromDocValues?: boolean | undefined; indexed?: boolean | undefined; customLabel?: string | undefined; runtimeField?: ", { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.RuntimeFieldSpec", - "text": "RuntimeFieldSpec" + "plugin": "maps", + "path": "x-pack/plugins/maps/public/trigger_actions/visualize_geo_field_action.ts" }, - " | undefined; fixedInterval?: string[] | undefined; timeZone?: string[] | undefined; timeSeriesDimension?: boolean | undefined; timeSeriesMetric?: \"gauge\" | \"histogram\" | \"summary\" | \"counter\" | undefined; shortDotsEnable?: boolean | undefined; isMapped?: boolean | undefined; parentName?: string | undefined; }" - ], - "path": "src/plugins/data_views/common/fields/data_view_field.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "dataViews", - "id": "def-public.DataViewField.Unnamed", - "type": "Function", - "tags": [ - "constructor" - ], - "label": "Constructor", - "description": [ - "\nDataView constructor" - ], - "signature": [ - "any" - ], - "path": "src/plugins/data_views/common/fields/data_view_field.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ { - "parentPluginId": "dataViews", - "id": "def-public.DataViewField.Unnamed.$1", - "type": "CompoundType", - "tags": [], - "label": "spec", - "description": [ - "Configuration for the field" - ], - "signature": [ - { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.FieldSpec", - "text": "FieldSpec" - } - ], - "path": "src/plugins/data_views/common/fields/data_view_field.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "dataViews", - "id": "def-public.DataViewField.count", - "type": "number", - "tags": [], - "label": "count", - "description": [ - "\nCount is used for field popularity in discover." - ], - "path": "src/plugins/data_views/common/fields/data_view_field.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "dataViews", - "id": "def-public.DataViewField.count", - "type": "number", - "tags": [], - "label": "count", - "description": [ - "\nSet count, which is used for field popularity in discover." - ], - "path": "src/plugins/data_views/common/fields/data_view_field.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "dataViews", - "id": "def-public.DataViewField.runtimeField", - "type": "CompoundType", - "tags": [], - "label": "runtimeField", - "description": [ - "\nReturns runtime field definition or undefined if field is not runtime field." - ], - "signature": [ + "plugin": "dataVisualizer", + "path": "x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/full_time_range_selector/full_time_range_selector_service.ts" + }, { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.RuntimeFieldSpec", - "text": "RuntimeFieldSpec" + "plugin": "dataVisualizer", + "path": "x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/actions_panel/actions_panel.tsx" }, - " | undefined" - ], - "path": "src/plugins/data_views/common/fields/data_view_field.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "dataViews", - "id": "def-public.DataViewField.runtimeField", - "type": "CompoundType", - "tags": [], - "label": "runtimeField", - "description": [ - "\nSets runtime field definition or unsets if undefined is provided." - ], - "signature": [ { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.RuntimeFieldSpec", - "text": "RuntimeFieldSpec" + "plugin": "dataVisualizer", + "path": "x-pack/plugins/data_visualizer/public/application/index_data_visualizer/hooks/use_data_visualizer_grid_data.ts" }, - " | undefined" - ], - "path": "src/plugins/data_views/common/fields/data_view_field.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "dataViews", - "id": "def-public.DataViewField.script", - "type": "string", - "tags": [], - "label": "script", - "description": [ - "\nScript field code" - ], - "signature": [ - "string | undefined" - ], - "path": "src/plugins/data_views/common/fields/data_view_field.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "dataViews", - "id": "def-public.DataViewField.script", - "type": "string", - "tags": [], - "label": "script", - "description": [ - "\nSets scripted field painless code" - ], - "signature": [ - "string | undefined" - ], - "path": "src/plugins/data_views/common/fields/data_view_field.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "dataViews", - "id": "def-public.DataViewField.lang", - "type": "string", - "tags": [], - "label": "lang", - "description": [ - "\nScript field language" - ], - "signature": [ - "string | undefined" - ], - "path": "src/plugins/data_views/common/fields/data_view_field.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "dataViews", - "id": "def-public.DataViewField.lang", - "type": "string", - "tags": [], - "label": "lang", - "description": [ - "\nSets scripted field langauge." - ], - "signature": [ - "string | undefined" - ], - "path": "src/plugins/data_views/common/fields/data_view_field.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "dataViews", - "id": "def-public.DataViewField.customLabel", - "type": "string", - "tags": [], - "label": "customLabel", - "description": [ - "\nReturns custom label if set, otherwise undefined." - ], - "signature": [ - "string | undefined" - ], - "path": "src/plugins/data_views/common/fields/data_view_field.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "dataViews", + { + "plugin": "dataVisualizer", + "path": "x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/index_data_visualizer_view.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/util/index_utils.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/util/index_utils.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/util/index_utils.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/services/new_job_capabilities/new_job_capabilities_service_analytics.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/services/new_job_capabilities/new_job_capabilities_service_analytics.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_details.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/datavisualizer/index_based/data_loader/data_loader.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/page.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_clone/clone_action_name.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/index_or_search/preconfigured_job_redirect.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/job_type/page.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/job_type/page.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/job_type/page.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/services/new_job_capabilities/new_job_capabilities_service.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/services/new_job_capabilities/new_job_capabilities_service.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/job_creator.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/common/chart_loader/chart_loader.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/common/results_loader/categorization_examples_loader.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/components/full_time_range_selector/full_time_range_selector_service.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/bucket_span_estimator/estimate_bucket_span.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/components/datafeed_step/components/data_view/change_data_view.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/new_job/wizard_steps.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/recognize/components/job_settings_form.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/recognize/page.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/recognize/page.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/quick_create_job.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/use_outlier_data.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/use_exploration_results.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/source_selection/source_selection.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/embeddables/anomaly_charts/anomaly_charts_embeddable.tsx" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/infra/public/pages/logs/settings/validation_errors.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/infra/public/pages/logs/settings/validation_errors.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/infra/public/pages/logs/settings/validation_errors.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/infra/public/pages/logs/settings/validation_errors.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/filter_dataset.tsx" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/filter_log_level.tsx" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/query_bar.tsx" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/public/applications/fleet/components/search_bar.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/server/models/data_frame_analytics/index_patterns.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/server/models/job_service/new_job_caps/rollup.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/server/lib/alerts/alerting_service.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.ts" + }, + { + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/common/index_patterns_utils.ts" + }, + { + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/common/index_patterns_utils.ts" + }, + { + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/server/lib/get_fields.ts" + }, + { + "plugin": "apm", + "path": "x-pack/plugins/apm/server/routes/data_view/create_static_data_view.ts" + }, + { + "plugin": "reporting", + "path": "x-pack/plugins/reporting/server/export_types/csv_searchsource/generate_csv/generate_csv.ts" + }, + { + "plugin": "graph", + "path": "x-pack/plugins/graph/public/state_management/datasource.sagas.ts" + }, + { + "plugin": "graph", + "path": "x-pack/plugins/graph/public/state_management/persistence.ts" + }, + { + "plugin": "graph", + "path": "x-pack/plugins/graph/public/state_management/persistence.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/detections/components/rules/eql_query_bar/validators.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/detections/components/rules/step_define_rule/index.tsx" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/index.tsx" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/sourcerer/routes/index.ts" + }, + { + "plugin": "stackAlerts", + "path": "x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/expressions/boundary_index_expression.tsx" + }, + { + "plugin": "stackAlerts", + "path": "x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/expressions/entity_index_expression.tsx" + }, + { + "plugin": "stackAlerts", + "path": "x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/index.tsx" + }, + { + "plugin": "stackAlerts", + "path": "x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/index.tsx" + }, + { + "plugin": "stackAlerts", + "path": "x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/index.tsx" + }, + { + "plugin": "stackAlerts", + "path": "x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/index.tsx" + }, + { + "plugin": "stackAlerts", + "path": "x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/index.tsx" + }, + { + "plugin": "stackAlerts", + "path": "x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/index.tsx" + }, + { + "plugin": "stackAlerts", + "path": "x-pack/plugins/stack_alerts/public/alert_types/es_query/expression/search_source_expression_form.tsx" + }, + { + "plugin": "synthetics", + "path": "x-pack/plugins/synthetics/public/legacy_uptime/components/overview/filter_group/filter_group.tsx" + }, + { + "plugin": "synthetics", + "path": "x-pack/plugins/synthetics/public/legacy_uptime/components/overview/alerts/monitor_expressions/filters_expression_select.tsx" + }, + { + "plugin": "timelines", + "path": "x-pack/plugins/timelines/server/search_strategy/index_fields/index.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_details/step_details_form.tsx" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/wizard/wizard.tsx" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/filter_agg/components/filter_term_form.tsx" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/hooks/use_index_data.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/hooks/use_index_data.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/hooks/use_index_data.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/hooks/use_index_data.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/hooks/use_index_data.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/hooks/use_index_data.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/hooks/use_index_data.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/hooks/use_step_define_form.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/hooks/use_step_define_form.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_form.tsx" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_form.tsx" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_form.tsx" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_form.tsx" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_summary.tsx" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_summary.tsx" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_summary.tsx" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/hooks/use_search_items/common.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/services/es_index_service.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/server/routes/api/transforms.ts" + }, + { + "plugin": "upgradeAssistant", + "path": "x-pack/plugins/upgrade_assistant/public/application/components/es_deprecation_logs/fix_deprecation_logs/external_links.tsx" + }, + { + "plugin": "ux", + "path": "x-pack/plugins/ux/public/components/app/rum_dashboard/local_uifilters/use_data_view.ts" + }, + { + "plugin": "graph", + "path": "x-pack/plugins/graph/public/state_management/datasource.test.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/infra/common/dependency_mocks/index_patterns.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/infra/common/dependency_mocks/index_patterns.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/infra/common/dependency_mocks/index_patterns.ts" + }, + { + "plugin": "maps", + "path": "x-pack/plugins/maps/public/classes/tooltips/es_tooltip_property.test.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/services/new_job_capabilities/remove_nested_field_children.test.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/common.test.ts" + }, + { + "plugin": "controls", + "path": "src/plugins/controls/public/services/data_views/data_views.story.ts" + }, + { + "plugin": "dataViewManagement", + "path": "src/plugins/data_view_management/public/components/edit_index_pattern/edit_index_pattern.tsx" + }, + { + "plugin": "dataViewManagement", + "path": "src/plugins/data_view_management/public/components/edit_index_pattern/edit_index_pattern.tsx" + }, + { + "plugin": "dataViewManagement", + "path": "src/plugins/data_view_management/public/components/field_editor/components/scripting_help/test_script.tsx" + }, + { + "plugin": "dataViewManagement", + "path": "src/plugins/data_view_management/public/components/field_editor/field_editor.tsx" + }, + { + "plugin": "dataViewManagement", + "path": "src/plugins/data_view_management/public/components/edit_index_pattern/create_edit_field/create_edit_field.tsx" + }, + { + "plugin": "inputControlVis", + "path": "src/plugins/input_control_vis/public/control/list_control_factory.ts" + }, + { + "plugin": "inputControlVis", + "path": "src/plugins/input_control_vis/public/control/range_control_factory.ts" + }, + { + "plugin": "unifiedFieldList", + "path": "src/plugins/unified_field_list/server/routes/field_stats.ts" + }, + { + "plugin": "unifiedFieldList", + "path": "src/plugins/unified_field_list/server/routes/field_stats.ts" + }, + { + "plugin": "visDefaultEditor", + "path": "src/plugins/vis_default_editor/public/components/controls/field.tsx" + }, + { + "plugin": "visDefaultEditor", + "path": "src/plugins/vis_default_editor/public/components/controls/field.tsx" + }, + { + "plugin": "visDefaultEditor", + "path": "src/plugins/vis_default_editor/public/components/agg_select.tsx" + }, + { + "plugin": "inputControlVis", + "path": "src/plugins/input_control_vis/public/test_utils/get_index_pattern_mock.ts" + }, + { + "plugin": "visTypeTimelion", + "path": "src/plugins/vis_types/timelion/public/helpers/arg_value_suggestions.ts" + }, + { + "plugin": "visTypeTimelion", + "path": "src/plugins/vis_types/timelion/public/helpers/arg_value_suggestions.ts" + }, + { + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/common/index_patterns_utils.test.ts" + }, + { + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/common/index_patterns_utils.test.ts" + }, + { + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/public/application/components/lib/convert_series_to_datatable.ts" + }, + { + "plugin": "visTypeVega", + "path": "src/plugins/vis_types/vega/public/data_model/search_api.ts" + }, + { + "plugin": "data", + "path": "src/plugins/data/common/search/aggs/agg_config.test.ts" + }, + { + "plugin": "data", + "path": "src/plugins/data/common/search/aggs/buckets/_terms_other_bucket_helper.test.ts" + }, + { + "plugin": "data", + "path": "src/plugins/data/common/search/aggs/buckets/multi_terms.test.ts" + }, + { + "plugin": "data", + "path": "src/plugins/data/common/search/aggs/buckets/multi_terms.test.ts" + }, + { + "plugin": "data", + "path": "src/plugins/data/common/search/aggs/buckets/rare_terms.test.ts" + }, + { + "plugin": "data", + "path": "src/plugins/data/common/search/aggs/buckets/terms.test.ts" + }, + { + "plugin": "data", + "path": "src/plugins/data/common/search/aggs/buckets/terms.test.ts" + }, + { + "plugin": "data", + "path": "src/plugins/data/public/query/filter_manager/lib/get_display_value.test.ts" + }, + { + "plugin": "discover", + "path": "src/plugins/discover/public/application/main/hooks/use_adhoc_data_views.test.ts" + }, + { + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/public/application/components/lib/convert_series_to_datatable.test.ts" + }, + { + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/public/convert_to_lens/lib/datasource/get_datasource_info.test.ts" + }, + { + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/public/convert_to_lens/lib/datasource/get_datasource_info.test.ts" + }, + { + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/public/convert_to_lens/lib/datasource/get_datasource_info.test.ts" + }, + { + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/server/lib/search_strategies/lib/cached_index_pattern_fetcher.test.ts" + }, + { + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/server/lib/search_strategies/lib/cached_index_pattern_fetcher.test.ts" + }, + { + "plugin": "discover", + "path": "src/plugins/discover/public/application/main/components/layout/__stories__/get_layout_props.ts" + }, + { + "plugin": "lens", + "path": "x-pack/plugins/lens/public/data_views_service/loader.test.ts" + }, + { + "plugin": "lens", + "path": "x-pack/plugins/lens/public/data_views_service/loader.test.ts" + }, + { + "plugin": "lens", + "path": "x-pack/plugins/lens/public/data_views_service/loader.test.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/sourcerer/routes/index.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/sourcerer/routes/index.ts" + } + ] + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.fieldFormatMap", + "type": "Object", + "tags": [], + "label": "fieldFormatMap", + "description": [ + "\nMap of field formats by field name" + ], + "signature": [ + "{ [x: string]: ", + { + "pluginId": "fieldFormats", + "scope": "common", + "docId": "kibFieldFormatsPluginApi", + "section": "def-common.SerializedFieldFormat", + "text": "SerializedFieldFormat" + }, + "<{}, ", + "SerializableRecord", + ">; }" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.typeMeta", + "type": "Object", + "tags": [], + "label": "typeMeta", + "description": [ + "\nOnly used by rollup indices, used by rollup specific endpoint to load field list." + ], + "signature": [ + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.TypeMeta", + "text": "TypeMeta" + }, + " | undefined" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.fields", + "type": "CompoundType", + "tags": [], + "label": "fields", + "description": [ + "\nField list, in extended array format" + ], + "signature": [ + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.IIndexPatternFieldList", + "text": "IIndexPatternFieldList" + }, + " & { toSpec: () => ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewFieldMap", + "text": "DataViewFieldMap" + }, + "; }" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.timeFieldName", + "type": "string", + "tags": [], + "label": "timeFieldName", + "description": [ + "\nTimestamp field name" + ], + "signature": [ + "string | undefined" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.type", + "type": "string", + "tags": [], + "label": "type", + "description": [ + "\nType is used to identify rollup index patterns." + ], + "signature": [ + "string | undefined" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.flattenHit", + "type": "Function", + "tags": [ + "deprecated" + ], + "label": "flattenHit", + "description": [], + "signature": [ + "(hit: Record, deep?: boolean | undefined) => Record" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": true, + "trackAdoption": false, + "references": [ + { + "plugin": "maps", + "path": "x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx" + }, + { + "plugin": "maps", + "path": "x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx" + } + ], + "returnComment": [], + "children": [ + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.flattenHit.$1", + "type": "Object", + "tags": [], + "label": "hit", + "description": [], + "signature": [ + "{ [x: string]: unknown[]; }" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.flattenHit.$2", + "type": "CompoundType", + "tags": [], + "label": "deep", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false + } + ] + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.metaFields", + "type": "Array", + "tags": [], + "label": "metaFields", + "description": [ + "\nList of meta fields by name" + ], + "signature": [ + "string[]" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.version", + "type": "string", + "tags": [], + "label": "version", + "description": [ + "\nSavedObject version" + ], + "signature": [ + "string | undefined" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.sourceFilters", + "type": "Array", + "tags": [], + "label": "sourceFilters", + "description": [ + "\nArray of filters - hides fields in discover" + ], + "signature": [ + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.SourceFilter", + "text": "SourceFilter" + }, + "[] | undefined" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.namespaces", + "type": "Array", + "tags": [], + "label": "namespaces", + "description": [ + "\nArray of namespace ids" + ], + "signature": [ + "string[]" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.allowNoIndex", + "type": "boolean", + "tags": [], + "label": "allowNoIndex", + "description": [ + "\nPrevents errors when index pattern exists before indices" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.name", + "type": "string", + "tags": [], + "label": "name", + "description": [ + "\nName of the data view. Human readable name used to differentiate data view." + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.matchedIndices", + "type": "Array", + "tags": [], + "label": "matchedIndices", + "description": [], + "signature": [ + "string[]" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.Unnamed", + "type": "Function", + "tags": [], + "label": "Constructor", + "description": [ + "\nconstructor" + ], + "signature": [ + "any" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.Unnamed.$1", + "type": "Object", + "tags": [], + "label": "config", + "description": [ + "- config data and dependencies" + ], + "signature": [ + "DataViewDeps" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.getName", + "type": "Function", + "tags": [], + "label": "getName", + "description": [ + "\nGet name of Data View" + ], + "signature": [ + "() => string" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.getIndexPattern", + "type": "Function", + "tags": [], + "label": "getIndexPattern", + "description": [ + "\nGet index pattern" + ], + "signature": [ + "() => string" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [ + "index pattern string" + ] + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.setIndexPattern", + "type": "Function", + "tags": [], + "label": "setIndexPattern", + "description": [ + "\nSet index pattern" + ], + "signature": [ + "(indexPattern: string) => void" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.setIndexPattern.$1", + "type": "string", + "tags": [], + "label": "indexPattern", + "description": [], + "signature": [ + "string" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.getOriginalSavedObjectBody", + "type": "Function", + "tags": [], + "label": "getOriginalSavedObjectBody", + "description": [ + "\nGet last saved saved object fields" + ], + "signature": [ + "() => { fieldAttrs?: string | undefined; title?: string | undefined; timeFieldName?: string | undefined; fields?: string | undefined; sourceFilters?: string | undefined; fieldFormatMap?: string | undefined; typeMeta?: string | undefined; type?: string | undefined; }" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.resetOriginalSavedObjectBody", + "type": "Function", + "tags": [], + "label": "resetOriginalSavedObjectBody", + "description": [ + "\nReset last saved saved object fields. Used after saving." + ], + "signature": [ + "() => void" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.getFieldAttrs", + "type": "Function", + "tags": [], + "label": "getFieldAttrs", + "description": [ + "\nReturns field attributes map" + ], + "signature": [ + "() => { [x: string]: ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.FieldAttrSet", + "text": "FieldAttrSet" + }, + "; }" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.getComputedFields", + "type": "Function", + "tags": [], + "label": "getComputedFields", + "description": [ + "\nReturns scripted fields" + ], + "signature": [ + "() => { storedFields: string[]; scriptFields: Record; docvalueFields: { field: string; format: string; }[]; runtimeFields: ", + "MappingRuntimeFields", + "; }" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.isPersisted", + "type": "Function", + "tags": [], + "label": "isPersisted", + "description": [], + "signature": [ + "() => boolean" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.toSpec", + "type": "Function", + "tags": [], + "label": "toSpec", + "description": [ + "\nCreates static representation of the data view." + ], + "signature": [ + "(includeFields?: boolean) => ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewSpec", + "text": "DataViewSpec" + } + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.toSpec.$1", + "type": "boolean", + "tags": [], + "label": "includeFields", + "description": [ + "Whether or not to include the `fields` list as part of this spec. If not included, the list\nwill be fetched from Elasticsearch when instantiating a new Data View with this spec." + ], + "signature": [ + "boolean" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.getSourceFiltering", + "type": "Function", + "tags": [], + "label": "getSourceFiltering", + "description": [ + "\nGet the source filtering configuration for that index." + ], + "signature": [ + "() => { excludes: string[]; }" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.removeScriptedField", + "type": "Function", + "tags": [ + "deprecated" + ], + "label": "removeScriptedField", + "description": [ + "\nRemoves scripted field from field list." + ], + "signature": [ + "(fieldName: string) => void" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": true, + "trackAdoption": false, + "references": [ + { + "plugin": "dataViewManagement", + "path": "src/plugins/data_view_management/public/components/edit_index_pattern/scripted_fields_table/scripted_fields_table.tsx" + }, + { + "plugin": "dataViewManagement", + "path": "src/plugins/data_view_management/public/components/field_editor/field_editor.tsx" + } + ], + "children": [ + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.removeScriptedField.$1", + "type": "string", + "tags": [], + "label": "fieldName", + "description": [ + "name of scripted field to remove" + ], + "signature": [ + "string" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.getNonScriptedFields", + "type": "Function", + "tags": [ + "deprecated" + ], + "label": "getNonScriptedFields", + "description": [ + "\n" + ], + "signature": [ + "() => ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewField", + "text": "DataViewField" + }, + "[]" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": true, + "trackAdoption": false, + "references": [ + { + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts" + }, + { + "plugin": "graph", + "path": "x-pack/plugins/graph/public/services/persistence/deserialize.ts" + }, + { + "plugin": "graph", + "path": "x-pack/plugins/graph/public/state_management/datasource.test.ts" + }, + { + "plugin": "graph", + "path": "x-pack/plugins/graph/public/services/persistence/deserialize.test.ts" + }, + { + "plugin": "graph", + "path": "x-pack/plugins/graph/public/services/persistence/deserialize.test.ts" + }, + { + "plugin": "dataViewManagement", + "path": "src/plugins/data_view_management/public/components/edit_index_pattern/source_filters_table/components/table/table.tsx" + }, + { + "plugin": "dataViewManagement", + "path": "src/plugins/data_view_management/public/components/edit_index_pattern/edit_index_pattern.tsx" + }, + { + "plugin": "dataViewManagement", + "path": "src/plugins/data_view_management/public/components/edit_index_pattern/edit_index_pattern.tsx" + }, + { + "plugin": "dataViewManagement", + "path": "src/plugins/data_view_management/public/components/edit_index_pattern/edit_index_pattern.tsx" + }, + { + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/public/application/lib/fetch_fields.ts" + } + ], + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.getScriptedFields", + "type": "Function", + "tags": [ + "deprecated" + ], + "label": "getScriptedFields", + "description": [ + "\n" + ], + "signature": [ + "() => ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewField", + "text": "DataViewField" + }, + "[]" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": true, + "trackAdoption": false, + "references": [ + { + "plugin": "dataViewManagement", + "path": "src/plugins/data_view_management/public/components/edit_index_pattern/scripted_fields_table/scripted_fields_table.tsx" + } + ], + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.isTSDBMode", + "type": "Function", + "tags": [], + "label": "isTSDBMode", + "description": [ + "\nreturns true if dataview contains TSDB fields" + ], + "signature": [ + "() => boolean" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.isTimeBased", + "type": "Function", + "tags": [], + "label": "isTimeBased", + "description": [ + "\nDoes the data view have a timestamp field?" + ], + "signature": [ + "() => this is ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.TimeBasedDataView", + "text": "TimeBasedDataView" + } + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.isTimeNanosBased", + "type": "Function", + "tags": [], + "label": "isTimeNanosBased", + "description": [ + "\nDoes the data view have a timestamp field and is it a date nanos field?" + ], + "signature": [ + "() => this is ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.TimeBasedDataView", + "text": "TimeBasedDataView" + } + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.getTimeField", + "type": "Function", + "tags": [], + "label": "getTimeField", + "description": [ + "\nGet timestamp field as DataViewField or return undefined" + ], + "signature": [ + "() => ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewField", + "text": "DataViewField" + }, + " | undefined" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.getFieldByName", + "type": "Function", + "tags": [], + "label": "getFieldByName", + "description": [ + "\nGet field by name." + ], + "signature": [ + "(name: string) => ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewField", + "text": "DataViewField" + }, + " | undefined" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.getFieldByName.$1", + "type": "string", + "tags": [], + "label": "name", + "description": [ + "field name" + ], + "signature": [ + "string" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.getAggregationRestrictions", + "type": "Function", + "tags": [], + "label": "getAggregationRestrictions", + "description": [ + "\nGet aggregation restrictions. Rollup fields can only perform a subset of aggregations." + ], + "signature": [ + "() => Record | undefined" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.getAsSavedObjectBody", + "type": "Function", + "tags": [], + "label": "getAsSavedObjectBody", + "description": [ + "\nReturns index pattern as saved object body for saving" + ], + "signature": [ + "() => ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewAttributes", + "text": "DataViewAttributes" + } + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.getFormatterForField", + "type": "Function", + "tags": [], + "label": "getFormatterForField", + "description": [ + "\nProvide a field, get its formatter" + ], + "signature": [ + "(field: ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.FieldSpec", + "text": "FieldSpec" + }, + " | ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewField", + "text": "DataViewField" + }, + ") => ", + { + "pluginId": "fieldFormats", + "scope": "common", + "docId": "kibFieldFormatsPluginApi", + "section": "def-common.FieldFormat", + "text": "FieldFormat" + } + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.getFormatterForField.$1", + "type": "CompoundType", + "tags": [], + "label": "field", + "description": [ + "field to get formatter for" + ], + "signature": [ + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.FieldSpec", + "text": "FieldSpec" + }, + " | ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewField", + "text": "DataViewField" + } + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.addRuntimeField", + "type": "Function", + "tags": [], + "label": "addRuntimeField", + "description": [ + "\nAdd a runtime field - Appended to existing mapped field or a new field is\ncreated as appropriate." + ], + "signature": [ + "(name: string, runtimeField: ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.RuntimeField", + "text": "RuntimeField" + }, + ") => ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewField", + "text": "DataViewField" + }, + "[]" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.addRuntimeField.$1", + "type": "string", + "tags": [], + "label": "name", + "description": [ + "Field name" + ], + "signature": [ + "string" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.addRuntimeField.$2", + "type": "Object", + "tags": [], + "label": "runtimeField", + "description": [ + "Runtime field definition" + ], + "signature": [ + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.RuntimeField", + "text": "RuntimeField" + } + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.hasRuntimeField", + "type": "Function", + "tags": [], + "label": "hasRuntimeField", + "description": [ + "\nChecks if runtime field exists" + ], + "signature": [ + "(name: string) => boolean" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.hasRuntimeField.$1", + "type": "string", + "tags": [], + "label": "name", + "description": [ + "field name" + ], + "signature": [ + "string" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.getRuntimeField", + "type": "Function", + "tags": [], + "label": "getRuntimeField", + "description": [ + "\nReturns runtime field if exists" + ], + "signature": [ + "(name: string) => ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.RuntimeField", + "text": "RuntimeField" + }, + " | null" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.getRuntimeField.$1", + "type": "string", + "tags": [], + "label": "name", + "description": [ + "Runtime field name" + ], + "signature": [ + "string" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.getAllRuntimeFields", + "type": "Function", + "tags": [], + "label": "getAllRuntimeFields", + "description": [ + "\nGet all runtime field definitions.\nNOTE: this does not strip out runtime fields that match mapped field names" + ], + "signature": [ + "() => Record" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [ + "map of runtime field definitions by field name" + ] + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.getFieldsByRuntimeFieldName", + "type": "Function", + "tags": [], + "label": "getFieldsByRuntimeFieldName", + "description": [ + "\nReturns data view fields backed by runtime fields." + ], + "signature": [ + "(name: string) => Record | undefined" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.getFieldsByRuntimeFieldName.$1", + "type": "string", + "tags": [], + "label": "name", + "description": [ + "runtime field name" + ], + "signature": [ + "string" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [ + "map of DataViewFields (that are runtime fields) by field name" + ] + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.replaceAllRuntimeFields", + "type": "Function", + "tags": [], + "label": "replaceAllRuntimeFields", + "description": [ + "\nReplaces all existing runtime fields with new fields." + ], + "signature": [ + "(newFields: Record) => void" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.replaceAllRuntimeFields.$1", + "type": "Object", + "tags": [], + "label": "newFields", + "description": [ + "Map of runtime field definitions by field name" + ], + "signature": [ + "Record" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.removeRuntimeField", + "type": "Function", + "tags": [], + "label": "removeRuntimeField", + "description": [ + "\nRemove a runtime field - removed from mapped field or removed unmapped\nfield as appropriate. Doesn't clear associated field attributes." + ], + "signature": [ + "(name: string) => void" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.removeRuntimeField.$1", + "type": "string", + "tags": [], + "label": "name", + "description": [ + "- Field name to remove" + ], + "signature": [ + "string" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.getRuntimeMappings", + "type": "Function", + "tags": [], + "label": "getRuntimeMappings", + "description": [ + "\nReturn the \"runtime_mappings\" section of the ES search query." + ], + "signature": [ + "() => ", + "MappingRuntimeFields" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.getFormatterForFieldNoDefault", + "type": "Function", + "tags": [], + "label": "getFormatterForFieldNoDefault", + "description": [ + "\nGet formatter for a given field name. Return undefined if none exists." + ], + "signature": [ + "(fieldname: string) => ", + { + "pluginId": "fieldFormats", + "scope": "common", + "docId": "kibFieldFormatsPluginApi", + "section": "def-common.FieldFormat", + "text": "FieldFormat" + }, + " | undefined" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.getFormatterForFieldNoDefault.$1", + "type": "string", + "tags": [], + "label": "fieldname", + "description": [ + "name of field to get formatter for" + ], + "signature": [ + "string" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.setFieldAttrs", + "type": "Function", + "tags": [], + "label": "setFieldAttrs", + "description": [ + "\nSet field attribute" + ], + "signature": [ + "(fieldName: string, attrName: K, value: ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.FieldAttrSet", + "text": "FieldAttrSet" + }, + "[K]) => void" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.setFieldAttrs.$1", + "type": "string", + "tags": [], + "label": "fieldName", + "description": [ + "name of field to set attribute on" + ], + "signature": [ + "string" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.setFieldAttrs.$2", + "type": "Uncategorized", + "tags": [], + "label": "attrName", + "description": [ + "name of attribute to set" + ], + "signature": [ + "K" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.setFieldAttrs.$3", + "type": "Uncategorized", + "tags": [], + "label": "value", + "description": [ + "value of attribute" + ], + "signature": [ + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.FieldAttrSet", + "text": "FieldAttrSet" + }, + "[K]" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.setFieldCustomLabel", + "type": "Function", + "tags": [], + "label": "setFieldCustomLabel", + "description": [ + "\nSet field custom label" + ], + "signature": [ + "(fieldName: string, customLabel: string | null | undefined) => void" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.setFieldCustomLabel.$1", + "type": "string", + "tags": [], + "label": "fieldName", + "description": [ + "name of field to set custom label on" + ], + "signature": [ + "string" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.setFieldCustomLabel.$2", + "type": "CompoundType", + "tags": [], + "label": "customLabel", + "description": [ + "custom label value. If undefined, custom label is removed" + ], + "signature": [ + "string | null | undefined" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.setFieldCount", + "type": "Function", + "tags": [], + "label": "setFieldCount", + "description": [ + "\nSet field count" + ], + "signature": [ + "(fieldName: string, count: number | null | undefined) => void" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.setFieldCount.$1", + "type": "string", + "tags": [], + "label": "fieldName", + "description": [ + "name of field to set count on" + ], + "signature": [ + "string" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.setFieldCount.$2", + "type": "CompoundType", + "tags": [], + "label": "count", + "description": [ + "count value. If undefined, count is removed" + ], + "signature": [ + "number | null | undefined" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.setFieldFormat", + "type": "Function", + "tags": [], + "label": "setFieldFormat", + "description": [ + "\nSet field formatter" + ], + "signature": [ + "(fieldName: string, format: ", + { + "pluginId": "fieldFormats", + "scope": "common", + "docId": "kibFieldFormatsPluginApi", + "section": "def-common.SerializedFieldFormat", + "text": "SerializedFieldFormat" + }, + "<{}, ", + "SerializableRecord", + ">) => void" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.setFieldFormat.$1", + "type": "string", + "tags": [], + "label": "fieldName", + "description": [ + "name of field to set format on" + ], + "signature": [ + "string" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.setFieldFormat.$2", + "type": "Object", + "tags": [], + "label": "format", + "description": [ + "field format in serialized form" + ], + "signature": [ + { + "pluginId": "fieldFormats", + "scope": "common", + "docId": "kibFieldFormatsPluginApi", + "section": "def-common.SerializedFieldFormat", + "text": "SerializedFieldFormat" + }, + "<{}, ", + "SerializableRecord", + ">" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.deleteFieldFormat", + "type": "Function", + "tags": [], + "label": "deleteFieldFormat", + "description": [ + "\nRemove field format from the field format map." + ], + "signature": [ + "(fieldName: string) => void" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "dataViews", + "id": "def-public.DataView.deleteFieldFormat.$1", + "type": "string", + "tags": [], + "label": "fieldName", + "description": [ + "field name associated with the format for removal" + ], + "signature": [ + "string" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataViewField", + "type": "Class", + "tags": [], + "label": "DataViewField", + "description": [ + "\nData view field class" + ], + "signature": [ + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewField", + "text": "DataViewField" + }, + " implements ", + "DataViewFieldBase" + ], + "path": "src/plugins/data_views/common/fields/data_view_field.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "dataViews", + "id": "def-public.DataViewField.spec", + "type": "CompoundType", + "tags": [], + "label": "spec", + "description": [], + "signature": [ + "DataViewFieldBase", + " & { count?: number | undefined; conflictDescriptions?: Record | undefined; format?: ", + { + "pluginId": "fieldFormats", + "scope": "common", + "docId": "kibFieldFormatsPluginApi", + "section": "def-common.SerializedFieldFormat", + "text": "SerializedFieldFormat" + }, + "<{}, ", + "SerializableRecord", + "> | undefined; esTypes?: string[] | undefined; searchable: boolean; aggregatable: boolean; readFromDocValues?: boolean | undefined; indexed?: boolean | undefined; customLabel?: string | undefined; runtimeField?: ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.RuntimeFieldSpec", + "text": "RuntimeFieldSpec" + }, + " | undefined; fixedInterval?: string[] | undefined; timeZone?: string[] | undefined; timeSeriesDimension?: boolean | undefined; timeSeriesMetric?: \"gauge\" | \"histogram\" | \"summary\" | \"counter\" | undefined; shortDotsEnable?: boolean | undefined; isMapped?: boolean | undefined; parentName?: string | undefined; }" + ], + "path": "src/plugins/data_views/common/fields/data_view_field.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataViewField.Unnamed", + "type": "Function", + "tags": [ + "constructor" + ], + "label": "Constructor", + "description": [ + "\nDataView constructor" + ], + "signature": [ + "any" + ], + "path": "src/plugins/data_views/common/fields/data_view_field.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "dataViews", + "id": "def-public.DataViewField.Unnamed.$1", + "type": "CompoundType", + "tags": [], + "label": "spec", + "description": [ + "Configuration for the field" + ], + "signature": [ + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.FieldSpec", + "text": "FieldSpec" + } + ], + "path": "src/plugins/data_views/common/fields/data_view_field.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataViewField.count", + "type": "number", + "tags": [], + "label": "count", + "description": [ + "\nCount is used for field popularity in discover." + ], + "path": "src/plugins/data_views/common/fields/data_view_field.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataViewField.count", + "type": "number", + "tags": [], + "label": "count", + "description": [ + "\nSet count, which is used for field popularity in discover." + ], + "path": "src/plugins/data_views/common/fields/data_view_field.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataViewField.runtimeField", + "type": "CompoundType", + "tags": [], + "label": "runtimeField", + "description": [ + "\nReturns runtime field definition or undefined if field is not runtime field." + ], + "signature": [ + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.RuntimeFieldSpec", + "text": "RuntimeFieldSpec" + }, + " | undefined" + ], + "path": "src/plugins/data_views/common/fields/data_view_field.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataViewField.runtimeField", + "type": "CompoundType", + "tags": [], + "label": "runtimeField", + "description": [ + "\nSets runtime field definition or unsets if undefined is provided." + ], + "signature": [ + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.RuntimeFieldSpec", + "text": "RuntimeFieldSpec" + }, + " | undefined" + ], + "path": "src/plugins/data_views/common/fields/data_view_field.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataViewField.script", + "type": "string", + "tags": [], + "label": "script", + "description": [ + "\nScript field code" + ], + "signature": [ + "string | undefined" + ], + "path": "src/plugins/data_views/common/fields/data_view_field.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataViewField.script", + "type": "string", + "tags": [], + "label": "script", + "description": [ + "\nSets scripted field painless code" + ], + "signature": [ + "string | undefined" + ], + "path": "src/plugins/data_views/common/fields/data_view_field.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataViewField.lang", + "type": "string", + "tags": [], + "label": "lang", + "description": [ + "\nScript field language" + ], + "signature": [ + "string | undefined" + ], + "path": "src/plugins/data_views/common/fields/data_view_field.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataViewField.lang", + "type": "string", + "tags": [], + "label": "lang", + "description": [ + "\nSets scripted field langauge." + ], + "signature": [ + "string | undefined" + ], + "path": "src/plugins/data_views/common/fields/data_view_field.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "dataViews", + "id": "def-public.DataViewField.customLabel", + "type": "string", + "tags": [], + "label": "customLabel", + "description": [ + "\nReturns custom label if set, otherwise undefined." + ], + "signature": [ + "string | undefined" + ], + "path": "src/plugins/data_views/common/fields/data_view_field.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "dataViews", "id": "def-public.DataViewField.customLabel", "type": "string", "tags": [], @@ -6947,14 +7885,898 @@ "parentPluginId": "dataViews", "id": "def-server.DataView.title", "type": "string", - "tags": [], + "tags": [ + "deprecated" + ], "label": "title", "description": [ "\nTitle of data view" ], "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false + "deprecated": true, + "trackAdoption": false, + "references": [ + { + "plugin": "timelines", + "path": "x-pack/plugins/timelines/public/container/source/index.tsx" + }, + { + "plugin": "timelines", + "path": "x-pack/plugins/timelines/public/container/source/index.tsx" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/containers/source/index.tsx" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/containers/source/index.tsx" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/detections/containers/detection_engine/exceptions/get_es_query_filter.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/utils.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/signals/get_query_filter.ts" + }, + { + "plugin": "timelines", + "path": "x-pack/plugins/timelines/public/mock/index_pattern.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/mock/index_pattern.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts" + }, + { + "plugin": "threatIntelligence", + "path": "x-pack/plugins/threat_intelligence/public/common/mocks/mock_security_context.tsx" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/flyout_components/alerts_actions/utils.test.ts" + }, + { + "plugin": "data", + "path": "src/plugins/data/common/search/expressions/kibana_context.test.ts" + }, + { + "plugin": "data", + "path": "src/plugins/data/common/search/expressions/kibana_context.test.ts" + }, + { + "plugin": "data", + "path": "src/plugins/data/common/search/expressions/kibana_context.test.ts" + }, + { + "plugin": "data", + "path": "src/plugins/data/public/query/filter_manager/lib/get_display_value.ts" + }, + { + "plugin": "data", + "path": "src/plugins/data/common/search/search_source/inspect/inspector_stats.ts" + }, + { + "plugin": "data", + "path": "src/plugins/data/common/search/tabify/response_writer.ts" + }, + { + "plugin": "data", + "path": "src/plugins/data/public/search/errors/painless_error.tsx" + }, + { + "plugin": "data", + "path": "src/plugins/data/common/search/aggs/param_types/field.ts" + }, + { + "plugin": "dataViewEditor", + "path": "src/plugins/data_view_editor/public/components/data_view_editor_flyout_content.tsx" + }, + { + "plugin": "unifiedSearch", + "path": "src/plugins/unified_search/public/autocomplete/providers/value_suggestion_provider.ts" + }, + { + "plugin": "unifiedSearch", + "path": "src/plugins/unified_search/public/query_string_input/fetch_index_patterns.ts" + }, + { + "plugin": "unifiedSearch", + "path": "src/plugins/unified_search/public/dataview_picker/change_dataview.tsx" + }, + { + "plugin": "triggersActionsUi", + "path": "x-pack/plugins/triggers_actions_ui/public/common/lib/data_apis.ts" + }, + { + "plugin": "savedObjectsManagement", + "path": "src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx" + }, + { + "plugin": "savedObjectsManagement", + "path": "src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx" + }, + { + "plugin": "unifiedFieldList", + "path": "src/plugins/unified_field_list/public/services/field_stats/load_field_stats.ts" + }, + { + "plugin": "unifiedFieldList", + "path": "src/plugins/unified_field_list/common/utils/field_existing_utils.ts" + }, + { + "plugin": "unifiedFieldList", + "path": "src/plugins/unified_field_list/common/utils/field_existing_utils.ts" + }, + { + "plugin": "unifiedFieldList", + "path": "src/plugins/unified_field_list/common/utils/field_existing_utils.ts" + }, + { + "plugin": "discover", + "path": "src/plugins/discover/public/hooks/use_es_doc_search.ts" + }, + { + "plugin": "discover", + "path": "src/plugins/discover/public/application/main/utils/resolve_data_view.ts" + }, + { + "plugin": "discover", + "path": "src/plugins/discover/public/application/main/utils/resolve_data_view.ts" + }, + { + "plugin": "discover", + "path": "src/plugins/discover/public/application/main/components/sidebar/discover_sidebar.tsx" + }, + { + "plugin": "discover", + "path": "src/plugins/discover/public/application/main/components/top_nav/discover_topnav.tsx" + }, + { + "plugin": "aiops", + "path": "x-pack/plugins/aiops/public/hooks/use_data.ts" + }, + { + "plugin": "aiops", + "path": "x-pack/plugins/aiops/public/components/full_time_range_selector/full_time_range_selector_service.ts" + }, + { + "plugin": "aiops", + "path": "x-pack/plugins/aiops/public/components/explain_log_rate_spikes/explain_log_rate_spikes_analysis.tsx" + }, + { + "plugin": "aiops", + "path": "x-pack/plugins/aiops/public/components/log_categorization/log_categorization_page.tsx" + }, + { + "plugin": "presentationUtil", + "path": "src/plugins/presentation_util/public/services/storybook/data_views.ts" + }, + { + "plugin": "controls", + "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" + }, + { + "plugin": "controls", + "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" + }, + { + "plugin": "lens", + "path": "x-pack/plugins/lens/public/data_views_service/loader.ts" + }, + { + "plugin": "lens", + "path": "x-pack/plugins/lens/public/app_plugin/lens_top_nav.tsx" + }, + { + "plugin": "observability", + "path": "x-pack/plugins/observability/public/utils/observability_data_views/observability_data_views.ts" + }, + { + "plugin": "observability", + "path": "x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/report_definition_field.tsx" + }, + { + "plugin": "observability", + "path": "x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/use_filter_values.ts" + }, + { + "plugin": "observability", + "path": "x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/filter_value_btn.tsx" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/infra/common/log_views/resolved_log_view.ts" + }, + { + "plugin": "maps", + "path": "x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.tsx" + }, + { + "plugin": "maps", + "path": "x-pack/plugins/maps/public/classes/sources/es_search_source/util/scaling_form.tsx" + }, + { + "plugin": "maps", + "path": "x-pack/plugins/maps/public/classes/sources/es_search_source/top_hits/top_hits_form.tsx" + }, + { + "plugin": "maps", + "path": "x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx" + }, + { + "plugin": "maps", + "path": "x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx" + }, + { + "plugin": "maps", + "path": "x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx" + }, + { + "plugin": "maps", + "path": "x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx" + }, + { + "plugin": "maps", + "path": "x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx" + }, + { + "plugin": "maps", + "path": "x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx" + }, + { + "plugin": "maps", + "path": "x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx" + }, + { + "plugin": "maps", + "path": "x-pack/plugins/maps/public/trigger_actions/visualize_geo_field_action.ts" + }, + { + "plugin": "dataVisualizer", + "path": "x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/full_time_range_selector/full_time_range_selector_service.ts" + }, + { + "plugin": "dataVisualizer", + "path": "x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/actions_panel/actions_panel.tsx" + }, + { + "plugin": "dataVisualizer", + "path": "x-pack/plugins/data_visualizer/public/application/index_data_visualizer/hooks/use_data_visualizer_grid_data.ts" + }, + { + "plugin": "dataVisualizer", + "path": "x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/index_data_visualizer_view.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/util/index_utils.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/util/index_utils.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/util/index_utils.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/services/new_job_capabilities/new_job_capabilities_service_analytics.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/services/new_job_capabilities/new_job_capabilities_service_analytics.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_details.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/datavisualizer/index_based/data_loader/data_loader.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/page.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_clone/clone_action_name.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/index_or_search/preconfigured_job_redirect.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/job_type/page.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/job_type/page.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/job_type/page.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/services/new_job_capabilities/new_job_capabilities_service.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/services/new_job_capabilities/new_job_capabilities_service.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/job_creator.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/common/chart_loader/chart_loader.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/common/results_loader/categorization_examples_loader.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/components/full_time_range_selector/full_time_range_selector_service.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/bucket_span_estimator/estimate_bucket_span.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/components/datafeed_step/components/data_view/change_data_view.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/new_job/wizard_steps.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/recognize/components/job_settings_form.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/recognize/page.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/recognize/page.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/quick_create_job.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/use_outlier_data.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/use_exploration_results.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/source_selection/source_selection.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/embeddables/anomaly_charts/anomaly_charts_embeddable.tsx" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/infra/public/pages/logs/settings/validation_errors.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/infra/public/pages/logs/settings/validation_errors.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/infra/public/pages/logs/settings/validation_errors.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/infra/public/pages/logs/settings/validation_errors.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/filter_dataset.tsx" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/filter_log_level.tsx" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/query_bar.tsx" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/public/applications/fleet/components/search_bar.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/server/models/data_frame_analytics/index_patterns.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/server/models/job_service/new_job_caps/rollup.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/server/lib/alerts/alerting_service.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.ts" + }, + { + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/common/index_patterns_utils.ts" + }, + { + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/common/index_patterns_utils.ts" + }, + { + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/server/lib/get_fields.ts" + }, + { + "plugin": "apm", + "path": "x-pack/plugins/apm/server/routes/data_view/create_static_data_view.ts" + }, + { + "plugin": "reporting", + "path": "x-pack/plugins/reporting/server/export_types/csv_searchsource/generate_csv/generate_csv.ts" + }, + { + "plugin": "graph", + "path": "x-pack/plugins/graph/public/state_management/datasource.sagas.ts" + }, + { + "plugin": "graph", + "path": "x-pack/plugins/graph/public/state_management/persistence.ts" + }, + { + "plugin": "graph", + "path": "x-pack/plugins/graph/public/state_management/persistence.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/detections/components/rules/eql_query_bar/validators.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/detections/components/rules/step_define_rule/index.tsx" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/index.tsx" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/sourcerer/routes/index.ts" + }, + { + "plugin": "stackAlerts", + "path": "x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/expressions/boundary_index_expression.tsx" + }, + { + "plugin": "stackAlerts", + "path": "x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/expressions/entity_index_expression.tsx" + }, + { + "plugin": "stackAlerts", + "path": "x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/index.tsx" + }, + { + "plugin": "stackAlerts", + "path": "x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/index.tsx" + }, + { + "plugin": "stackAlerts", + "path": "x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/index.tsx" + }, + { + "plugin": "stackAlerts", + "path": "x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/index.tsx" + }, + { + "plugin": "stackAlerts", + "path": "x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/index.tsx" + }, + { + "plugin": "stackAlerts", + "path": "x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/index.tsx" + }, + { + "plugin": "stackAlerts", + "path": "x-pack/plugins/stack_alerts/public/alert_types/es_query/expression/search_source_expression_form.tsx" + }, + { + "plugin": "synthetics", + "path": "x-pack/plugins/synthetics/public/legacy_uptime/components/overview/filter_group/filter_group.tsx" + }, + { + "plugin": "synthetics", + "path": "x-pack/plugins/synthetics/public/legacy_uptime/components/overview/alerts/monitor_expressions/filters_expression_select.tsx" + }, + { + "plugin": "timelines", + "path": "x-pack/plugins/timelines/server/search_strategy/index_fields/index.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_details/step_details_form.tsx" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/wizard/wizard.tsx" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/filter_agg/components/filter_term_form.tsx" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/hooks/use_index_data.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/hooks/use_index_data.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/hooks/use_index_data.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/hooks/use_index_data.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/hooks/use_index_data.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/hooks/use_index_data.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/hooks/use_index_data.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/hooks/use_step_define_form.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/hooks/use_step_define_form.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_form.tsx" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_form.tsx" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_form.tsx" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_form.tsx" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_summary.tsx" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_summary.tsx" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_summary.tsx" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/hooks/use_search_items/common.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/services/es_index_service.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/server/routes/api/transforms.ts" + }, + { + "plugin": "upgradeAssistant", + "path": "x-pack/plugins/upgrade_assistant/public/application/components/es_deprecation_logs/fix_deprecation_logs/external_links.tsx" + }, + { + "plugin": "ux", + "path": "x-pack/plugins/ux/public/components/app/rum_dashboard/local_uifilters/use_data_view.ts" + }, + { + "plugin": "graph", + "path": "x-pack/plugins/graph/public/state_management/datasource.test.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/infra/common/dependency_mocks/index_patterns.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/infra/common/dependency_mocks/index_patterns.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/infra/common/dependency_mocks/index_patterns.ts" + }, + { + "plugin": "maps", + "path": "x-pack/plugins/maps/public/classes/tooltips/es_tooltip_property.test.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/services/new_job_capabilities/remove_nested_field_children.test.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/common.test.ts" + }, + { + "plugin": "controls", + "path": "src/plugins/controls/public/services/data_views/data_views.story.ts" + }, + { + "plugin": "dataViewManagement", + "path": "src/plugins/data_view_management/public/components/edit_index_pattern/edit_index_pattern.tsx" + }, + { + "plugin": "dataViewManagement", + "path": "src/plugins/data_view_management/public/components/edit_index_pattern/edit_index_pattern.tsx" + }, + { + "plugin": "dataViewManagement", + "path": "src/plugins/data_view_management/public/components/field_editor/components/scripting_help/test_script.tsx" + }, + { + "plugin": "dataViewManagement", + "path": "src/plugins/data_view_management/public/components/field_editor/field_editor.tsx" + }, + { + "plugin": "dataViewManagement", + "path": "src/plugins/data_view_management/public/components/edit_index_pattern/create_edit_field/create_edit_field.tsx" + }, + { + "plugin": "inputControlVis", + "path": "src/plugins/input_control_vis/public/control/list_control_factory.ts" + }, + { + "plugin": "inputControlVis", + "path": "src/plugins/input_control_vis/public/control/range_control_factory.ts" + }, + { + "plugin": "unifiedFieldList", + "path": "src/plugins/unified_field_list/server/routes/field_stats.ts" + }, + { + "plugin": "unifiedFieldList", + "path": "src/plugins/unified_field_list/server/routes/field_stats.ts" + }, + { + "plugin": "visDefaultEditor", + "path": "src/plugins/vis_default_editor/public/components/controls/field.tsx" + }, + { + "plugin": "visDefaultEditor", + "path": "src/plugins/vis_default_editor/public/components/controls/field.tsx" + }, + { + "plugin": "visDefaultEditor", + "path": "src/plugins/vis_default_editor/public/components/agg_select.tsx" + }, + { + "plugin": "inputControlVis", + "path": "src/plugins/input_control_vis/public/test_utils/get_index_pattern_mock.ts" + }, + { + "plugin": "visTypeTimelion", + "path": "src/plugins/vis_types/timelion/public/helpers/arg_value_suggestions.ts" + }, + { + "plugin": "visTypeTimelion", + "path": "src/plugins/vis_types/timelion/public/helpers/arg_value_suggestions.ts" + }, + { + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/common/index_patterns_utils.test.ts" + }, + { + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/common/index_patterns_utils.test.ts" + }, + { + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/public/application/components/lib/convert_series_to_datatable.ts" + }, + { + "plugin": "visTypeVega", + "path": "src/plugins/vis_types/vega/public/data_model/search_api.ts" + }, + { + "plugin": "data", + "path": "src/plugins/data/common/search/aggs/agg_config.test.ts" + }, + { + "plugin": "data", + "path": "src/plugins/data/common/search/aggs/buckets/_terms_other_bucket_helper.test.ts" + }, + { + "plugin": "data", + "path": "src/plugins/data/common/search/aggs/buckets/multi_terms.test.ts" + }, + { + "plugin": "data", + "path": "src/plugins/data/common/search/aggs/buckets/multi_terms.test.ts" + }, + { + "plugin": "data", + "path": "src/plugins/data/common/search/aggs/buckets/rare_terms.test.ts" + }, + { + "plugin": "data", + "path": "src/plugins/data/common/search/aggs/buckets/terms.test.ts" + }, + { + "plugin": "data", + "path": "src/plugins/data/common/search/aggs/buckets/terms.test.ts" + }, + { + "plugin": "data", + "path": "src/plugins/data/public/query/filter_manager/lib/get_display_value.test.ts" + }, + { + "plugin": "discover", + "path": "src/plugins/discover/public/application/main/hooks/use_adhoc_data_views.test.ts" + }, + { + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/public/application/components/lib/convert_series_to_datatable.test.ts" + }, + { + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/public/convert_to_lens/lib/datasource/get_datasource_info.test.ts" + }, + { + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/public/convert_to_lens/lib/datasource/get_datasource_info.test.ts" + }, + { + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/public/convert_to_lens/lib/datasource/get_datasource_info.test.ts" + }, + { + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/server/lib/search_strategies/lib/cached_index_pattern_fetcher.test.ts" + }, + { + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/server/lib/search_strategies/lib/cached_index_pattern_fetcher.test.ts" + }, + { + "plugin": "discover", + "path": "src/plugins/discover/public/application/main/components/layout/__stories__/get_layout_props.ts" + }, + { + "plugin": "lens", + "path": "x-pack/plugins/lens/public/data_views_service/loader.test.ts" + }, + { + "plugin": "lens", + "path": "x-pack/plugins/lens/public/data_views_service/loader.test.ts" + }, + { + "plugin": "lens", + "path": "x-pack/plugins/lens/public/data_views_service/loader.test.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/sourcerer/routes/index.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/sourcerer/routes/index.ts" + } + ] }, { "parentPluginId": "dataViews", @@ -7290,6 +9112,60 @@ "children": [], "returnComment": [] }, + { + "parentPluginId": "dataViews", + "id": "def-server.DataView.getIndexPattern", + "type": "Function", + "tags": [], + "label": "getIndexPattern", + "description": [ + "\nGet index pattern" + ], + "signature": [ + "() => string" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [ + "index pattern string" + ] + }, + { + "parentPluginId": "dataViews", + "id": "def-server.DataView.setIndexPattern", + "type": "Function", + "tags": [], + "label": "setIndexPattern", + "description": [ + "\nSet index pattern" + ], + "signature": [ + "(indexPattern: string) => void" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "dataViews", + "id": "def-server.DataView.setIndexPattern.$1", + "type": "string", + "tags": [], + "label": "indexPattern", + "description": [], + "signature": [ + "string" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, { "parentPluginId": "dataViews", "id": "def-server.DataView.getOriginalSavedObjectBody", @@ -11875,7 +13751,9 @@ "TransportRequestOptions", " | undefined): Promise<", "UpdateResponse", - ">; }; [kInternal]: symbol | null; [kAsyncSearch]: symbol | null; [kAutoscaling]: symbol | null; [kCat]: symbol | null; [kCcr]: symbol | null; [kCluster]: symbol | null; [kDanglingIndices]: symbol | null; [kEnrich]: symbol | null; [kEql]: symbol | null; [kFeatures]: symbol | null; [kFleet]: symbol | null; [kGraph]: symbol | null; [kIlm]: symbol | null; [kIndices]: symbol | null; [kIngest]: symbol | null; [kLicense]: symbol | null; [kLogstash]: symbol | null; [kMigration]: symbol | null; [kMl]: symbol | null; [kMonitoring]: symbol | null; [kNodes]: symbol | null; [kRollup]: symbol | null; [kSearchableSnapshots]: symbol | null; [kSecurity]: symbol | null; [kShutdown]: symbol | null; [kSlm]: symbol | null; [kSnapshot]: symbol | null; [kSql]: symbol | null; [kSsl]: symbol | null; [kTasks]: symbol | null; [kTextStructure]: symbol | null; [kTransform]: symbol | null; [kWatcher]: symbol | null; [kXpack]: symbol | null; transport: ", + ">; }; asyncSearch: ", + "default", + "; [kInternal]: symbol | null; [kAsyncSearch]: symbol | null; [kAutoscaling]: symbol | null; [kCat]: symbol | null; [kCcr]: symbol | null; [kCluster]: symbol | null; [kDanglingIndices]: symbol | null; [kEnrich]: symbol | null; [kEql]: symbol | null; [kFeatures]: symbol | null; [kFleet]: symbol | null; [kGraph]: symbol | null; [kIlm]: symbol | null; [kIndices]: symbol | null; [kIngest]: symbol | null; [kLicense]: symbol | null; [kLogstash]: symbol | null; [kMigration]: symbol | null; [kMl]: symbol | null; [kMonitoring]: symbol | null; [kNodes]: symbol | null; [kRollup]: symbol | null; [kSearchableSnapshots]: symbol | null; [kSecurity]: symbol | null; [kShutdown]: symbol | null; [kSlm]: symbol | null; [kSnapshot]: symbol | null; [kSql]: symbol | null; [kSsl]: symbol | null; [kTasks]: symbol | null; [kTextStructure]: symbol | null; [kTransform]: symbol | null; [kWatcher]: symbol | null; [kXpack]: symbol | null; transport: ", "default", "; helpers: ", "default", @@ -11885,8 +13763,6 @@ "default", "; Internal: ", "default", - "; asyncSearch: ", - "default", "; autoscaling: ", "default", "; bulk: { (this: That, params: ", @@ -12997,14 +14873,898 @@ "parentPluginId": "dataViews", "id": "def-common.DataView.title", "type": "string", - "tags": [], + "tags": [ + "deprecated" + ], "label": "title", "description": [ "\nTitle of data view" ], "path": "src/plugins/data_views/common/data_views/data_view.ts", - "deprecated": false, - "trackAdoption": false + "deprecated": true, + "trackAdoption": false, + "references": [ + { + "plugin": "timelines", + "path": "x-pack/plugins/timelines/public/container/source/index.tsx" + }, + { + "plugin": "timelines", + "path": "x-pack/plugins/timelines/public/container/source/index.tsx" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/containers/source/index.tsx" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/containers/source/index.tsx" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/detections/containers/detection_engine/exceptions/get_es_query_filter.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/utils.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/detection_engine/signals/get_query_filter.ts" + }, + { + "plugin": "timelines", + "path": "x-pack/plugins/timelines/public/mock/index_pattern.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/common/mock/index_pattern.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts" + }, + { + "plugin": "lists", + "path": "x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts" + }, + { + "plugin": "threatIntelligence", + "path": "x-pack/plugins/threat_intelligence/public/common/mocks/mock_security_context.tsx" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/flyout_components/alerts_actions/utils.test.ts" + }, + { + "plugin": "data", + "path": "src/plugins/data/common/search/expressions/kibana_context.test.ts" + }, + { + "plugin": "data", + "path": "src/plugins/data/common/search/expressions/kibana_context.test.ts" + }, + { + "plugin": "data", + "path": "src/plugins/data/common/search/expressions/kibana_context.test.ts" + }, + { + "plugin": "data", + "path": "src/plugins/data/public/query/filter_manager/lib/get_display_value.ts" + }, + { + "plugin": "data", + "path": "src/plugins/data/common/search/search_source/inspect/inspector_stats.ts" + }, + { + "plugin": "data", + "path": "src/plugins/data/common/search/tabify/response_writer.ts" + }, + { + "plugin": "data", + "path": "src/plugins/data/public/search/errors/painless_error.tsx" + }, + { + "plugin": "data", + "path": "src/plugins/data/common/search/aggs/param_types/field.ts" + }, + { + "plugin": "dataViewEditor", + "path": "src/plugins/data_view_editor/public/components/data_view_editor_flyout_content.tsx" + }, + { + "plugin": "unifiedSearch", + "path": "src/plugins/unified_search/public/autocomplete/providers/value_suggestion_provider.ts" + }, + { + "plugin": "unifiedSearch", + "path": "src/plugins/unified_search/public/query_string_input/fetch_index_patterns.ts" + }, + { + "plugin": "unifiedSearch", + "path": "src/plugins/unified_search/public/dataview_picker/change_dataview.tsx" + }, + { + "plugin": "triggersActionsUi", + "path": "x-pack/plugins/triggers_actions_ui/public/common/lib/data_apis.ts" + }, + { + "plugin": "savedObjectsManagement", + "path": "src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx" + }, + { + "plugin": "savedObjectsManagement", + "path": "src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx" + }, + { + "plugin": "unifiedFieldList", + "path": "src/plugins/unified_field_list/public/services/field_stats/load_field_stats.ts" + }, + { + "plugin": "unifiedFieldList", + "path": "src/plugins/unified_field_list/common/utils/field_existing_utils.ts" + }, + { + "plugin": "unifiedFieldList", + "path": "src/plugins/unified_field_list/common/utils/field_existing_utils.ts" + }, + { + "plugin": "unifiedFieldList", + "path": "src/plugins/unified_field_list/common/utils/field_existing_utils.ts" + }, + { + "plugin": "discover", + "path": "src/plugins/discover/public/hooks/use_es_doc_search.ts" + }, + { + "plugin": "discover", + "path": "src/plugins/discover/public/application/main/utils/resolve_data_view.ts" + }, + { + "plugin": "discover", + "path": "src/plugins/discover/public/application/main/utils/resolve_data_view.ts" + }, + { + "plugin": "discover", + "path": "src/plugins/discover/public/application/main/components/sidebar/discover_sidebar.tsx" + }, + { + "plugin": "discover", + "path": "src/plugins/discover/public/application/main/components/top_nav/discover_topnav.tsx" + }, + { + "plugin": "aiops", + "path": "x-pack/plugins/aiops/public/hooks/use_data.ts" + }, + { + "plugin": "aiops", + "path": "x-pack/plugins/aiops/public/components/full_time_range_selector/full_time_range_selector_service.ts" + }, + { + "plugin": "aiops", + "path": "x-pack/plugins/aiops/public/components/explain_log_rate_spikes/explain_log_rate_spikes_analysis.tsx" + }, + { + "plugin": "aiops", + "path": "x-pack/plugins/aiops/public/components/log_categorization/log_categorization_page.tsx" + }, + { + "plugin": "presentationUtil", + "path": "src/plugins/presentation_util/public/services/storybook/data_views.ts" + }, + { + "plugin": "controls", + "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" + }, + { + "plugin": "controls", + "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" + }, + { + "plugin": "lens", + "path": "x-pack/plugins/lens/public/data_views_service/loader.ts" + }, + { + "plugin": "lens", + "path": "x-pack/plugins/lens/public/app_plugin/lens_top_nav.tsx" + }, + { + "plugin": "observability", + "path": "x-pack/plugins/observability/public/utils/observability_data_views/observability_data_views.ts" + }, + { + "plugin": "observability", + "path": "x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/report_definition_field.tsx" + }, + { + "plugin": "observability", + "path": "x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/use_filter_values.ts" + }, + { + "plugin": "observability", + "path": "x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/filter_value_btn.tsx" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/infra/common/log_views/resolved_log_view.ts" + }, + { + "plugin": "maps", + "path": "x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.tsx" + }, + { + "plugin": "maps", + "path": "x-pack/plugins/maps/public/classes/sources/es_search_source/util/scaling_form.tsx" + }, + { + "plugin": "maps", + "path": "x-pack/plugins/maps/public/classes/sources/es_search_source/top_hits/top_hits_form.tsx" + }, + { + "plugin": "maps", + "path": "x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx" + }, + { + "plugin": "maps", + "path": "x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx" + }, + { + "plugin": "maps", + "path": "x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx" + }, + { + "plugin": "maps", + "path": "x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx" + }, + { + "plugin": "maps", + "path": "x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx" + }, + { + "plugin": "maps", + "path": "x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx" + }, + { + "plugin": "maps", + "path": "x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx" + }, + { + "plugin": "maps", + "path": "x-pack/plugins/maps/public/trigger_actions/visualize_geo_field_action.ts" + }, + { + "plugin": "dataVisualizer", + "path": "x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/full_time_range_selector/full_time_range_selector_service.ts" + }, + { + "plugin": "dataVisualizer", + "path": "x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/actions_panel/actions_panel.tsx" + }, + { + "plugin": "dataVisualizer", + "path": "x-pack/plugins/data_visualizer/public/application/index_data_visualizer/hooks/use_data_visualizer_grid_data.ts" + }, + { + "plugin": "dataVisualizer", + "path": "x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/index_data_visualizer_view.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/util/index_utils.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/util/index_utils.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/util/index_utils.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/services/new_job_capabilities/new_job_capabilities_service_analytics.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/services/new_job_capabilities/new_job_capabilities_service_analytics.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_details.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/datavisualizer/index_based/data_loader/data_loader.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/page.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/action_clone/clone_action_name.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/index_or_search/preconfigured_job_redirect.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/job_type/page.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/job_type/page.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/job_type/page.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/services/new_job_capabilities/new_job_capabilities_service.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/services/new_job_capabilities/new_job_capabilities_service.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/job_creator.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/common/chart_loader/chart_loader.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/common/results_loader/categorization_examples_loader.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/components/full_time_range_selector/full_time_range_selector_service.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/bucket_span_estimator/estimate_bucket_span.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/components/datafeed_step/components/data_view/change_data_view.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/pages/new_job/wizard_steps.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/recognize/components/job_settings_form.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/recognize/page.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/recognize/page.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/quick_create_job.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/outlier_exploration/use_outlier_data.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_results_table/use_exploration_results.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/source_selection/source_selection.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/embeddables/anomaly_charts/anomaly_charts_embeddable.tsx" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/infra/public/pages/logs/settings/validation_errors.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/infra/public/pages/logs/settings/validation_errors.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/infra/public/pages/logs/settings/validation_errors.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/infra/public/pages/logs/settings/validation_errors.ts" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/filter_dataset.tsx" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/filter_log_level.tsx" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/query_bar.tsx" + }, + { + "plugin": "fleet", + "path": "x-pack/plugins/fleet/public/applications/fleet/components/search_bar.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/server/models/data_frame_analytics/index_patterns.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/server/models/job_service/new_job_caps/rollup.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/server/lib/alerts/alerting_service.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/server/models/data_recognizer/data_recognizer.ts" + }, + { + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/common/index_patterns_utils.ts" + }, + { + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/common/index_patterns_utils.ts" + }, + { + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/server/lib/get_fields.ts" + }, + { + "plugin": "apm", + "path": "x-pack/plugins/apm/server/routes/data_view/create_static_data_view.ts" + }, + { + "plugin": "reporting", + "path": "x-pack/plugins/reporting/server/export_types/csv_searchsource/generate_csv/generate_csv.ts" + }, + { + "plugin": "graph", + "path": "x-pack/plugins/graph/public/state_management/datasource.sagas.ts" + }, + { + "plugin": "graph", + "path": "x-pack/plugins/graph/public/state_management/persistence.ts" + }, + { + "plugin": "graph", + "path": "x-pack/plugins/graph/public/state_management/persistence.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/detections/components/rules/eql_query_bar/validators.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/detections/components/rules/step_define_rule/index.tsx" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/index.tsx" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/sourcerer/routes/index.ts" + }, + { + "plugin": "stackAlerts", + "path": "x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/expressions/boundary_index_expression.tsx" + }, + { + "plugin": "stackAlerts", + "path": "x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/expressions/entity_index_expression.tsx" + }, + { + "plugin": "stackAlerts", + "path": "x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/index.tsx" + }, + { + "plugin": "stackAlerts", + "path": "x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/index.tsx" + }, + { + "plugin": "stackAlerts", + "path": "x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/index.tsx" + }, + { + "plugin": "stackAlerts", + "path": "x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/index.tsx" + }, + { + "plugin": "stackAlerts", + "path": "x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/index.tsx" + }, + { + "plugin": "stackAlerts", + "path": "x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/index.tsx" + }, + { + "plugin": "stackAlerts", + "path": "x-pack/plugins/stack_alerts/public/alert_types/es_query/expression/search_source_expression_form.tsx" + }, + { + "plugin": "synthetics", + "path": "x-pack/plugins/synthetics/public/legacy_uptime/components/overview/filter_group/filter_group.tsx" + }, + { + "plugin": "synthetics", + "path": "x-pack/plugins/synthetics/public/legacy_uptime/components/overview/alerts/monitor_expressions/filters_expression_select.tsx" + }, + { + "plugin": "timelines", + "path": "x-pack/plugins/timelines/server/search_strategy/index_fields/index.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_details/step_details_form.tsx" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/wizard/wizard.tsx" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/filter_agg/components/filter_term_form.tsx" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/hooks/use_index_data.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/hooks/use_index_data.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/hooks/use_index_data.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/hooks/use_index_data.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/hooks/use_index_data.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/hooks/use_index_data.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/hooks/use_index_data.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/hooks/use_step_define_form.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/hooks/use_step_define_form.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_form.tsx" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_form.tsx" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_form.tsx" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_form.tsx" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_summary.tsx" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_summary.tsx" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/step_define_summary.tsx" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/hooks/use_search_items/common.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/services/es_index_service.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/server/routes/api/transforms.ts" + }, + { + "plugin": "upgradeAssistant", + "path": "x-pack/plugins/upgrade_assistant/public/application/components/es_deprecation_logs/fix_deprecation_logs/external_links.tsx" + }, + { + "plugin": "ux", + "path": "x-pack/plugins/ux/public/components/app/rum_dashboard/local_uifilters/use_data_view.ts" + }, + { + "plugin": "graph", + "path": "x-pack/plugins/graph/public/state_management/datasource.test.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/infra/common/dependency_mocks/index_patterns.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/infra/common/dependency_mocks/index_patterns.ts" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/infra/common/dependency_mocks/index_patterns.ts" + }, + { + "plugin": "maps", + "path": "x-pack/plugins/maps/public/classes/tooltips/es_tooltip_property.test.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/services/new_job_capabilities/remove_nested_field_children.test.ts" + }, + { + "plugin": "transform", + "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/common.test.ts" + }, + { + "plugin": "controls", + "path": "src/plugins/controls/public/services/data_views/data_views.story.ts" + }, + { + "plugin": "dataViewManagement", + "path": "src/plugins/data_view_management/public/components/edit_index_pattern/edit_index_pattern.tsx" + }, + { + "plugin": "dataViewManagement", + "path": "src/plugins/data_view_management/public/components/edit_index_pattern/edit_index_pattern.tsx" + }, + { + "plugin": "dataViewManagement", + "path": "src/plugins/data_view_management/public/components/field_editor/components/scripting_help/test_script.tsx" + }, + { + "plugin": "dataViewManagement", + "path": "src/plugins/data_view_management/public/components/field_editor/field_editor.tsx" + }, + { + "plugin": "dataViewManagement", + "path": "src/plugins/data_view_management/public/components/edit_index_pattern/create_edit_field/create_edit_field.tsx" + }, + { + "plugin": "inputControlVis", + "path": "src/plugins/input_control_vis/public/control/list_control_factory.ts" + }, + { + "plugin": "inputControlVis", + "path": "src/plugins/input_control_vis/public/control/range_control_factory.ts" + }, + { + "plugin": "unifiedFieldList", + "path": "src/plugins/unified_field_list/server/routes/field_stats.ts" + }, + { + "plugin": "unifiedFieldList", + "path": "src/plugins/unified_field_list/server/routes/field_stats.ts" + }, + { + "plugin": "visDefaultEditor", + "path": "src/plugins/vis_default_editor/public/components/controls/field.tsx" + }, + { + "plugin": "visDefaultEditor", + "path": "src/plugins/vis_default_editor/public/components/controls/field.tsx" + }, + { + "plugin": "visDefaultEditor", + "path": "src/plugins/vis_default_editor/public/components/agg_select.tsx" + }, + { + "plugin": "inputControlVis", + "path": "src/plugins/input_control_vis/public/test_utils/get_index_pattern_mock.ts" + }, + { + "plugin": "visTypeTimelion", + "path": "src/plugins/vis_types/timelion/public/helpers/arg_value_suggestions.ts" + }, + { + "plugin": "visTypeTimelion", + "path": "src/plugins/vis_types/timelion/public/helpers/arg_value_suggestions.ts" + }, + { + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/common/index_patterns_utils.test.ts" + }, + { + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/common/index_patterns_utils.test.ts" + }, + { + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/public/application/components/lib/convert_series_to_datatable.ts" + }, + { + "plugin": "visTypeVega", + "path": "src/plugins/vis_types/vega/public/data_model/search_api.ts" + }, + { + "plugin": "data", + "path": "src/plugins/data/common/search/aggs/agg_config.test.ts" + }, + { + "plugin": "data", + "path": "src/plugins/data/common/search/aggs/buckets/_terms_other_bucket_helper.test.ts" + }, + { + "plugin": "data", + "path": "src/plugins/data/common/search/aggs/buckets/multi_terms.test.ts" + }, + { + "plugin": "data", + "path": "src/plugins/data/common/search/aggs/buckets/multi_terms.test.ts" + }, + { + "plugin": "data", + "path": "src/plugins/data/common/search/aggs/buckets/rare_terms.test.ts" + }, + { + "plugin": "data", + "path": "src/plugins/data/common/search/aggs/buckets/terms.test.ts" + }, + { + "plugin": "data", + "path": "src/plugins/data/common/search/aggs/buckets/terms.test.ts" + }, + { + "plugin": "data", + "path": "src/plugins/data/public/query/filter_manager/lib/get_display_value.test.ts" + }, + { + "plugin": "discover", + "path": "src/plugins/discover/public/application/main/hooks/use_adhoc_data_views.test.ts" + }, + { + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/public/application/components/lib/convert_series_to_datatable.test.ts" + }, + { + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/public/convert_to_lens/lib/datasource/get_datasource_info.test.ts" + }, + { + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/public/convert_to_lens/lib/datasource/get_datasource_info.test.ts" + }, + { + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/public/convert_to_lens/lib/datasource/get_datasource_info.test.ts" + }, + { + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/server/lib/search_strategies/lib/cached_index_pattern_fetcher.test.ts" + }, + { + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/server/lib/search_strategies/lib/cached_index_pattern_fetcher.test.ts" + }, + { + "plugin": "discover", + "path": "src/plugins/discover/public/application/main/components/layout/__stories__/get_layout_props.ts" + }, + { + "plugin": "lens", + "path": "x-pack/plugins/lens/public/data_views_service/loader.test.ts" + }, + { + "plugin": "lens", + "path": "x-pack/plugins/lens/public/data_views_service/loader.test.ts" + }, + { + "plugin": "lens", + "path": "x-pack/plugins/lens/public/data_views_service/loader.test.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/sourcerer/routes/index.ts" + }, + { + "plugin": "securitySolution", + "path": "x-pack/plugins/security_solution/server/lib/sourcerer/routes/index.ts" + } + ] }, { "parentPluginId": "dataViews", @@ -13340,6 +16100,60 @@ "children": [], "returnComment": [] }, + { + "parentPluginId": "dataViews", + "id": "def-common.DataView.getIndexPattern", + "type": "Function", + "tags": [], + "label": "getIndexPattern", + "description": [ + "\nGet index pattern" + ], + "signature": [ + "() => string" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [ + "index pattern string" + ] + }, + { + "parentPluginId": "dataViews", + "id": "def-common.DataView.setIndexPattern", + "type": "Function", + "tags": [], + "label": "setIndexPattern", + "description": [ + "\nSet index pattern" + ], + "signature": [ + "(indexPattern: string) => void" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "dataViews", + "id": "def-common.DataView.setIndexPattern.$1", + "type": "string", + "tags": [], + "label": "indexPattern", + "description": [], + "signature": [ + "string" + ], + "path": "src/plugins/data_views/common/data_views/data_view.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, { "parentPluginId": "dataViews", "id": "def-common.DataView.getOriginalSavedObjectBody", diff --git a/api_docs/data_views.mdx b/api_docs/data_views.mdx index 6c3fe9e7afdc9..4dc453cc326d1 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-10 +date: 2022-10-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViews'] --- import dataViewsObj from './data_views.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 | |-------------------|-----------|------------------------|-----------------| -| 983 | 0 | 225 | 2 | +| 992 | 0 | 228 | 2 | ## Client diff --git a/api_docs/data_visualizer.mdx b/api_docs/data_visualizer.mdx index 62f252081b2cf..747a8397163b1 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-10 +date: 2022-10-16 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 37d2e5139c65b..0b242dfd2a006 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-10 +date: 2022-10-16 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -28,6 +28,9 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | savedObjects, embeddable, fleet, visualizations, dashboard, infra, canvas, graph, actions, alerting, enterpriseSearch, securitySolution, taskManager, savedSearch, ml, @kbn/core-saved-objects-server-internal | - | | | discover, maps, monitoring | - | | | unifiedSearch, discover, maps, infra, graph, securitySolution, stackAlerts, inputControlVis, savedObjects | - | +| | timelines, securitySolution, lists, threatIntelligence, dataViews, dataViewEditor, unifiedSearch, triggersActionsUi, savedObjectsManagement, unifiedFieldList, discover, aiops, presentationUtil, controls, lens, observability, infra, maps, dataVisualizer, ml, fleet, visTypeTimeseries, apm, reporting, graph, stackAlerts, synthetics, transform, upgradeAssistant, ux, dataViewManagement, inputControlVis, visDefaultEditor, visTypeTimelion, visTypeVega, data | - | +| | timelines, securitySolution, lists, threatIntelligence, dataViews, dataViewEditor, unifiedSearch, triggersActionsUi, savedObjectsManagement, unifiedFieldList, discover, aiops, presentationUtil, controls, lens, observability, infra, maps, dataVisualizer, ml, fleet, visTypeTimeseries, apm, reporting, graph, stackAlerts, synthetics, transform, upgradeAssistant, ux, dataViewManagement, inputControlVis, visDefaultEditor, visTypeTimelion, visTypeVega, data | - | +| | timelines, securitySolution, lists, threatIntelligence, data, dataViewEditor, unifiedSearch, triggersActionsUi, savedObjectsManagement, unifiedFieldList, discover, aiops, presentationUtil, controls, lens, observability, infra, maps, dataVisualizer, ml, fleet, visTypeTimeseries, apm, reporting, graph, stackAlerts, synthetics, transform, upgradeAssistant, ux, dataViewManagement, inputControlVis, visDefaultEditor, visTypeTimelion, visTypeVega | - | | | data, discover, embeddable | - | | | advancedSettings, discover | - | | | advancedSettings, discover | - | @@ -37,6 +40,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | dataViews, maps | - | | | dataViews, maps | - | | | maps | - | +| | maps, ml | - | | | unifiedSearch | - | | | unifiedSearch | - | | | visTypeTimeseries, graph, dataViewManagement, dataViews | - | @@ -48,10 +52,13 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | dataViews, dataViewManagement | - | | | dataViewManagement, dataViews | - | | | dataViews, dataViewManagement | - | -| | dataViewManagement | - | -| | dataViewManagement | - | | | home, data, esUiShared, spaces, savedObjectsManagement, fleet, observability, ml, apm, indexLifecycleManagement, synthetics, upgradeAssistant, ux, kibanaOverview | - | +| | spaces, savedObjectsManagement | - | +| | spaces, savedObjectsManagement | - | | | spaces, ml, canvas, osquery | - | +| | actions, ml, savedObjectsTagging, enterpriseSearch | - | +| | dataViewManagement | - | +| | dataViewManagement | - | | | canvas | - | | | canvas | - | | | canvas | - | @@ -62,9 +69,6 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | canvas | - | | | canvas | - | | | canvas | - | -| | spaces, savedObjectsManagement | - | -| | spaces, savedObjectsManagement | - | -| | actions, ml, savedObjectsTagging, enterpriseSearch | - | | | enterpriseSearch | - | | | console, @kbn/core-elasticsearch-server-internal | - | | | spaces, security, alerting | 8.8.0 | @@ -77,12 +81,12 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | maps, dashboard, @kbn/core-saved-objects-migration-server-internal | 8.8.0 | | | monitoring, kibanaUsageCollection, @kbn/core-apps-browser-internal, @kbn/core-metrics-server-internal, @kbn/core-status-server-internal, @kbn/core-usage-data-server-internal | 8.8.0 | | | savedObjectsTaggingOss, dashboard | 8.8.0 | +| | security, licenseManagement, ml, apm, crossClusterReplication, logstash, painlessLab, searchprofiler, watcher | 8.8.0 | | | security, fleet | 8.8.0 | | | security, fleet | 8.8.0 | | | security, fleet | 8.8.0 | | | management, fleet, security, kibanaOverview, @kbn/core-application-browser-internal, @kbn/core-application-browser-mocks | 8.8.0 | | | apm | 8.8.0 | -| | security, licenseManagement, ml, apm, crossClusterReplication, logstash, painlessLab, searchprofiler, watcher | 8.8.0 | | | security | 8.8.0 | | | mapsEms | 8.8.0 | | | ml, @kbn/core-http-browser-internal | 8.8.0 diff --git a/api_docs/deprecations_by_plugin.mdx b/api_docs/deprecations_by_plugin.mdx index 4c125f75cfa83..ab1906a84934e 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-10 +date: 2022-10-16 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -125,6 +125,16 @@ so TS and code-reference navigation might not highlight them. | +## aiops + +| Deprecated API | Reference location(s) | Remove By | +| ---------------|-----------|-----------| +| | [use_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/aiops/public/hooks/use_data.ts#:~:text=title), [full_time_range_selector_service.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/aiops/public/components/full_time_range_selector/full_time_range_selector_service.ts#:~:text=title), [explain_log_rate_spikes_analysis.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/aiops/public/components/explain_log_rate_spikes/explain_log_rate_spikes_analysis.tsx#:~:text=title), [log_categorization_page.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/aiops/public/components/log_categorization/log_categorization_page.tsx#:~:text=title), [use_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/aiops/public/hooks/use_data.ts#:~:text=title), [full_time_range_selector_service.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/aiops/public/components/full_time_range_selector/full_time_range_selector_service.ts#:~:text=title), [explain_log_rate_spikes_analysis.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/aiops/public/components/explain_log_rate_spikes/explain_log_rate_spikes_analysis.tsx#:~:text=title), [log_categorization_page.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/aiops/public/components/log_categorization/log_categorization_page.tsx#:~:text=title) | - | +| | [use_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/aiops/public/hooks/use_data.ts#:~:text=title), [full_time_range_selector_service.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/aiops/public/components/full_time_range_selector/full_time_range_selector_service.ts#:~:text=title), [explain_log_rate_spikes_analysis.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/aiops/public/components/explain_log_rate_spikes/explain_log_rate_spikes_analysis.tsx#:~:text=title), [log_categorization_page.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/aiops/public/components/log_categorization/log_categorization_page.tsx#:~:text=title), [use_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/aiops/public/hooks/use_data.ts#:~:text=title), [full_time_range_selector_service.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/aiops/public/components/full_time_range_selector/full_time_range_selector_service.ts#:~:text=title), [explain_log_rate_spikes_analysis.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/aiops/public/components/explain_log_rate_spikes/explain_log_rate_spikes_analysis.tsx#:~:text=title), [log_categorization_page.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/aiops/public/components/log_categorization/log_categorization_page.tsx#:~:text=title) | - | +| | [use_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/aiops/public/hooks/use_data.ts#:~:text=title), [full_time_range_selector_service.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/aiops/public/components/full_time_range_selector/full_time_range_selector_service.ts#:~:text=title), [explain_log_rate_spikes_analysis.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/aiops/public/components/explain_log_rate_spikes/explain_log_rate_spikes_analysis.tsx#:~:text=title), [log_categorization_page.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/aiops/public/components/log_categorization/log_categorization_page.tsx#:~:text=title) | - | + + + ## alerting | Deprecated API | Reference location(s) | Remove By | @@ -136,8 +146,8 @@ so TS and code-reference navigation might not highlight them. | | | [plugin.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/alerting/server/plugin.test.ts#:~:text=getKibanaFeatures) | 8.8.0 | | | [plugin.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/alerting/server/plugin.ts#:~:text=license%24), [license_state.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/alerting/server/lib/license_state.test.ts#:~:text=license%24), [license_state.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/alerting/server/lib/license_state.test.ts#:~:text=license%24) | 8.8.0 | | | [task.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/alerting/server/usage/task.ts#:~:text=index) | - | -| | [rule.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/alerting/common/rule.ts#:~:text=SavedObjectAttributes), [rule.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/alerting/common/rule.ts#:~:text=SavedObjectAttributes), [rule.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/alerting/common/rule.ts#:~:text=SavedObjectAttributes), [rule.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/alerting/common/rule.ts#:~:text=SavedObjectAttributes), [rule.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/alerting/common/rule.ts#:~:text=SavedObjectAttributes), [rule.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/alerting/common/rule.ts#:~:text=SavedObjectAttributes), [migrations.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/alerting/server/saved_objects/geo_containment/migrations.ts#:~:text=SavedObjectAttributes), [migrations.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/alerting/server/saved_objects/geo_containment/migrations.ts#:~:text=SavedObjectAttributes), [migrations.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/alerting/server/saved_objects/migrations.ts#:~:text=SavedObjectAttributes), [migrations.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/alerting/server/saved_objects/migrations.ts#:~:text=SavedObjectAttributes)+ 10 more | - | -| | [rule.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/alerting/common/rule.ts#:~:text=SavedObjectAttributes), [rule.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/alerting/common/rule.ts#:~:text=SavedObjectAttributes), [rule.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/alerting/common/rule.ts#:~:text=SavedObjectAttributes), [rule.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/alerting/common/rule.ts#:~:text=SavedObjectAttributes), [rule.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/alerting/common/rule.ts#:~:text=SavedObjectAttributes), [rule.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/alerting/common/rule.ts#:~:text=SavedObjectAttributes), [migrations.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/alerting/server/saved_objects/geo_containment/migrations.ts#:~:text=SavedObjectAttributes), [migrations.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/alerting/server/saved_objects/geo_containment/migrations.ts#:~:text=SavedObjectAttributes), [migrations.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/alerting/server/saved_objects/migrations.ts#:~:text=SavedObjectAttributes), [migrations.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/alerting/server/saved_objects/migrations.ts#:~:text=SavedObjectAttributes)+ 10 more | - | +| | [rule.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/alerting/common/rule.ts#:~:text=SavedObjectAttributes), [rule.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/alerting/common/rule.ts#:~:text=SavedObjectAttributes), [rule.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/alerting/common/rule.ts#:~:text=SavedObjectAttributes), [rule.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/alerting/common/rule.ts#:~:text=SavedObjectAttributes), [rule.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/alerting/common/rule.ts#:~:text=SavedObjectAttributes), [rule.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/alerting/common/rule.ts#:~:text=SavedObjectAttributes), [migrations.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/alerting/server/saved_objects/geo_containment/migrations.ts#:~:text=SavedObjectAttributes), [migrations.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/alerting/server/saved_objects/geo_containment/migrations.ts#:~:text=SavedObjectAttributes), [types.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/alerting/server/types.ts#:~:text=SavedObjectAttributes), [types.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/alerting/server/types.ts#:~:text=SavedObjectAttributes)+ 11 more | - | +| | [rule.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/alerting/common/rule.ts#:~:text=SavedObjectAttributes), [rule.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/alerting/common/rule.ts#:~:text=SavedObjectAttributes), [rule.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/alerting/common/rule.ts#:~:text=SavedObjectAttributes), [rule.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/alerting/common/rule.ts#:~:text=SavedObjectAttributes), [rule.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/alerting/common/rule.ts#:~:text=SavedObjectAttributes), [rule.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/alerting/common/rule.ts#:~:text=SavedObjectAttributes), [migrations.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/alerting/server/saved_objects/geo_containment/migrations.ts#:~:text=SavedObjectAttributes), [migrations.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/alerting/server/saved_objects/geo_containment/migrations.ts#:~:text=SavedObjectAttributes), [types.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/alerting/server/types.ts#:~:text=SavedObjectAttributes), [types.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/alerting/server/types.ts#:~:text=SavedObjectAttributes)+ 11 more | - | @@ -145,6 +155,9 @@ so TS and code-reference navigation might not highlight them. | | Deprecated API | Reference location(s) | Remove By | | ---------------|-----------|-----------| +| | [create_static_data_view.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/apm/server/routes/data_view/create_static_data_view.ts#:~:text=title), [create_static_data_view.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/apm/server/routes/data_view/create_static_data_view.ts#:~:text=title) | - | +| | [create_static_data_view.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/apm/server/routes/data_view/create_static_data_view.ts#:~:text=title), [create_static_data_view.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/apm/server/routes/data_view/create_static_data_view.ts#:~:text=title) | - | +| | [create_static_data_view.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/apm/server/routes/data_view/create_static_data_view.ts#:~:text=title) | - | | | [plugin.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/apm/public/plugin.ts#:~:text=environment) | 8.8.0 | | | [app_root.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/apm/public/components/routing/app_root.tsx#:~:text=RedirectAppLinks), [app_root.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/apm/public/components/routing/app_root.tsx#:~:text=RedirectAppLinks), [app_root.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/apm/public/components/routing/app_root.tsx#:~:text=RedirectAppLinks) | - | | | [license_check.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/apm/common/license_check.test.ts#:~:text=mode), [license_check.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/apm/common/license_check.test.ts#:~:text=mode), [license_check.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/apm/common/license_check.test.ts#:~:text=mode), [license_check.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/apm/common/license_check.test.ts#:~:text=mode), [license_check.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/apm/common/license_check.test.ts#:~:text=mode), [license_check.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/apm/common/license_check.test.ts#:~:text=mode), [license_check.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/apm/common/license_check.test.ts#:~:text=mode), [license_check.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/apm/common/license_check.test.ts#:~:text=mode), [license_check.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/apm/common/license_check.test.ts#:~:text=mode), [license_check.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/apm/common/license_check.test.ts#:~:text=mode)+ 2 more | 8.8.0 | @@ -197,6 +210,16 @@ so TS and code-reference navigation might not highlight them. | +## controls + +| Deprecated API | Reference location(s) | Remove By | +| ---------------|-----------|-----------| +| | [options_list_service.ts](https://github.com/elastic/kibana/tree/main/src/plugins/controls/public/services/options_list/options_list_service.ts#:~:text=title), [options_list_service.ts](https://github.com/elastic/kibana/tree/main/src/plugins/controls/public/services/options_list/options_list_service.ts#:~:text=title), [data_views.story.ts](https://github.com/elastic/kibana/tree/main/src/plugins/controls/public/services/data_views/data_views.story.ts#:~:text=title), [options_list_service.ts](https://github.com/elastic/kibana/tree/main/src/plugins/controls/public/services/options_list/options_list_service.ts#:~:text=title), [options_list_service.ts](https://github.com/elastic/kibana/tree/main/src/plugins/controls/public/services/options_list/options_list_service.ts#:~:text=title), [data_views.story.ts](https://github.com/elastic/kibana/tree/main/src/plugins/controls/public/services/data_views/data_views.story.ts#:~:text=title) | - | +| | [options_list_service.ts](https://github.com/elastic/kibana/tree/main/src/plugins/controls/public/services/options_list/options_list_service.ts#:~:text=title), [options_list_service.ts](https://github.com/elastic/kibana/tree/main/src/plugins/controls/public/services/options_list/options_list_service.ts#:~:text=title), [data_views.story.ts](https://github.com/elastic/kibana/tree/main/src/plugins/controls/public/services/data_views/data_views.story.ts#:~:text=title), [options_list_service.ts](https://github.com/elastic/kibana/tree/main/src/plugins/controls/public/services/options_list/options_list_service.ts#:~:text=title), [options_list_service.ts](https://github.com/elastic/kibana/tree/main/src/plugins/controls/public/services/options_list/options_list_service.ts#:~:text=title), [data_views.story.ts](https://github.com/elastic/kibana/tree/main/src/plugins/controls/public/services/data_views/data_views.story.ts#:~:text=title) | - | +| | [options_list_service.ts](https://github.com/elastic/kibana/tree/main/src/plugins/controls/public/services/options_list/options_list_service.ts#:~:text=title), [options_list_service.ts](https://github.com/elastic/kibana/tree/main/src/plugins/controls/public/services/options_list/options_list_service.ts#:~:text=title), [data_views.story.ts](https://github.com/elastic/kibana/tree/main/src/plugins/controls/public/services/data_views/data_views.story.ts#:~:text=title) | - | + + + ## crossClusterReplication | Deprecated API | Reference location(s) | Remove By | @@ -224,22 +247,38 @@ so TS and code-reference navigation might not highlight them. | | Deprecated API | Reference location(s) | Remove By | | ---------------|-----------|-----------| +| | [kibana_context.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/expressions/kibana_context.test.ts#:~:text=title), [kibana_context.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/expressions/kibana_context.test.ts#:~:text=title), [kibana_context.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/expressions/kibana_context.test.ts#:~:text=title), [get_display_value.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/public/query/filter_manager/lib/get_display_value.ts#:~:text=title), [inspector_stats.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/search_source/inspect/inspector_stats.ts#:~:text=title), [response_writer.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/tabify/response_writer.ts#:~:text=title), [painless_error.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data/public/search/errors/painless_error.tsx#:~:text=title), [field.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/aggs/param_types/field.ts#:~:text=title), [agg_config.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/aggs/agg_config.test.ts#:~:text=title), [_terms_other_bucket_helper.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/aggs/buckets/_terms_other_bucket_helper.test.ts#:~:text=title)+ 6 more | - | +| | [kibana_context.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/expressions/kibana_context.test.ts#:~:text=title), [kibana_context.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/expressions/kibana_context.test.ts#:~:text=title), [kibana_context.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/expressions/kibana_context.test.ts#:~:text=title), [get_display_value.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/public/query/filter_manager/lib/get_display_value.ts#:~:text=title), [inspector_stats.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/search_source/inspect/inspector_stats.ts#:~:text=title), [response_writer.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/tabify/response_writer.ts#:~:text=title), [painless_error.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data/public/search/errors/painless_error.tsx#:~:text=title), [field.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/aggs/param_types/field.ts#:~:text=title), [agg_config.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/aggs/agg_config.test.ts#:~:text=title), [_terms_other_bucket_helper.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/aggs/buckets/_terms_other_bucket_helper.test.ts#:~:text=title)+ 6 more | - | +| | [kibana_context.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/expressions/kibana_context.test.ts#:~:text=title), [kibana_context.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/expressions/kibana_context.test.ts#:~:text=title), [kibana_context.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/expressions/kibana_context.test.ts#:~:text=title), [get_display_value.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/public/query/filter_manager/lib/get_display_value.ts#:~:text=title), [inspector_stats.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/search_source/inspect/inspector_stats.ts#:~:text=title), [response_writer.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/tabify/response_writer.ts#:~:text=title), [painless_error.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data/public/search/errors/painless_error.tsx#:~:text=title), [field.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/aggs/param_types/field.ts#:~:text=title), [agg_config.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/aggs/agg_config.test.ts#:~:text=title), [_terms_other_bucket_helper.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/common/search/aggs/buckets/_terms_other_bucket_helper.test.ts#:~:text=title)+ 6 more | - | | | [get_columns.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data/public/search/session/sessions_mgmt/lib/get_columns.tsx#:~:text=RedirectAppLinks), [get_columns.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data/public/search/session/sessions_mgmt/lib/get_columns.tsx#:~:text=RedirectAppLinks), [get_columns.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data/public/search/session/sessions_mgmt/lib/get_columns.tsx#:~:text=RedirectAppLinks), [connected_search_session_indicator.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data/public/search/session/session_indicator/connected_search_session_indicator/connected_search_session_indicator.tsx#:~:text=RedirectAppLinks), [connected_search_session_indicator.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data/public/search/session/session_indicator/connected_search_session_indicator/connected_search_session_indicator.tsx#:~:text=RedirectAppLinks), [connected_search_session_indicator.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data/public/search/session/session_indicator/connected_search_session_indicator/connected_search_session_indicator.tsx#:~:text=RedirectAppLinks) | - | | | [data_table.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data/public/utils/table_inspector_view/components/data_table.tsx#:~:text=executeTriggerActions), [data_table.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data/public/utils/table_inspector_view/components/data_table.tsx#:~:text=executeTriggerActions) | - | | | [session_service.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data/server/search/session/session_service.ts#:~:text=authc) | - | +## dataViewEditor + +| Deprecated API | Reference location(s) | Remove By | +| ---------------|-----------|-----------| +| | [data_view_editor_flyout_content.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_editor/public/components/data_view_editor_flyout_content.tsx#:~:text=title), [data_view_editor_flyout_content.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_editor/public/components/data_view_editor_flyout_content.tsx#:~:text=title) | - | +| | [data_view_editor_flyout_content.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_editor/public/components/data_view_editor_flyout_content.tsx#:~:text=title), [data_view_editor_flyout_content.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_editor/public/components/data_view_editor_flyout_content.tsx#:~:text=title) | - | +| | [data_view_editor_flyout_content.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_editor/public/components/data_view_editor_flyout_content.tsx#:~:text=title) | - | + + + ## dataViewManagement | Deprecated API | Reference location(s) | Remove By | | ---------------|-----------|-----------| +| | [edit_index_pattern.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_management/public/components/edit_index_pattern/edit_index_pattern.tsx#:~:text=title), [edit_index_pattern.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_management/public/components/edit_index_pattern/edit_index_pattern.tsx#:~:text=title), [test_script.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_management/public/components/field_editor/components/scripting_help/test_script.tsx#:~:text=title), [field_editor.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_management/public/components/field_editor/field_editor.tsx#:~:text=title), [create_edit_field.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_management/public/components/edit_index_pattern/create_edit_field/create_edit_field.tsx#:~:text=title), [edit_index_pattern.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_management/public/components/edit_index_pattern/edit_index_pattern.tsx#:~:text=title), [edit_index_pattern.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_management/public/components/edit_index_pattern/edit_index_pattern.tsx#:~:text=title), [test_script.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_management/public/components/field_editor/components/scripting_help/test_script.tsx#:~:text=title), [field_editor.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_management/public/components/field_editor/field_editor.tsx#:~:text=title), [create_edit_field.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_management/public/components/edit_index_pattern/create_edit_field/create_edit_field.tsx#:~:text=title) | - | | | [scripted_fields_table.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_management/public/components/edit_index_pattern/scripted_fields_table/scripted_fields_table.tsx#:~:text=removeScriptedField), [field_editor.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_management/public/components/field_editor/field_editor.tsx#:~:text=removeScriptedField), [scripted_fields_table.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_management/public/components/edit_index_pattern/scripted_fields_table/scripted_fields_table.tsx#:~:text=removeScriptedField), [field_editor.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_management/public/components/field_editor/field_editor.tsx#:~:text=removeScriptedField) | - | | | [table.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_management/public/components/edit_index_pattern/source_filters_table/components/table/table.tsx#:~:text=getNonScriptedFields), [edit_index_pattern.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_management/public/components/edit_index_pattern/edit_index_pattern.tsx#:~:text=getNonScriptedFields), [edit_index_pattern.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_management/public/components/edit_index_pattern/edit_index_pattern.tsx#:~:text=getNonScriptedFields), [edit_index_pattern.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_management/public/components/edit_index_pattern/edit_index_pattern.tsx#:~:text=getNonScriptedFields), [table.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_management/public/components/edit_index_pattern/source_filters_table/components/table/table.tsx#:~:text=getNonScriptedFields), [edit_index_pattern.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_management/public/components/edit_index_pattern/edit_index_pattern.tsx#:~:text=getNonScriptedFields), [edit_index_pattern.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_management/public/components/edit_index_pattern/edit_index_pattern.tsx#:~:text=getNonScriptedFields), [edit_index_pattern.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_management/public/components/edit_index_pattern/edit_index_pattern.tsx#:~:text=getNonScriptedFields) | - | | | [scripted_fields_table.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_management/public/components/edit_index_pattern/scripted_fields_table/scripted_fields_table.tsx#:~:text=getScriptedFields), [scripted_fields_table.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_management/public/components/edit_index_pattern/scripted_fields_table/scripted_fields_table.tsx#:~:text=getScriptedFields) | - | +| | [edit_index_pattern.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_management/public/components/edit_index_pattern/edit_index_pattern.tsx#:~:text=title), [edit_index_pattern.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_management/public/components/edit_index_pattern/edit_index_pattern.tsx#:~:text=title), [test_script.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_management/public/components/field_editor/components/scripting_help/test_script.tsx#:~:text=title), [field_editor.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_management/public/components/field_editor/field_editor.tsx#:~:text=title), [create_edit_field.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_management/public/components/edit_index_pattern/create_edit_field/create_edit_field.tsx#:~:text=title), [edit_index_pattern.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_management/public/components/edit_index_pattern/edit_index_pattern.tsx#:~:text=title), [edit_index_pattern.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_management/public/components/edit_index_pattern/edit_index_pattern.tsx#:~:text=title), [test_script.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_management/public/components/field_editor/components/scripting_help/test_script.tsx#:~:text=title), [field_editor.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_management/public/components/field_editor/field_editor.tsx#:~:text=title), [create_edit_field.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_management/public/components/edit_index_pattern/create_edit_field/create_edit_field.tsx#:~:text=title) | - | | | [scripted_fields_table.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_management/public/components/edit_index_pattern/scripted_fields_table/scripted_fields_table.tsx#:~:text=removeScriptedField), [field_editor.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_management/public/components/field_editor/field_editor.tsx#:~:text=removeScriptedField), [scripted_fields_table.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_management/public/components/edit_index_pattern/scripted_fields_table/scripted_fields_table.tsx#:~:text=removeScriptedField), [field_editor.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_management/public/components/field_editor/field_editor.tsx#:~:text=removeScriptedField) | - | | | [table.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_management/public/components/edit_index_pattern/source_filters_table/components/table/table.tsx#:~:text=getNonScriptedFields), [edit_index_pattern.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_management/public/components/edit_index_pattern/edit_index_pattern.tsx#:~:text=getNonScriptedFields), [edit_index_pattern.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_management/public/components/edit_index_pattern/edit_index_pattern.tsx#:~:text=getNonScriptedFields), [edit_index_pattern.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_management/public/components/edit_index_pattern/edit_index_pattern.tsx#:~:text=getNonScriptedFields), [table.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_management/public/components/edit_index_pattern/source_filters_table/components/table/table.tsx#:~:text=getNonScriptedFields), [edit_index_pattern.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_management/public/components/edit_index_pattern/edit_index_pattern.tsx#:~:text=getNonScriptedFields), [edit_index_pattern.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_management/public/components/edit_index_pattern/edit_index_pattern.tsx#:~:text=getNonScriptedFields), [edit_index_pattern.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_management/public/components/edit_index_pattern/edit_index_pattern.tsx#:~:text=getNonScriptedFields) | - | | | [scripted_fields_table.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_management/public/components/edit_index_pattern/scripted_fields_table/scripted_fields_table.tsx#:~:text=getScriptedFields), [scripted_fields_table.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_management/public/components/edit_index_pattern/scripted_fields_table/scripted_fields_table.tsx#:~:text=getScriptedFields) | - | +| | [edit_index_pattern.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_management/public/components/edit_index_pattern/edit_index_pattern.tsx#:~:text=title), [edit_index_pattern.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_management/public/components/edit_index_pattern/edit_index_pattern.tsx#:~:text=title), [test_script.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_management/public/components/field_editor/components/scripting_help/test_script.tsx#:~:text=title), [field_editor.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_management/public/components/field_editor/field_editor.tsx#:~:text=title), [create_edit_field.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_management/public/components/edit_index_pattern/create_edit_field/create_edit_field.tsx#:~:text=title) | - | | | [scripted_fields_table.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_management/public/components/edit_index_pattern/scripted_fields_table/scripted_fields_table.tsx#:~:text=removeScriptedField), [field_editor.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_management/public/components/field_editor/field_editor.tsx#:~:text=removeScriptedField) | - | | | [table.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_management/public/components/edit_index_pattern/source_filters_table/components/table/table.tsx#:~:text=getNonScriptedFields), [edit_index_pattern.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_management/public/components/edit_index_pattern/edit_index_pattern.tsx#:~:text=getNonScriptedFields), [edit_index_pattern.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_management/public/components/edit_index_pattern/edit_index_pattern.tsx#:~:text=getNonScriptedFields), [edit_index_pattern.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_management/public/components/edit_index_pattern/edit_index_pattern.tsx#:~:text=getNonScriptedFields) | - | | | [scripted_fields_table.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/data_view_management/public/components/edit_index_pattern/scripted_fields_table/scripted_fields_table.tsx#:~:text=getScriptedFields) | - | @@ -250,10 +289,12 @@ so TS and code-reference navigation might not highlight them. | | Deprecated API | Reference location(s) | Remove By | | ---------------|-----------|-----------| +| | [data_view.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data_views/common/data_views/data_view.ts#:~:text=title), [data_view.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data_views/common/data_views/data_view.ts#:~:text=title), [data_view.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data_views/common/data_views/data_view.ts#:~:text=title), [data_view.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data_views/common/data_views/data_view.ts#:~:text=title), [update_data_view.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data_views/server/rest_api_routes/update_data_view.ts#:~:text=title), [update_data_view.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data_views/server/rest_api_routes/update_data_view.ts#:~:text=title), [data_views.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data_views/common/data_views/data_views.ts#:~:text=title) | - | | | [data_view.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data_views/common/data_views/data_view.ts#:~:text=flattenHit) | - | | | [data_view.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data_views/common/data_views/data_view.test.ts#:~:text=removeScriptedField) | - | | | [data_view.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data_views/common/data_views/data_view.test.ts#:~:text=getNonScriptedFields) | - | | | [data_view.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data_views/common/data_views/data_view.ts#:~:text=getScriptedFields), [data_view.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data_views/common/data_views/data_view.ts#:~:text=getScriptedFields), [data_views.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data_views/common/data_views/data_views.ts#:~:text=getScriptedFields), [register_index_pattern_usage_collection.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data_views/server/register_index_pattern_usage_collection.ts#:~:text=getScriptedFields), [data_view.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data_views/common/data_views/data_view.test.ts#:~:text=getScriptedFields), [data_view.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data_views/common/data_views/data_view.test.ts#:~:text=getScriptedFields), [data_view.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data_views/common/data_views/data_view.test.ts#:~:text=getScriptedFields), [data_view.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data_views/common/data_views/data_view.test.ts#:~:text=getScriptedFields), [data_view.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data_views/common/data_views/data_view.test.ts#:~:text=getScriptedFields) | - | +| | [data_view.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data_views/common/data_views/data_view.ts#:~:text=title), [data_view.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data_views/common/data_views/data_view.ts#:~:text=title), [data_view.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data_views/common/data_views/data_view.ts#:~:text=title), [data_view.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data_views/common/data_views/data_view.ts#:~:text=title), [update_data_view.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data_views/server/rest_api_routes/update_data_view.ts#:~:text=title), [update_data_view.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data_views/server/rest_api_routes/update_data_view.ts#:~:text=title), [data_views.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data_views/common/data_views/data_views.ts#:~:text=title) | - | | | [data_view.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data_views/common/data_views/data_view.ts#:~:text=flattenHit) | - | | | [data_view.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data_views/common/data_views/data_view.test.ts#:~:text=removeScriptedField) | - | | | [data_view.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/data_views/common/data_views/data_view.test.ts#:~:text=getNonScriptedFields) | - | @@ -266,6 +307,9 @@ so TS and code-reference navigation might not highlight them. | | Deprecated API | Reference location(s) | Remove By | | ---------------|-----------|-----------| | | [top_values.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/common/components/top_values/top_values.tsx#:~:text=fieldFormats) | - | +| | [full_time_range_selector_service.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/full_time_range_selector/full_time_range_selector_service.ts#:~:text=title), [actions_panel.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/actions_panel/actions_panel.tsx#:~:text=title), [use_data_visualizer_grid_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/hooks/use_data_visualizer_grid_data.ts#:~:text=title), [index_data_visualizer_view.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/index_data_visualizer_view.tsx#:~:text=title), [full_time_range_selector_service.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/full_time_range_selector/full_time_range_selector_service.ts#:~:text=title), [actions_panel.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/actions_panel/actions_panel.tsx#:~:text=title), [use_data_visualizer_grid_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/hooks/use_data_visualizer_grid_data.ts#:~:text=title), [index_data_visualizer_view.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/index_data_visualizer_view.tsx#:~:text=title) | - | +| | [full_time_range_selector_service.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/full_time_range_selector/full_time_range_selector_service.ts#:~:text=title), [actions_panel.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/actions_panel/actions_panel.tsx#:~:text=title), [use_data_visualizer_grid_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/hooks/use_data_visualizer_grid_data.ts#:~:text=title), [index_data_visualizer_view.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/index_data_visualizer_view.tsx#:~:text=title), [full_time_range_selector_service.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/full_time_range_selector/full_time_range_selector_service.ts#:~:text=title), [actions_panel.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/actions_panel/actions_panel.tsx#:~:text=title), [use_data_visualizer_grid_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/hooks/use_data_visualizer_grid_data.ts#:~:text=title), [index_data_visualizer_view.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/index_data_visualizer_view.tsx#:~:text=title) | - | +| | [full_time_range_selector_service.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/full_time_range_selector/full_time_range_selector_service.ts#:~:text=title), [actions_panel.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/actions_panel/actions_panel.tsx#:~:text=title), [use_data_visualizer_grid_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/hooks/use_data_visualizer_grid_data.ts#:~:text=title), [index_data_visualizer_view.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/index_data_visualizer_view.tsx#:~:text=title) | - | | | [results_links.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/common/components/results_links/results_links.tsx#:~:text=indexPatternId), [actions_panel.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/actions_panel/actions_panel.tsx#:~:text=indexPatternId) | - | @@ -277,7 +321,10 @@ so TS and code-reference navigation might not highlight them. | | | [saved_search_embeddable.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/discover/public/embeddable/saved_search_embeddable.tsx#:~:text=create), [saved_search_embeddable.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/discover/public/embeddable/saved_search_embeddable.tsx#:~:text=create) | - | | | [discover_state.ts](https://github.com/elastic/kibana/tree/main/src/plugins/discover/public/application/main/services/discover_state.ts#:~:text=syncQueryStateWithUrl), [discover_state.ts](https://github.com/elastic/kibana/tree/main/src/plugins/discover/public/application/main/services/discover_state.ts#:~:text=syncQueryStateWithUrl) | - | | | [plugin.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/discover/public/plugin.tsx#:~:text=indexPatterns) | - | +| | [use_es_doc_search.ts](https://github.com/elastic/kibana/tree/main/src/plugins/discover/public/hooks/use_es_doc_search.ts#:~:text=title), [resolve_data_view.ts](https://github.com/elastic/kibana/tree/main/src/plugins/discover/public/application/main/utils/resolve_data_view.ts#:~:text=title), [resolve_data_view.ts](https://github.com/elastic/kibana/tree/main/src/plugins/discover/public/application/main/utils/resolve_data_view.ts#:~:text=title), [discover_sidebar.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar.tsx#:~:text=title), [discover_topnav.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/discover/public/application/main/components/top_nav/discover_topnav.tsx#:~:text=title), [use_adhoc_data_views.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/discover/public/application/main/hooks/use_adhoc_data_views.test.ts#:~:text=title), [get_layout_props.ts](https://github.com/elastic/kibana/tree/main/src/plugins/discover/public/application/main/components/layout/__stories__/get_layout_props.ts#:~:text=title), [use_es_doc_search.ts](https://github.com/elastic/kibana/tree/main/src/plugins/discover/public/hooks/use_es_doc_search.ts#:~:text=title), [resolve_data_view.ts](https://github.com/elastic/kibana/tree/main/src/plugins/discover/public/application/main/utils/resolve_data_view.ts#:~:text=title), [resolve_data_view.ts](https://github.com/elastic/kibana/tree/main/src/plugins/discover/public/application/main/utils/resolve_data_view.ts#:~:text=title)+ 4 more | - | | | [saved_search_embeddable.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/discover/public/embeddable/saved_search_embeddable.tsx#:~:text=create), [saved_search_embeddable.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/discover/public/embeddable/saved_search_embeddable.tsx#:~:text=create) | - | +| | [use_es_doc_search.ts](https://github.com/elastic/kibana/tree/main/src/plugins/discover/public/hooks/use_es_doc_search.ts#:~:text=title), [resolve_data_view.ts](https://github.com/elastic/kibana/tree/main/src/plugins/discover/public/application/main/utils/resolve_data_view.ts#:~:text=title), [resolve_data_view.ts](https://github.com/elastic/kibana/tree/main/src/plugins/discover/public/application/main/utils/resolve_data_view.ts#:~:text=title), [discover_sidebar.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar.tsx#:~:text=title), [discover_topnav.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/discover/public/application/main/components/top_nav/discover_topnav.tsx#:~:text=title), [use_adhoc_data_views.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/discover/public/application/main/hooks/use_adhoc_data_views.test.ts#:~:text=title), [get_layout_props.ts](https://github.com/elastic/kibana/tree/main/src/plugins/discover/public/application/main/components/layout/__stories__/get_layout_props.ts#:~:text=title), [use_es_doc_search.ts](https://github.com/elastic/kibana/tree/main/src/plugins/discover/public/hooks/use_es_doc_search.ts#:~:text=title), [resolve_data_view.ts](https://github.com/elastic/kibana/tree/main/src/plugins/discover/public/application/main/utils/resolve_data_view.ts#:~:text=title), [resolve_data_view.ts](https://github.com/elastic/kibana/tree/main/src/plugins/discover/public/application/main/utils/resolve_data_view.ts#:~:text=title)+ 4 more | - | +| | [use_es_doc_search.ts](https://github.com/elastic/kibana/tree/main/src/plugins/discover/public/hooks/use_es_doc_search.ts#:~:text=title), [resolve_data_view.ts](https://github.com/elastic/kibana/tree/main/src/plugins/discover/public/application/main/utils/resolve_data_view.ts#:~:text=title), [resolve_data_view.ts](https://github.com/elastic/kibana/tree/main/src/plugins/discover/public/application/main/utils/resolve_data_view.ts#:~:text=title), [discover_sidebar.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar.tsx#:~:text=title), [discover_topnav.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/discover/public/application/main/components/top_nav/discover_topnav.tsx#:~:text=title), [use_adhoc_data_views.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/discover/public/application/main/hooks/use_adhoc_data_views.test.ts#:~:text=title), [get_layout_props.ts](https://github.com/elastic/kibana/tree/main/src/plugins/discover/public/application/main/components/layout/__stories__/get_layout_props.ts#:~:text=title) | - | | | [on_save_search.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/discover/public/application/main/components/top_nav/on_save_search.tsx#:~:text=SavedObjectSaveModal), [on_save_search.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/discover/public/application/main/components/top_nav/on_save_search.tsx#:~:text=SavedObjectSaveModal) | 8.8.0 | | | [saved_search_embeddable.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/discover/public/embeddable/saved_search_embeddable.tsx#:~:text=executeTriggerActions), [search_embeddable_factory.ts](https://github.com/elastic/kibana/tree/main/src/plugins/discover/public/embeddable/search_embeddable_factory.ts#:~:text=executeTriggerActions), [plugin.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/discover/public/plugin.tsx#:~:text=executeTriggerActions) | - | | | [ui_settings.ts](https://github.com/elastic/kibana/tree/main/src/plugins/discover/server/ui_settings.ts#:~:text=metric), [ui_settings.ts](https://github.com/elastic/kibana/tree/main/src/plugins/discover/server/ui_settings.ts#:~:text=metric), [ui_settings.ts](https://github.com/elastic/kibana/tree/main/src/plugins/discover/server/ui_settings.ts#:~:text=metric) | - | @@ -343,6 +390,9 @@ so TS and code-reference navigation might not highlight them. | | Deprecated API | Reference location(s) | Remove By | | ---------------|-----------|-----------| +| | [filter_dataset.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/filter_dataset.tsx#:~:text=title), [filter_log_level.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/filter_log_level.tsx#:~:text=title), [query_bar.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/query_bar.tsx#:~:text=title), [search_bar.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/applications/fleet/components/search_bar.tsx#:~:text=title), [filter_dataset.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/filter_dataset.tsx#:~:text=title), [filter_log_level.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/filter_log_level.tsx#:~:text=title), [query_bar.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/query_bar.tsx#:~:text=title), [search_bar.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/applications/fleet/components/search_bar.tsx#:~:text=title) | - | +| | [filter_dataset.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/filter_dataset.tsx#:~:text=title), [filter_log_level.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/filter_log_level.tsx#:~:text=title), [query_bar.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/query_bar.tsx#:~:text=title), [search_bar.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/applications/fleet/components/search_bar.tsx#:~:text=title), [filter_dataset.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/filter_dataset.tsx#:~:text=title), [filter_log_level.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/filter_log_level.tsx#:~:text=title), [query_bar.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/query_bar.tsx#:~:text=title), [search_bar.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/applications/fleet/components/search_bar.tsx#:~:text=title) | - | +| | [filter_dataset.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/filter_dataset.tsx#:~:text=title), [filter_log_level.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/filter_log_level.tsx#:~:text=title), [query_bar.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/query_bar.tsx#:~:text=title), [search_bar.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/applications/fleet/components/search_bar.tsx#:~:text=title) | - | | | [use_get_logs_discover_link.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/multi_page_layout/hooks/use_get_logs_discover_link.tsx#:~:text=indexPatternId) | - | | | [tutorial_directory_header_link.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/components/home_integration/tutorial_directory_header_link.tsx#:~:text=RedirectAppLinks), [tutorial_directory_header_link.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/components/home_integration/tutorial_directory_header_link.tsx#:~:text=RedirectAppLinks), [tutorial_directory_header_link.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/components/home_integration/tutorial_directory_header_link.tsx#:~:text=RedirectAppLinks), [custom_assets_accordion.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/components/custom_assets_accordion.tsx#:~:text=RedirectAppLinks), [custom_assets_accordion.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/components/custom_assets_accordion.tsx#:~:text=RedirectAppLinks), [custom_assets_accordion.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/components/custom_assets_accordion.tsx#:~:text=RedirectAppLinks), [agent_logs.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/agent_logs.tsx#:~:text=RedirectAppLinks), [agent_logs.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/agent_logs.tsx#:~:text=RedirectAppLinks), [agent_logs.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/agent_logs.tsx#:~:text=RedirectAppLinks), [app.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/public/applications/integrations/app.tsx#:~:text=RedirectAppLinks)+ 5 more | - | | | [plugin.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/fleet/server/plugin.ts#:~:text=disabled) | 8.8.0 | @@ -359,8 +409,11 @@ so TS and code-reference navigation might not highlight them. | | Deprecated API | Reference location(s) | Remove By | | ---------------|-----------|-----------| | | [plugin.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/graph/public/plugin.ts#:~:text=indexPatterns) | - | +| | [datasource.sagas.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/graph/public/state_management/datasource.sagas.ts#:~:text=title), [persistence.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/graph/public/state_management/persistence.ts#:~:text=title), [persistence.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/graph/public/state_management/persistence.ts#:~:text=title), [datasource.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/graph/public/state_management/datasource.test.ts#:~:text=title), [datasource.sagas.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/graph/public/state_management/datasource.sagas.ts#:~:text=title), [persistence.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/graph/public/state_management/persistence.ts#:~:text=title), [persistence.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/graph/public/state_management/persistence.ts#:~:text=title), [datasource.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/graph/public/state_management/datasource.test.ts#:~:text=title) | - | | | [deserialize.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/graph/public/services/persistence/deserialize.ts#:~:text=getNonScriptedFields), [datasource.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/graph/public/state_management/datasource.test.ts#:~:text=getNonScriptedFields), [deserialize.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/graph/public/services/persistence/deserialize.test.ts#:~:text=getNonScriptedFields), [deserialize.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/graph/public/services/persistence/deserialize.test.ts#:~:text=getNonScriptedFields), [deserialize.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/graph/public/services/persistence/deserialize.ts#:~:text=getNonScriptedFields), [datasource.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/graph/public/state_management/datasource.test.ts#:~:text=getNonScriptedFields), [deserialize.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/graph/public/services/persistence/deserialize.test.ts#:~:text=getNonScriptedFields), [deserialize.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/graph/public/services/persistence/deserialize.test.ts#:~:text=getNonScriptedFields) | - | +| | [datasource.sagas.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/graph/public/state_management/datasource.sagas.ts#:~:text=title), [persistence.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/graph/public/state_management/persistence.ts#:~:text=title), [persistence.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/graph/public/state_management/persistence.ts#:~:text=title), [datasource.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/graph/public/state_management/datasource.test.ts#:~:text=title), [datasource.sagas.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/graph/public/state_management/datasource.sagas.ts#:~:text=title), [persistence.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/graph/public/state_management/persistence.ts#:~:text=title), [persistence.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/graph/public/state_management/persistence.ts#:~:text=title), [datasource.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/graph/public/state_management/datasource.test.ts#:~:text=title) | - | | | [deserialize.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/graph/public/services/persistence/deserialize.ts#:~:text=getNonScriptedFields), [datasource.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/graph/public/state_management/datasource.test.ts#:~:text=getNonScriptedFields), [deserialize.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/graph/public/services/persistence/deserialize.test.ts#:~:text=getNonScriptedFields), [deserialize.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/graph/public/services/persistence/deserialize.test.ts#:~:text=getNonScriptedFields), [deserialize.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/graph/public/services/persistence/deserialize.ts#:~:text=getNonScriptedFields), [datasource.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/graph/public/state_management/datasource.test.ts#:~:text=getNonScriptedFields), [deserialize.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/graph/public/services/persistence/deserialize.test.ts#:~:text=getNonScriptedFields), [deserialize.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/graph/public/services/persistence/deserialize.test.ts#:~:text=getNonScriptedFields) | - | +| | [datasource.sagas.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/graph/public/state_management/datasource.sagas.ts#:~:text=title), [persistence.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/graph/public/state_management/persistence.ts#:~:text=title), [persistence.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/graph/public/state_management/persistence.ts#:~:text=title), [datasource.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/graph/public/state_management/datasource.test.ts#:~:text=title) | - | | | [deserialize.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/graph/public/services/persistence/deserialize.ts#:~:text=getNonScriptedFields), [datasource.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/graph/public/state_management/datasource.test.ts#:~:text=getNonScriptedFields), [deserialize.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/graph/public/services/persistence/deserialize.test.ts#:~:text=getNonScriptedFields), [deserialize.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/graph/public/services/persistence/deserialize.test.ts#:~:text=getNonScriptedFields) | - | | | [save_modal.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/graph/public/components/save_modal.tsx#:~:text=SavedObjectSaveModal), [save_modal.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/graph/public/components/save_modal.tsx#:~:text=SavedObjectSaveModal) | 8.8.0 | | | [plugin.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/graph/server/plugin.ts#:~:text=license%24) | 8.8.0 | @@ -391,6 +444,9 @@ so TS and code-reference navigation might not highlight them. | | Deprecated API | Reference location(s) | Remove By | | ---------------|-----------|-----------| | | [use_kibana_index_patterns.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/infra/public/hooks/use_kibana_index_patterns.ts#:~:text=indexPatterns) | - | +| | [resolved_log_view.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/infra/common/log_views/resolved_log_view.ts#:~:text=title), [validation_errors.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/infra/public/pages/logs/settings/validation_errors.ts#:~:text=title), [validation_errors.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/infra/public/pages/logs/settings/validation_errors.ts#:~:text=title), [validation_errors.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/infra/public/pages/logs/settings/validation_errors.ts#:~:text=title), [validation_errors.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/infra/public/pages/logs/settings/validation_errors.ts#:~:text=title), [index_patterns.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/infra/common/dependency_mocks/index_patterns.ts#:~:text=title), [index_patterns.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/infra/common/dependency_mocks/index_patterns.ts#:~:text=title), [index_patterns.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/infra/common/dependency_mocks/index_patterns.ts#:~:text=title), [resolved_log_view.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/infra/common/log_views/resolved_log_view.ts#:~:text=title), [validation_errors.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/infra/public/pages/logs/settings/validation_errors.ts#:~:text=title)+ 6 more | - | +| | [resolved_log_view.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/infra/common/log_views/resolved_log_view.ts#:~:text=title), [validation_errors.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/infra/public/pages/logs/settings/validation_errors.ts#:~:text=title), [validation_errors.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/infra/public/pages/logs/settings/validation_errors.ts#:~:text=title), [validation_errors.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/infra/public/pages/logs/settings/validation_errors.ts#:~:text=title), [validation_errors.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/infra/public/pages/logs/settings/validation_errors.ts#:~:text=title), [index_patterns.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/infra/common/dependency_mocks/index_patterns.ts#:~:text=title), [index_patterns.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/infra/common/dependency_mocks/index_patterns.ts#:~:text=title), [index_patterns.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/infra/common/dependency_mocks/index_patterns.ts#:~:text=title), [resolved_log_view.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/infra/common/log_views/resolved_log_view.ts#:~:text=title), [validation_errors.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/infra/public/pages/logs/settings/validation_errors.ts#:~:text=title)+ 6 more | - | +| | [resolved_log_view.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/infra/common/log_views/resolved_log_view.ts#:~:text=title), [validation_errors.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/infra/public/pages/logs/settings/validation_errors.ts#:~:text=title), [validation_errors.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/infra/public/pages/logs/settings/validation_errors.ts#:~:text=title), [validation_errors.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/infra/public/pages/logs/settings/validation_errors.ts#:~:text=title), [validation_errors.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/infra/public/pages/logs/settings/validation_errors.ts#:~:text=title), [index_patterns.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/infra/common/dependency_mocks/index_patterns.ts#:~:text=title), [index_patterns.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/infra/common/dependency_mocks/index_patterns.ts#:~:text=title), [index_patterns.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/infra/common/dependency_mocks/index_patterns.ts#:~:text=title) | - | | | [use_find_saved_object.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/infra/public/hooks/use_find_saved_object.tsx#:~:text=SavedObjectAttributes), [use_find_saved_object.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/infra/public/hooks/use_find_saved_object.tsx#:~:text=SavedObjectAttributes), [use_create_saved_object.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/infra/public/hooks/use_create_saved_object.tsx#:~:text=SavedObjectAttributes), [use_create_saved_object.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/infra/public/hooks/use_create_saved_object.tsx#:~:text=SavedObjectAttributes), [use_create_saved_object.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/infra/public/hooks/use_create_saved_object.tsx#:~:text=SavedObjectAttributes), [use_get_saved_object.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/infra/public/hooks/use_get_saved_object.tsx#:~:text=SavedObjectAttributes), [use_get_saved_object.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/infra/public/hooks/use_get_saved_object.tsx#:~:text=SavedObjectAttributes), [use_update_saved_object.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/infra/public/hooks/use_update_saved_object.tsx#:~:text=SavedObjectAttributes), [use_update_saved_object.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/infra/public/hooks/use_update_saved_object.tsx#:~:text=SavedObjectAttributes), [use_update_saved_object.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/infra/public/hooks/use_update_saved_object.tsx#:~:text=SavedObjectAttributes)+ 2 more | - | | | [use_find_saved_object.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/infra/public/hooks/use_find_saved_object.tsx#:~:text=SavedObjectAttributes), [use_find_saved_object.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/infra/public/hooks/use_find_saved_object.tsx#:~:text=SavedObjectAttributes), [use_create_saved_object.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/infra/public/hooks/use_create_saved_object.tsx#:~:text=SavedObjectAttributes), [use_create_saved_object.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/infra/public/hooks/use_create_saved_object.tsx#:~:text=SavedObjectAttributes), [use_create_saved_object.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/infra/public/hooks/use_create_saved_object.tsx#:~:text=SavedObjectAttributes), [use_get_saved_object.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/infra/public/hooks/use_get_saved_object.tsx#:~:text=SavedObjectAttributes), [use_get_saved_object.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/infra/public/hooks/use_get_saved_object.tsx#:~:text=SavedObjectAttributes), [use_update_saved_object.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/infra/public/hooks/use_update_saved_object.tsx#:~:text=SavedObjectAttributes), [use_update_saved_object.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/infra/public/hooks/use_update_saved_object.tsx#:~:text=SavedObjectAttributes), [use_update_saved_object.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/infra/public/hooks/use_update_saved_object.tsx#:~:text=SavedObjectAttributes)+ 2 more | - | @@ -402,7 +458,10 @@ so TS and code-reference navigation might not highlight them. | | ---------------|-----------|-----------| | | [list_control_factory.ts](https://github.com/elastic/kibana/tree/main/src/plugins/input_control_vis/public/control/list_control_factory.ts#:~:text=fetch), [range_control_factory.ts](https://github.com/elastic/kibana/tree/main/src/plugins/input_control_vis/public/control/range_control_factory.ts#:~:text=fetch) | - | | | [list_control_factory.ts](https://github.com/elastic/kibana/tree/main/src/plugins/input_control_vis/public/control/list_control_factory.ts#:~:text=indexPatterns), [range_control_factory.ts](https://github.com/elastic/kibana/tree/main/src/plugins/input_control_vis/public/control/range_control_factory.ts#:~:text=indexPatterns), [controls_tab.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/input_control_vis/public/components/editor/controls_tab.tsx#:~:text=indexPatterns) | - | +| | [list_control_factory.ts](https://github.com/elastic/kibana/tree/main/src/plugins/input_control_vis/public/control/list_control_factory.ts#:~:text=title), [range_control_factory.ts](https://github.com/elastic/kibana/tree/main/src/plugins/input_control_vis/public/control/range_control_factory.ts#:~:text=title), [get_index_pattern_mock.ts](https://github.com/elastic/kibana/tree/main/src/plugins/input_control_vis/public/test_utils/get_index_pattern_mock.ts#:~:text=title), [list_control_factory.ts](https://github.com/elastic/kibana/tree/main/src/plugins/input_control_vis/public/control/list_control_factory.ts#:~:text=title), [range_control_factory.ts](https://github.com/elastic/kibana/tree/main/src/plugins/input_control_vis/public/control/range_control_factory.ts#:~:text=title), [get_index_pattern_mock.ts](https://github.com/elastic/kibana/tree/main/src/plugins/input_control_vis/public/test_utils/get_index_pattern_mock.ts#:~:text=title) | - | | | [list_control_factory.ts](https://github.com/elastic/kibana/tree/main/src/plugins/input_control_vis/public/control/list_control_factory.ts#:~:text=fetch), [range_control_factory.ts](https://github.com/elastic/kibana/tree/main/src/plugins/input_control_vis/public/control/range_control_factory.ts#:~:text=fetch) | - | +| | [list_control_factory.ts](https://github.com/elastic/kibana/tree/main/src/plugins/input_control_vis/public/control/list_control_factory.ts#:~:text=title), [range_control_factory.ts](https://github.com/elastic/kibana/tree/main/src/plugins/input_control_vis/public/control/range_control_factory.ts#:~:text=title), [get_index_pattern_mock.ts](https://github.com/elastic/kibana/tree/main/src/plugins/input_control_vis/public/test_utils/get_index_pattern_mock.ts#:~:text=title), [list_control_factory.ts](https://github.com/elastic/kibana/tree/main/src/plugins/input_control_vis/public/control/list_control_factory.ts#:~:text=title), [range_control_factory.ts](https://github.com/elastic/kibana/tree/main/src/plugins/input_control_vis/public/control/range_control_factory.ts#:~:text=title), [get_index_pattern_mock.ts](https://github.com/elastic/kibana/tree/main/src/plugins/input_control_vis/public/test_utils/get_index_pattern_mock.ts#:~:text=title) | - | +| | [list_control_factory.ts](https://github.com/elastic/kibana/tree/main/src/plugins/input_control_vis/public/control/list_control_factory.ts#:~:text=title), [range_control_factory.ts](https://github.com/elastic/kibana/tree/main/src/plugins/input_control_vis/public/control/range_control_factory.ts#:~:text=title), [get_index_pattern_mock.ts](https://github.com/elastic/kibana/tree/main/src/plugins/input_control_vis/public/test_utils/get_index_pattern_mock.ts#:~:text=title) | - | @@ -427,6 +486,9 @@ so TS and code-reference navigation might not highlight them. | | Deprecated API | Reference location(s) | Remove By | | ---------------|-----------|-----------| +| | [loader.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/data_views_service/loader.ts#:~:text=title), [lens_top_nav.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/app_plugin/lens_top_nav.tsx#:~:text=title), [loader.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/data_views_service/loader.test.ts#:~:text=title), [loader.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/data_views_service/loader.test.ts#:~:text=title), [loader.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/data_views_service/loader.test.ts#:~:text=title), [loader.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/data_views_service/loader.ts#:~:text=title), [lens_top_nav.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/app_plugin/lens_top_nav.tsx#:~:text=title), [loader.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/data_views_service/loader.test.ts#:~:text=title), [loader.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/data_views_service/loader.test.ts#:~:text=title), [loader.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/data_views_service/loader.test.ts#:~:text=title) | - | +| | [loader.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/data_views_service/loader.ts#:~:text=title), [lens_top_nav.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/app_plugin/lens_top_nav.tsx#:~:text=title), [loader.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/data_views_service/loader.test.ts#:~:text=title), [loader.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/data_views_service/loader.test.ts#:~:text=title), [loader.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/data_views_service/loader.test.ts#:~:text=title), [loader.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/data_views_service/loader.ts#:~:text=title), [lens_top_nav.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/app_plugin/lens_top_nav.tsx#:~:text=title), [loader.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/data_views_service/loader.test.ts#:~:text=title), [loader.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/data_views_service/loader.test.ts#:~:text=title), [loader.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/data_views_service/loader.test.ts#:~:text=title) | - | +| | [loader.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/data_views_service/loader.ts#:~:text=title), [lens_top_nav.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/app_plugin/lens_top_nav.tsx#:~:text=title), [loader.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/data_views_service/loader.test.ts#:~:text=title), [loader.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/data_views_service/loader.test.ts#:~:text=title), [loader.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/data_views_service/loader.test.ts#:~:text=title) | - | | | [types.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/app_plugin/types.ts#:~:text=onAppLeave), [types.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/app_plugin/types.ts#:~:text=onAppLeave), [mounter.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/app_plugin/mounter.tsx#:~:text=onAppLeave) | 8.8.0 | @@ -439,6 +501,16 @@ so TS and code-reference navigation might not highlight them. | +## lists + +| Deprecated API | Reference location(s) | Remove By | +| ---------------|-----------|-----------| +| | [helpers.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts#:~:text=title), [helpers.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts#:~:text=title), [helpers.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts#:~:text=title), [helpers.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts#:~:text=title), [helpers.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts#:~:text=title), [helpers.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts#:~:text=title), [helpers.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts#:~:text=title), [helpers.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts#:~:text=title), [helpers.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts#:~:text=title), [helpers.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts#:~:text=title)+ 8 more | - | +| | [helpers.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts#:~:text=title), [helpers.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts#:~:text=title), [helpers.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts#:~:text=title), [helpers.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts#:~:text=title), [helpers.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts#:~:text=title), [helpers.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts#:~:text=title), [helpers.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts#:~:text=title), [helpers.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts#:~:text=title), [helpers.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts#:~:text=title), [helpers.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts#:~:text=title)+ 8 more | - | +| | [helpers.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts#:~:text=title), [helpers.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts#:~:text=title), [helpers.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts#:~:text=title), [helpers.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts#:~:text=title), [helpers.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts#:~:text=title), [helpers.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts#:~:text=title), [helpers.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts#:~:text=title), [helpers.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts#:~:text=title), [helpers.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lists/public/exceptions/components/builder/helpers.test.ts#:~:text=title) | - | + + + ## logstash | Deprecated API | Reference location(s) | Remove By | @@ -462,9 +534,13 @@ so TS and code-reference navigation might not highlight them. | | ---------------|-----------|-----------| | | [global_sync.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/maps/public/routes/map_page/url_state/global_sync.ts#:~:text=syncQueryStateWithUrl), [global_sync.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/maps/public/routes/map_page/url_state/global_sync.ts#:~:text=syncQueryStateWithUrl) | - | | | [kibana_services.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/maps/public/kibana_services.ts#:~:text=indexPatterns) | - | +| | [es_geo_grid_source.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.tsx#:~:text=title), [scaling_form.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/maps/public/classes/sources/es_search_source/util/scaling_form.tsx#:~:text=title), [top_hits_form.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/maps/public/classes/sources/es_search_source/top_hits/top_hits_form.tsx#:~:text=title), [es_search_source.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx#:~:text=title), [es_search_source.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx#:~:text=title), [es_search_source.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx#:~:text=title), [es_search_source.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx#:~:text=title), [es_search_source.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx#:~:text=title), [es_search_source.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx#:~:text=title), [es_search_source.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx#:~:text=title)+ 14 more | - | | | [es_search_source.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx#:~:text=flattenHit), [es_search_source.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx#:~:text=flattenHit), [es_search_source.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx#:~:text=flattenHit), [es_search_source.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx#:~:text=flattenHit) | - | +| | [es_geo_grid_source.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.tsx#:~:text=title), [scaling_form.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/maps/public/classes/sources/es_search_source/util/scaling_form.tsx#:~:text=title), [top_hits_form.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/maps/public/classes/sources/es_search_source/top_hits/top_hits_form.tsx#:~:text=title), [es_search_source.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx#:~:text=title), [es_search_source.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx#:~:text=title), [es_search_source.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx#:~:text=title), [es_search_source.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx#:~:text=title), [es_search_source.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx#:~:text=title), [es_search_source.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx#:~:text=title), [es_search_source.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx#:~:text=title)+ 14 more | - | | | [es_search_source.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx#:~:text=flattenHit), [es_search_source.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx#:~:text=flattenHit), [es_search_source.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx#:~:text=flattenHit), [es_search_source.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx#:~:text=flattenHit) | - | +| | [es_geo_grid_source.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.tsx#:~:text=title), [scaling_form.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/maps/public/classes/sources/es_search_source/util/scaling_form.tsx#:~:text=title), [top_hits_form.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/maps/public/classes/sources/es_search_source/top_hits/top_hits_form.tsx#:~:text=title), [es_search_source.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx#:~:text=title), [es_search_source.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx#:~:text=title), [es_search_source.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx#:~:text=title), [es_search_source.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx#:~:text=title), [es_search_source.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx#:~:text=title), [es_search_source.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx#:~:text=title), [es_search_source.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx#:~:text=title)+ 2 more | - | | | [es_search_source.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx#:~:text=flattenHit), [es_search_source.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx#:~:text=flattenHit) | - | +| | [visualization.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/maps/public/lens/choropleth_chart/visualization.tsx#:~:text=layerTypes), [visualization.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/maps/public/lens/choropleth_chart/visualization.tsx#:~:text=layerTypes), [visualization.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/maps/public/lens/choropleth_chart/visualization.tsx#:~:text=layerTypes), [visualization.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/maps/public/lens/choropleth_chart/visualization.tsx#:~:text=layerTypes) | - | | | [render_app.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/maps/public/render_app.tsx#:~:text=onAppLeave), [map_app.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/maps/public/routes/map_page/map_app/map_app.tsx#:~:text=onAppLeave), [map_page.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/maps/public/routes/map_page/map_page.tsx#:~:text=onAppLeave) | 8.8.0 | | | [saved_object_migrations.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/maps/server/saved_objects/saved_object_migrations.ts#:~:text=warning) | 8.8.0 | @@ -483,8 +559,12 @@ so TS and code-reference navigation might not highlight them. | | Deprecated API | Reference location(s) | Remove By | | ---------------|-----------|-----------| +| | [index_utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/util/index_utils.ts#:~:text=title), [index_utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/util/index_utils.ts#:~:text=title), [index_utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/util/index_utils.ts#:~:text=title), [new_job_capabilities_service_analytics.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/services/new_job_capabilities/new_job_capabilities_service_analytics.ts#:~:text=title), [new_job_capabilities_service_analytics.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/services/new_job_capabilities/new_job_capabilities_service_analytics.ts#:~:text=title), [configuration_step_details.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_details.tsx#:~:text=title), [data_loader.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/datavisualizer/index_based/data_loader/data_loader.ts#:~:text=title), [use_index_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts#:~:text=title), [use_index_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts#:~:text=title), [use_index_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts#:~:text=title)+ 76 more | - | +| | [index_utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/util/index_utils.ts#:~:text=title), [index_utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/util/index_utils.ts#:~:text=title), [index_utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/util/index_utils.ts#:~:text=title), [new_job_capabilities_service_analytics.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/services/new_job_capabilities/new_job_capabilities_service_analytics.ts#:~:text=title), [new_job_capabilities_service_analytics.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/services/new_job_capabilities/new_job_capabilities_service_analytics.ts#:~:text=title), [configuration_step_details.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_details.tsx#:~:text=title), [data_loader.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/datavisualizer/index_based/data_loader/data_loader.ts#:~:text=title), [use_index_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts#:~:text=title), [use_index_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts#:~:text=title), [use_index_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts#:~:text=title)+ 76 more | - | +| | [index_utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/util/index_utils.ts#:~:text=title), [index_utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/util/index_utils.ts#:~:text=title), [index_utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/util/index_utils.ts#:~:text=title), [new_job_capabilities_service_analytics.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/services/new_job_capabilities/new_job_capabilities_service_analytics.ts#:~:text=title), [new_job_capabilities_service_analytics.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/services/new_job_capabilities/new_job_capabilities_service_analytics.ts#:~:text=title), [configuration_step_details.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_details.tsx#:~:text=title), [data_loader.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/datavisualizer/index_based/data_loader/data_loader.ts#:~:text=title), [use_index_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts#:~:text=title), [use_index_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts#:~:text=title), [use_index_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts#:~:text=title)+ 33 more | - | | | [ml_page.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/components/ml_page/ml_page.tsx#:~:text=KibanaPageTemplate), [ml_page.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/components/ml_page/ml_page.tsx#:~:text=KibanaPageTemplate), [ml_page.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/components/ml_page/ml_page.tsx#:~:text=KibanaPageTemplate) | - | | | [ml_page.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/components/ml_page/ml_page.tsx#:~:text=RedirectAppLinks), [ml_page.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/components/ml_page/ml_page.tsx#:~:text=RedirectAppLinks), [ml_page.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/components/ml_page/ml_page.tsx#:~:text=RedirectAppLinks), [jobs_list_page.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/management/jobs_list/components/jobs_list_page/jobs_list_page.tsx#:~:text=RedirectAppLinks), [jobs_list_page.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/management/jobs_list/components/jobs_list_page/jobs_list_page.tsx#:~:text=RedirectAppLinks), [jobs_list_page.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/management/jobs_list/components/jobs_list_page/jobs_list_page.tsx#:~:text=RedirectAppLinks) | - | +| | [utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/utils.ts#:~:text=layerTypes), [utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/utils.ts#:~:text=layerTypes), [utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/utils.ts#:~:text=layerTypes), [utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/utils.ts#:~:text=layerTypes), [utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/utils.ts#:~:text=layerTypes), [utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/utils.ts#:~:text=layerTypes), [visualization_extractor.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/visualization_extractor.ts#:~:text=layerTypes), [visualization_extractor.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/visualization_extractor.ts#:~:text=layerTypes), [visualization_extractor.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/visualization_extractor.ts#:~:text=layerTypes), [visualization_extractor.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/visualization_extractor.ts#:~:text=layerTypes) | - | | | [plugin.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/public/plugin.ts#:~:text=license%24) | 8.8.0 | | | [plugin.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/server/plugin.ts#:~:text=license%24), [plugin.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/server/plugin.ts#:~:text=license%24) | 8.8.0 | | | [annotations.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ml/server/routes/annotations.ts#:~:text=authc) | - | @@ -512,6 +592,9 @@ so TS and code-reference navigation might not highlight them. | | Deprecated API | Reference location(s) | Remove By | | ---------------|-----------|-----------| +| | [observability_data_views.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/utils/observability_data_views/observability_data_views.ts#:~:text=title), [report_definition_field.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/report_definition_field.tsx#:~:text=title), [use_filter_values.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/use_filter_values.ts#:~:text=title), [filter_value_btn.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/filter_value_btn.tsx#:~:text=title), [observability_data_views.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/utils/observability_data_views/observability_data_views.ts#:~:text=title), [report_definition_field.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/report_definition_field.tsx#:~:text=title), [use_filter_values.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/use_filter_values.ts#:~:text=title), [filter_value_btn.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/filter_value_btn.tsx#:~:text=title) | - | +| | [observability_data_views.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/utils/observability_data_views/observability_data_views.ts#:~:text=title), [report_definition_field.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/report_definition_field.tsx#:~:text=title), [use_filter_values.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/use_filter_values.ts#:~:text=title), [filter_value_btn.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/filter_value_btn.tsx#:~:text=title), [observability_data_views.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/utils/observability_data_views/observability_data_views.ts#:~:text=title), [report_definition_field.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/report_definition_field.tsx#:~:text=title), [use_filter_values.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/use_filter_values.ts#:~:text=title), [filter_value_btn.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/filter_value_btn.tsx#:~:text=title) | - | +| | [observability_data_views.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/utils/observability_data_views/observability_data_views.ts#:~:text=title), [report_definition_field.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/report_definition_field.tsx#:~:text=title), [use_filter_values.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/use_filter_values.ts#:~:text=title), [filter_value_btn.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/filter_value_btn.tsx#:~:text=title) | - | | | [use_discover_link.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/components/shared/exploratory_view/hooks/use_discover_link.tsx#:~:text=indexPatternId) | - | | | [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/application/index.tsx#:~:text=RedirectAppLinks), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/application/index.tsx#:~:text=RedirectAppLinks), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/observability/public/application/index.tsx#:~:text=RedirectAppLinks) | - | @@ -539,6 +622,9 @@ so TS and code-reference navigation might not highlight them. | | Deprecated API | Reference location(s) | Remove By | | ---------------|-----------|-----------| +| | [data_views.ts](https://github.com/elastic/kibana/tree/main/src/plugins/presentation_util/public/services/storybook/data_views.ts#:~:text=title), [data_views.ts](https://github.com/elastic/kibana/tree/main/src/plugins/presentation_util/public/services/storybook/data_views.ts#:~:text=title) | - | +| | [data_views.ts](https://github.com/elastic/kibana/tree/main/src/plugins/presentation_util/public/services/storybook/data_views.ts#:~:text=title), [data_views.ts](https://github.com/elastic/kibana/tree/main/src/plugins/presentation_util/public/services/storybook/data_views.ts#:~:text=title) | - | +| | [data_views.ts](https://github.com/elastic/kibana/tree/main/src/plugins/presentation_util/public/services/storybook/data_views.ts#:~:text=title) | - | | | [saved_object_save_modal_dashboard.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/presentation_util/public/components/saved_object_save_modal_dashboard.tsx#:~:text=SavedObjectSaveModal), [saved_object_save_modal_dashboard.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/presentation_util/public/components/saved_object_save_modal_dashboard.tsx#:~:text=SavedObjectSaveModal) | 8.8.0 | @@ -551,6 +637,16 @@ so TS and code-reference navigation might not highlight them. | +## reporting + +| Deprecated API | Reference location(s) | Remove By | +| ---------------|-----------|-----------| +| | [generate_csv.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/reporting/server/export_types/csv_searchsource/generate_csv/generate_csv.ts#:~:text=title), [generate_csv.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/reporting/server/export_types/csv_searchsource/generate_csv/generate_csv.ts#:~:text=title) | - | +| | [generate_csv.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/reporting/server/export_types/csv_searchsource/generate_csv/generate_csv.ts#:~:text=title), [generate_csv.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/reporting/server/export_types/csv_searchsource/generate_csv/generate_csv.ts#:~:text=title) | - | +| | [generate_csv.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/reporting/server/export_types/csv_searchsource/generate_csv/generate_csv.ts#:~:text=title) | - | + + + ## rollup | Deprecated API | Reference location(s) | Remove By | @@ -573,6 +669,9 @@ so TS and code-reference navigation might not highlight them. | | Deprecated API | Reference location(s) | Remove By | | ---------------|-----------|-----------| +| | [flyout.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx#:~:text=title), [flyout.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx#:~:text=title), [flyout.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx#:~:text=title), [flyout.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx#:~:text=title) | - | +| | [flyout.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx#:~:text=title), [flyout.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx#:~:text=title), [flyout.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx#:~:text=title), [flyout.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx#:~:text=title) | - | +| | [flyout.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx#:~:text=title), [flyout.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx#:~:text=title) | - | | | [saved_objects_edition_page.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/saved_objects_management/public/management_section/saved_objects_edition_page.tsx#:~:text=RedirectAppLinks), [saved_objects_edition_page.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/saved_objects_management/public/management_section/saved_objects_edition_page.tsx#:~:text=RedirectAppLinks), [saved_objects_edition_page.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/saved_objects_management/public/management_section/saved_objects_edition_page.tsx#:~:text=RedirectAppLinks), [saved_objects_table.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx#:~:text=RedirectAppLinks), [saved_objects_table.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx#:~:text=RedirectAppLinks), [saved_objects_table.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx#:~:text=RedirectAppLinks) | - | | | [resolve_import_errors.ts](https://github.com/elastic/kibana/tree/main/src/plugins/saved_objects_management/public/lib/resolve_import_errors.ts#:~:text=createNewCopy) | - | | | [resolve_import_errors.ts](https://github.com/elastic/kibana/tree/main/src/plugins/saved_objects_management/public/lib/resolve_import_errors.ts#:~:text=createNewCopy) | - | @@ -628,7 +727,7 @@ migrates to using the Kibana Privilege model: https://github.com/elastic/kibana/ This is relied on by the reporting feature, and should be removed once reporting migrates to using the Kibana Privilege model: https://github.com/elastic/kibana/issues/19914 | -| | [app_authorization.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security/server/authorization/app_authorization.ts#:~:text=getKibanaFeatures), [privileges.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security/server/authorization/privileges/privileges.ts#:~:text=getKibanaFeatures), [authorization_service.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security/server/authorization/authorization_service.tsx#:~:text=getKibanaFeatures), [app_authorization.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security/server/authorization/app_authorization.test.ts#:~:text=getKibanaFeatures), [privileges.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security/server/authorization/privileges/privileges.test.ts#:~:text=getKibanaFeatures), [privileges.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security/server/authorization/privileges/privileges.test.ts#:~:text=getKibanaFeatures), [privileges.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security/server/authorization/privileges/privileges.test.ts#:~:text=getKibanaFeatures), [privileges.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security/server/authorization/privileges/privileges.test.ts#:~:text=getKibanaFeatures), [privileges.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security/server/authorization/privileges/privileges.test.ts#:~:text=getKibanaFeatures), [privileges.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security/server/authorization/privileges/privileges.test.ts#:~:text=getKibanaFeatures)+ 14 more | 8.8.0 | +| | [app_authorization.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security/server/authorization/app_authorization.ts#:~:text=getKibanaFeatures), [privileges.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security/server/authorization/privileges/privileges.ts#:~:text=getKibanaFeatures), [authorization_service.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security/server/authorization/authorization_service.tsx#:~:text=getKibanaFeatures), [app_authorization.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security/server/authorization/app_authorization.test.ts#:~:text=getKibanaFeatures), [privileges.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security/server/authorization/privileges/privileges.test.ts#:~:text=getKibanaFeatures), [privileges.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security/server/authorization/privileges/privileges.test.ts#:~:text=getKibanaFeatures), [privileges.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security/server/authorization/privileges/privileges.test.ts#:~:text=getKibanaFeatures), [privileges.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security/server/authorization/privileges/privileges.test.ts#:~:text=getKibanaFeatures), [privileges.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security/server/authorization/privileges/privileges.test.ts#:~:text=getKibanaFeatures), [privileges.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security/server/authorization/privileges/privileges.test.ts#:~:text=getKibanaFeatures)+ 15 more | 8.8.0 | | | [authorization_service.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security/server/authorization/authorization_service.tsx#:~:text=getElasticsearchFeatures) | 8.8.0 | | | [license_service.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security/common/licensing/license_service.test.ts#:~:text=mode), [license_service.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security/common/licensing/license_service.test.ts#:~:text=mode), [license_service.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security/common/licensing/license_service.test.ts#:~:text=mode) | 8.8.0 | | | [plugin.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security/public/plugin.tsx#:~:text=license%24) | 8.8.0 | @@ -646,9 +745,12 @@ migrates to using the Kibana Privilege model: https://github.com/elastic/kibana/ | | [wrap_search_source_client.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/utils/wrap_search_source_client.ts#:~:text=create) | - | | | [wrap_search_source_client.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/utils/wrap_search_source_client.test.ts#:~:text=fetch), [wrap_search_source_client.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/utils/wrap_search_source_client.test.ts#:~:text=fetch), [wrap_search_source_client.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/utils/wrap_search_source_client.test.ts#:~:text=fetch), [wrap_search_source_client.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/utils/wrap_search_source_client.test.ts#:~:text=fetch) | - | | | [middleware.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts#:~:text=indexPatterns), [dependencies_start_mock.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/mock/endpoint/dependencies_start_mock.ts#:~:text=indexPatterns) | - | +| | [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 | - | | | [wrap_search_source_client.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/utils/wrap_search_source_client.ts#:~:text=create) | - | | | [wrap_search_source_client.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/utils/wrap_search_source_client.test.ts#:~:text=fetch), [wrap_search_source_client.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/utils/wrap_search_source_client.test.ts#:~:text=fetch), [wrap_search_source_client.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/utils/wrap_search_source_client.test.ts#:~:text=fetch), [wrap_search_source_client.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/utils/wrap_search_source_client.test.ts#:~:text=fetch) | - | | | [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 | | | [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 | @@ -688,7 +790,10 @@ migrates to using the Kibana Privilege model: https://github.com/elastic/kibana/ | | [fetch_search_source_query.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/stack_alerts/server/alert_types/es_query/lib/fetch_search_source_query.ts#:~:text=fetch), [rule_type.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/stack_alerts/server/alert_types/es_query/rule_type.test.ts#:~:text=fetch), [rule_type.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/stack_alerts/server/alert_types/es_query/rule_type.test.ts#:~:text=fetch) | - | | | [boundary_index_expression.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/expressions/boundary_index_expression.tsx#:~:text=indexPatterns), [entity_index_expression.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/expressions/entity_index_expression.tsx#:~:text=indexPatterns), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/index.tsx#:~:text=indexPatterns), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/index.tsx#:~:text=indexPatterns), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/index.tsx#:~:text=indexPatterns) | - | | | [expression.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/stack_alerts/public/alert_types/threshold/expression.tsx#:~:text=fieldFormats) | - | +| | [boundary_index_expression.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/expressions/boundary_index_expression.tsx#:~:text=title), [entity_index_expression.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/expressions/entity_index_expression.tsx#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/index.tsx#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/index.tsx#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/index.tsx#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/index.tsx#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/index.tsx#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/index.tsx#:~:text=title), [search_source_expression_form.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/stack_alerts/public/alert_types/es_query/expression/search_source_expression_form.tsx#:~:text=title), [boundary_index_expression.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/expressions/boundary_index_expression.tsx#:~:text=title)+ 8 more | - | | | [fetch_search_source_query.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/stack_alerts/server/alert_types/es_query/lib/fetch_search_source_query.ts#:~:text=fetch), [rule_type.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/stack_alerts/server/alert_types/es_query/rule_type.test.ts#:~:text=fetch), [rule_type.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/stack_alerts/server/alert_types/es_query/rule_type.test.ts#:~:text=fetch) | - | +| | [boundary_index_expression.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/expressions/boundary_index_expression.tsx#:~:text=title), [entity_index_expression.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/expressions/entity_index_expression.tsx#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/index.tsx#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/index.tsx#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/index.tsx#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/index.tsx#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/index.tsx#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/index.tsx#:~:text=title), [search_source_expression_form.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/stack_alerts/public/alert_types/es_query/expression/search_source_expression_form.tsx#:~:text=title), [boundary_index_expression.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/expressions/boundary_index_expression.tsx#:~:text=title)+ 8 more | - | +| | [boundary_index_expression.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/expressions/boundary_index_expression.tsx#:~:text=title), [entity_index_expression.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/expressions/entity_index_expression.tsx#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/index.tsx#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/index.tsx#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/index.tsx#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/index.tsx#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/index.tsx#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/stack_alerts/public/alert_types/geo_containment/query_builder/index.tsx#:~:text=title), [search_source_expression_form.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/stack_alerts/public/alert_types/es_query/expression/search_source_expression_form.tsx#:~:text=title) | - | @@ -696,6 +801,9 @@ migrates to using the Kibana Privilege model: https://github.com/elastic/kibana/ | Deprecated API | Reference location(s) | Remove By | | ---------------|-----------|-----------| +| | [filter_group.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/components/overview/filter_group/filter_group.tsx#:~:text=title), [filters_expression_select.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/components/overview/alerts/monitor_expressions/filters_expression_select.tsx#:~:text=title), [filter_group.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/components/overview/filter_group/filter_group.tsx#:~:text=title), [filters_expression_select.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/components/overview/alerts/monitor_expressions/filters_expression_select.tsx#:~:text=title) | - | +| | [filter_group.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/components/overview/filter_group/filter_group.tsx#:~:text=title), [filters_expression_select.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/components/overview/alerts/monitor_expressions/filters_expression_select.tsx#:~:text=title), [filter_group.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/components/overview/filter_group/filter_group.tsx#:~:text=title), [filters_expression_select.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/components/overview/alerts/monitor_expressions/filters_expression_select.tsx#:~:text=title) | - | +| | [filter_group.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/components/overview/filter_group/filter_group.tsx#:~:text=title), [filters_expression_select.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/components/overview/alerts/monitor_expressions/filters_expression_select.tsx#:~:text=title) | - | | | [stderr_logs.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/components/synthetics/check_steps/stderr_logs.tsx#:~:text=indexPatternId) | - | | | [alert_messages.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/lib/alert_types/alert_messages.tsx#:~:text=RedirectAppLinks), [alert_messages.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/lib/alert_types/alert_messages.tsx#:~:text=RedirectAppLinks), [alert_messages.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/lib/alert_types/alert_messages.tsx#:~:text=RedirectAppLinks), [uptime_app.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/app/uptime_app.tsx#:~:text=RedirectAppLinks), [uptime_app.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/app/uptime_app.tsx#:~:text=RedirectAppLinks), [uptime_app.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/app/uptime_app.tsx#:~:text=RedirectAppLinks), [synthetics_app.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/apps/synthetics/synthetics_app.tsx#:~:text=RedirectAppLinks), [synthetics_app.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/apps/synthetics/synthetics_app.tsx#:~:text=RedirectAppLinks), [synthetics_app.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/apps/synthetics/synthetics_app.tsx#:~:text=RedirectAppLinks) | - | @@ -710,19 +818,65 @@ migrates to using the Kibana Privilege model: https://github.com/elastic/kibana/ +## threatIntelligence + +| Deprecated API | Reference location(s) | Remove By | +| ---------------|-----------|-----------| +| | [mock_security_context.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/threat_intelligence/public/common/mocks/mock_security_context.tsx#:~:text=title), [mock_security_context.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/threat_intelligence/public/common/mocks/mock_security_context.tsx#:~:text=title) | - | +| | [mock_security_context.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/threat_intelligence/public/common/mocks/mock_security_context.tsx#:~:text=title), [mock_security_context.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/threat_intelligence/public/common/mocks/mock_security_context.tsx#:~:text=title) | - | +| | [mock_security_context.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/threat_intelligence/public/common/mocks/mock_security_context.tsx#:~:text=title) | - | + + + +## timelines + +| Deprecated API | Reference location(s) | Remove By | +| ---------------|-----------|-----------| +| | [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/timelines/public/container/source/index.tsx#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/timelines/public/container/source/index.tsx#:~:text=title), [index_pattern.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/timelines/public/mock/index_pattern.ts#:~:text=title), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/timelines/server/search_strategy/index_fields/index.ts#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/timelines/public/container/source/index.tsx#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/timelines/public/container/source/index.tsx#:~:text=title), [index_pattern.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/timelines/public/mock/index_pattern.ts#:~:text=title), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/timelines/server/search_strategy/index_fields/index.ts#:~:text=title) | - | +| | [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/timelines/public/container/source/index.tsx#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/timelines/public/container/source/index.tsx#:~:text=title), [index_pattern.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/timelines/public/mock/index_pattern.ts#:~:text=title), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/timelines/server/search_strategy/index_fields/index.ts#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/timelines/public/container/source/index.tsx#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/timelines/public/container/source/index.tsx#:~:text=title), [index_pattern.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/timelines/public/mock/index_pattern.ts#:~:text=title), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/timelines/server/search_strategy/index_fields/index.ts#:~:text=title) | - | +| | [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/timelines/public/container/source/index.tsx#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/timelines/public/container/source/index.tsx#:~:text=title), [index_pattern.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/timelines/public/mock/index_pattern.ts#:~:text=title), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/timelines/server/search_strategy/index_fields/index.ts#:~:text=title) | - | + + + ## transform | Deprecated API | Reference location(s) | Remove By | | ---------------|-----------|-----------| +| | [step_details_form.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/sections/create_transform/components/step_details/step_details_form.tsx#:~:text=title), [wizard.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/sections/create_transform/components/wizard/wizard.tsx#:~:text=title), [filter_term_form.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/filter_agg/components/filter_term_form.tsx#:~:text=title), [use_index_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/hooks/use_index_data.ts#:~:text=title), [use_index_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/hooks/use_index_data.ts#:~:text=title), [use_index_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/hooks/use_index_data.ts#:~:text=title), [use_index_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/hooks/use_index_data.ts#:~:text=title), [use_index_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/hooks/use_index_data.ts#:~:text=title), [use_index_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/hooks/use_index_data.ts#:~:text=title), [use_index_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/hooks/use_index_data.ts#:~:text=title)+ 36 more | - | +| | [step_details_form.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/sections/create_transform/components/step_details/step_details_form.tsx#:~:text=title), [wizard.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/sections/create_transform/components/wizard/wizard.tsx#:~:text=title), [filter_term_form.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/filter_agg/components/filter_term_form.tsx#:~:text=title), [use_index_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/hooks/use_index_data.ts#:~:text=title), [use_index_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/hooks/use_index_data.ts#:~:text=title), [use_index_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/hooks/use_index_data.ts#:~:text=title), [use_index_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/hooks/use_index_data.ts#:~:text=title), [use_index_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/hooks/use_index_data.ts#:~:text=title), [use_index_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/hooks/use_index_data.ts#:~:text=title), [use_index_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/hooks/use_index_data.ts#:~:text=title)+ 36 more | - | +| | [step_details_form.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/sections/create_transform/components/step_details/step_details_form.tsx#:~:text=title), [wizard.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/sections/create_transform/components/wizard/wizard.tsx#:~:text=title), [filter_term_form.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/filter_agg/components/filter_term_form.tsx#:~:text=title), [use_index_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/hooks/use_index_data.ts#:~:text=title), [use_index_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/hooks/use_index_data.ts#:~:text=title), [use_index_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/hooks/use_index_data.ts#:~:text=title), [use_index_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/hooks/use_index_data.ts#:~:text=title), [use_index_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/hooks/use_index_data.ts#:~:text=title), [use_index_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/hooks/use_index_data.ts#:~:text=title), [use_index_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/public/app/hooks/use_index_data.ts#:~:text=title)+ 13 more | - | | | [license.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/transform/server/services/license.ts#:~:text=license%24) | 8.8.0 | +## triggersActionsUi + +| Deprecated API | Reference location(s) | Remove By | +| ---------------|-----------|-----------| +| | [data_apis.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/triggers_actions_ui/public/common/lib/data_apis.ts#:~:text=title), [data_apis.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/triggers_actions_ui/public/common/lib/data_apis.ts#:~:text=title) | - | +| | [data_apis.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/triggers_actions_ui/public/common/lib/data_apis.ts#:~:text=title), [data_apis.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/triggers_actions_ui/public/common/lib/data_apis.ts#:~:text=title) | - | +| | [data_apis.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/triggers_actions_ui/public/common/lib/data_apis.ts#:~:text=title) | - | + + + +## unifiedFieldList + +| Deprecated API | Reference location(s) | Remove By | +| ---------------|-----------|-----------| +| | [load_field_stats.ts](https://github.com/elastic/kibana/tree/main/src/plugins/unified_field_list/public/services/field_stats/load_field_stats.ts#:~:text=title), [field_existing_utils.ts](https://github.com/elastic/kibana/tree/main/src/plugins/unified_field_list/common/utils/field_existing_utils.ts#:~:text=title), [field_existing_utils.ts](https://github.com/elastic/kibana/tree/main/src/plugins/unified_field_list/common/utils/field_existing_utils.ts#:~:text=title), [field_existing_utils.ts](https://github.com/elastic/kibana/tree/main/src/plugins/unified_field_list/common/utils/field_existing_utils.ts#:~:text=title), [field_stats.ts](https://github.com/elastic/kibana/tree/main/src/plugins/unified_field_list/server/routes/field_stats.ts#:~:text=title), [field_stats.ts](https://github.com/elastic/kibana/tree/main/src/plugins/unified_field_list/server/routes/field_stats.ts#:~:text=title), [load_field_stats.ts](https://github.com/elastic/kibana/tree/main/src/plugins/unified_field_list/public/services/field_stats/load_field_stats.ts#:~:text=title), [field_existing_utils.ts](https://github.com/elastic/kibana/tree/main/src/plugins/unified_field_list/common/utils/field_existing_utils.ts#:~:text=title), [field_existing_utils.ts](https://github.com/elastic/kibana/tree/main/src/plugins/unified_field_list/common/utils/field_existing_utils.ts#:~:text=title), [field_existing_utils.ts](https://github.com/elastic/kibana/tree/main/src/plugins/unified_field_list/common/utils/field_existing_utils.ts#:~:text=title)+ 2 more | - | +| | [load_field_stats.ts](https://github.com/elastic/kibana/tree/main/src/plugins/unified_field_list/public/services/field_stats/load_field_stats.ts#:~:text=title), [field_existing_utils.ts](https://github.com/elastic/kibana/tree/main/src/plugins/unified_field_list/common/utils/field_existing_utils.ts#:~:text=title), [field_existing_utils.ts](https://github.com/elastic/kibana/tree/main/src/plugins/unified_field_list/common/utils/field_existing_utils.ts#:~:text=title), [field_existing_utils.ts](https://github.com/elastic/kibana/tree/main/src/plugins/unified_field_list/common/utils/field_existing_utils.ts#:~:text=title), [field_stats.ts](https://github.com/elastic/kibana/tree/main/src/plugins/unified_field_list/server/routes/field_stats.ts#:~:text=title), [field_stats.ts](https://github.com/elastic/kibana/tree/main/src/plugins/unified_field_list/server/routes/field_stats.ts#:~:text=title), [load_field_stats.ts](https://github.com/elastic/kibana/tree/main/src/plugins/unified_field_list/public/services/field_stats/load_field_stats.ts#:~:text=title), [field_existing_utils.ts](https://github.com/elastic/kibana/tree/main/src/plugins/unified_field_list/common/utils/field_existing_utils.ts#:~:text=title), [field_existing_utils.ts](https://github.com/elastic/kibana/tree/main/src/plugins/unified_field_list/common/utils/field_existing_utils.ts#:~:text=title), [field_existing_utils.ts](https://github.com/elastic/kibana/tree/main/src/plugins/unified_field_list/common/utils/field_existing_utils.ts#:~:text=title)+ 2 more | - | +| | [load_field_stats.ts](https://github.com/elastic/kibana/tree/main/src/plugins/unified_field_list/public/services/field_stats/load_field_stats.ts#:~:text=title), [field_existing_utils.ts](https://github.com/elastic/kibana/tree/main/src/plugins/unified_field_list/common/utils/field_existing_utils.ts#:~:text=title), [field_existing_utils.ts](https://github.com/elastic/kibana/tree/main/src/plugins/unified_field_list/common/utils/field_existing_utils.ts#:~:text=title), [field_existing_utils.ts](https://github.com/elastic/kibana/tree/main/src/plugins/unified_field_list/common/utils/field_existing_utils.ts#:~:text=title), [field_stats.ts](https://github.com/elastic/kibana/tree/main/src/plugins/unified_field_list/server/routes/field_stats.ts#:~:text=title), [field_stats.ts](https://github.com/elastic/kibana/tree/main/src/plugins/unified_field_list/server/routes/field_stats.ts#:~:text=title) | - | + + + ## unifiedSearch | Deprecated API | Reference location(s) | Remove By | | ---------------|-----------|-----------| | | [query_string_input.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/unified_search/public/query_string_input/query_string_input.tsx#:~:text=indexPatterns) | - | +| | [value_suggestion_provider.ts](https://github.com/elastic/kibana/tree/main/src/plugins/unified_search/public/autocomplete/providers/value_suggestion_provider.ts#:~:text=title), [fetch_index_patterns.ts](https://github.com/elastic/kibana/tree/main/src/plugins/unified_search/public/query_string_input/fetch_index_patterns.ts#:~:text=title), [change_dataview.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/unified_search/public/dataview_picker/change_dataview.tsx#:~:text=title), [value_suggestion_provider.ts](https://github.com/elastic/kibana/tree/main/src/plugins/unified_search/public/autocomplete/providers/value_suggestion_provider.ts#:~:text=title), [fetch_index_patterns.ts](https://github.com/elastic/kibana/tree/main/src/plugins/unified_search/public/query_string_input/fetch_index_patterns.ts#:~:text=title), [change_dataview.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/unified_search/public/dataview_picker/change_dataview.tsx#:~:text=title) | - | +| | [value_suggestion_provider.ts](https://github.com/elastic/kibana/tree/main/src/plugins/unified_search/public/autocomplete/providers/value_suggestion_provider.ts#:~:text=title), [fetch_index_patterns.ts](https://github.com/elastic/kibana/tree/main/src/plugins/unified_search/public/query_string_input/fetch_index_patterns.ts#:~:text=title), [change_dataview.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/unified_search/public/dataview_picker/change_dataview.tsx#:~:text=title), [value_suggestion_provider.ts](https://github.com/elastic/kibana/tree/main/src/plugins/unified_search/public/autocomplete/providers/value_suggestion_provider.ts#:~:text=title), [fetch_index_patterns.ts](https://github.com/elastic/kibana/tree/main/src/plugins/unified_search/public/query_string_input/fetch_index_patterns.ts#:~:text=title), [change_dataview.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/unified_search/public/dataview_picker/change_dataview.tsx#:~:text=title) | - | +| | [value_suggestion_provider.ts](https://github.com/elastic/kibana/tree/main/src/plugins/unified_search/public/autocomplete/providers/value_suggestion_provider.ts#:~:text=title), [fetch_index_patterns.ts](https://github.com/elastic/kibana/tree/main/src/plugins/unified_search/public/query_string_input/fetch_index_patterns.ts#:~:text=title), [change_dataview.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/unified_search/public/dataview_picker/change_dataview.tsx#:~:text=title) | - | | | [terms_enum.ts](https://github.com/elastic/kibana/tree/main/src/plugins/unified_search/server/autocomplete/terms_enum.ts#:~:text=getFieldByName), [terms_enum.ts](https://github.com/elastic/kibana/tree/main/src/plugins/unified_search/server/autocomplete/terms_enum.ts#:~:text=getFieldByName), [terms_agg.ts](https://github.com/elastic/kibana/tree/main/src/plugins/unified_search/server/autocomplete/terms_agg.ts#:~:text=getFieldByName), [terms_agg.ts](https://github.com/elastic/kibana/tree/main/src/plugins/unified_search/server/autocomplete/terms_agg.ts#:~:text=getFieldByName) | - | | | [terms_enum.ts](https://github.com/elastic/kibana/tree/main/src/plugins/unified_search/server/autocomplete/terms_enum.ts#:~:text=findIndexPatternById), [terms_enum.ts](https://github.com/elastic/kibana/tree/main/src/plugins/unified_search/server/autocomplete/terms_enum.ts#:~:text=findIndexPatternById), [terms_agg.ts](https://github.com/elastic/kibana/tree/main/src/plugins/unified_search/server/autocomplete/terms_agg.ts#:~:text=findIndexPatternById), [terms_agg.ts](https://github.com/elastic/kibana/tree/main/src/plugins/unified_search/server/autocomplete/terms_agg.ts#:~:text=findIndexPatternById) | - | @@ -732,6 +886,9 @@ migrates to using the Kibana Privilege model: https://github.com/elastic/kibana/ | Deprecated API | Reference location(s) | Remove By | | ---------------|-----------|-----------| +| | [external_links.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecation_logs/fix_deprecation_logs/external_links.tsx#:~:text=title), [external_links.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecation_logs/fix_deprecation_logs/external_links.tsx#:~:text=title) | - | +| | [external_links.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecation_logs/fix_deprecation_logs/external_links.tsx#:~:text=title), [external_links.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecation_logs/fix_deprecation_logs/external_links.tsx#:~:text=title) | - | +| | [external_links.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecation_logs/fix_deprecation_logs/external_links.tsx#:~:text=title) | - | | | [shared_imports.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/upgrade_assistant/public/shared_imports.ts#:~:text=RedirectAppLinks), [app.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/upgrade_assistant/public/application/app.tsx#:~:text=RedirectAppLinks), [app.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/upgrade_assistant/public/application/app.tsx#:~:text=RedirectAppLinks), [app.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/upgrade_assistant/public/application/app.tsx#:~:text=RedirectAppLinks) | - | | | [reindex_service.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.ts#:~:text=license%24), [reindex_service.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.test.ts#:~:text=license%24), [reindex_service.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.test.ts#:~:text=license%24) | 8.8.0 | @@ -741,10 +898,23 @@ migrates to using the Kibana Privilege model: https://github.com/elastic/kibana/ | Deprecated API | Reference location(s) | Remove By | | ---------------|-----------|-----------| +| | [use_data_view.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ux/public/components/app/rum_dashboard/local_uifilters/use_data_view.ts#:~:text=title), [use_data_view.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ux/public/components/app/rum_dashboard/local_uifilters/use_data_view.ts#:~:text=title) | - | +| | [use_data_view.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ux/public/components/app/rum_dashboard/local_uifilters/use_data_view.ts#:~:text=title), [use_data_view.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ux/public/components/app/rum_dashboard/local_uifilters/use_data_view.ts#:~:text=title) | - | +| | [use_data_view.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ux/public/components/app/rum_dashboard/local_uifilters/use_data_view.ts#:~:text=title) | - | | | [ux_app.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ux/public/application/ux_app.tsx#:~:text=RedirectAppLinks), [ux_app.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ux/public/application/ux_app.tsx#:~:text=RedirectAppLinks), [ux_app.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/ux/public/application/ux_app.tsx#:~:text=RedirectAppLinks) | - | +## visDefaultEditor + +| Deprecated API | Reference location(s) | Remove By | +| ---------------|-----------|-----------| +| | [field.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/vis_default_editor/public/components/controls/field.tsx#:~:text=title), [field.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/vis_default_editor/public/components/controls/field.tsx#:~:text=title), [agg_select.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/vis_default_editor/public/components/agg_select.tsx#:~:text=title), [field.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/vis_default_editor/public/components/controls/field.tsx#:~:text=title), [field.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/vis_default_editor/public/components/controls/field.tsx#:~:text=title), [agg_select.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/vis_default_editor/public/components/agg_select.tsx#:~:text=title) | - | +| | [field.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/vis_default_editor/public/components/controls/field.tsx#:~:text=title), [field.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/vis_default_editor/public/components/controls/field.tsx#:~:text=title), [agg_select.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/vis_default_editor/public/components/agg_select.tsx#:~:text=title), [field.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/vis_default_editor/public/components/controls/field.tsx#:~:text=title), [field.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/vis_default_editor/public/components/controls/field.tsx#:~:text=title), [agg_select.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/vis_default_editor/public/components/agg_select.tsx#:~:text=title) | - | +| | [field.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/vis_default_editor/public/components/controls/field.tsx#:~:text=title), [field.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/vis_default_editor/public/components/controls/field.tsx#:~:text=title), [agg_select.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/vis_default_editor/public/components/agg_select.tsx#:~:text=title) | - | + + + ## visTypeGauge | Deprecated API | Reference location(s) | Remove By | @@ -762,16 +932,39 @@ migrates to using the Kibana Privilege model: https://github.com/elastic/kibana/ +## visTypeTimelion + +| Deprecated API | Reference location(s) | Remove By | +| ---------------|-----------|-----------| +| | [arg_value_suggestions.ts](https://github.com/elastic/kibana/tree/main/src/plugins/vis_types/timelion/public/helpers/arg_value_suggestions.ts#:~:text=title), [arg_value_suggestions.ts](https://github.com/elastic/kibana/tree/main/src/plugins/vis_types/timelion/public/helpers/arg_value_suggestions.ts#:~:text=title), [arg_value_suggestions.ts](https://github.com/elastic/kibana/tree/main/src/plugins/vis_types/timelion/public/helpers/arg_value_suggestions.ts#:~:text=title), [arg_value_suggestions.ts](https://github.com/elastic/kibana/tree/main/src/plugins/vis_types/timelion/public/helpers/arg_value_suggestions.ts#:~:text=title) | - | +| | [arg_value_suggestions.ts](https://github.com/elastic/kibana/tree/main/src/plugins/vis_types/timelion/public/helpers/arg_value_suggestions.ts#:~:text=title), [arg_value_suggestions.ts](https://github.com/elastic/kibana/tree/main/src/plugins/vis_types/timelion/public/helpers/arg_value_suggestions.ts#:~:text=title), [arg_value_suggestions.ts](https://github.com/elastic/kibana/tree/main/src/plugins/vis_types/timelion/public/helpers/arg_value_suggestions.ts#:~:text=title), [arg_value_suggestions.ts](https://github.com/elastic/kibana/tree/main/src/plugins/vis_types/timelion/public/helpers/arg_value_suggestions.ts#:~:text=title) | - | +| | [arg_value_suggestions.ts](https://github.com/elastic/kibana/tree/main/src/plugins/vis_types/timelion/public/helpers/arg_value_suggestions.ts#:~:text=title), [arg_value_suggestions.ts](https://github.com/elastic/kibana/tree/main/src/plugins/vis_types/timelion/public/helpers/arg_value_suggestions.ts#:~:text=title) | - | + + + ## visTypeTimeseries | Deprecated API | Reference location(s) | Remove By | | ---------------|-----------|-----------| +| | [index_patterns_utils.ts](https://github.com/elastic/kibana/tree/main/src/plugins/vis_types/timeseries/common/index_patterns_utils.ts#:~:text=title), [index_patterns_utils.ts](https://github.com/elastic/kibana/tree/main/src/plugins/vis_types/timeseries/common/index_patterns_utils.ts#:~:text=title), [get_fields.ts](https://github.com/elastic/kibana/tree/main/src/plugins/vis_types/timeseries/server/lib/get_fields.ts#:~:text=title), [index_patterns_utils.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/vis_types/timeseries/common/index_patterns_utils.test.ts#:~:text=title), [index_patterns_utils.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/vis_types/timeseries/common/index_patterns_utils.test.ts#:~:text=title), [convert_series_to_datatable.ts](https://github.com/elastic/kibana/tree/main/src/plugins/vis_types/timeseries/public/application/components/lib/convert_series_to_datatable.ts#:~:text=title), [convert_series_to_datatable.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/vis_types/timeseries/public/application/components/lib/convert_series_to_datatable.test.ts#:~:text=title), [get_datasource_info.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/vis_types/timeseries/public/convert_to_lens/lib/datasource/get_datasource_info.test.ts#:~:text=title), [get_datasource_info.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/vis_types/timeseries/public/convert_to_lens/lib/datasource/get_datasource_info.test.ts#:~:text=title), [get_datasource_info.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/vis_types/timeseries/public/convert_to_lens/lib/datasource/get_datasource_info.test.ts#:~:text=title)+ 14 more | - | | | [abstract_search_strategy.ts](https://github.com/elastic/kibana/tree/main/src/plugins/vis_types/timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts#:~:text=getNonScriptedFields), [fetch_fields.ts](https://github.com/elastic/kibana/tree/main/src/plugins/vis_types/timeseries/public/application/lib/fetch_fields.ts#:~:text=getNonScriptedFields), [abstract_search_strategy.ts](https://github.com/elastic/kibana/tree/main/src/plugins/vis_types/timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts#:~:text=getNonScriptedFields), [fetch_fields.ts](https://github.com/elastic/kibana/tree/main/src/plugins/vis_types/timeseries/public/application/lib/fetch_fields.ts#:~:text=getNonScriptedFields) | - | +| | [index_patterns_utils.ts](https://github.com/elastic/kibana/tree/main/src/plugins/vis_types/timeseries/common/index_patterns_utils.ts#:~:text=title), [index_patterns_utils.ts](https://github.com/elastic/kibana/tree/main/src/plugins/vis_types/timeseries/common/index_patterns_utils.ts#:~:text=title), [get_fields.ts](https://github.com/elastic/kibana/tree/main/src/plugins/vis_types/timeseries/server/lib/get_fields.ts#:~:text=title), [index_patterns_utils.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/vis_types/timeseries/common/index_patterns_utils.test.ts#:~:text=title), [index_patterns_utils.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/vis_types/timeseries/common/index_patterns_utils.test.ts#:~:text=title), [convert_series_to_datatable.ts](https://github.com/elastic/kibana/tree/main/src/plugins/vis_types/timeseries/public/application/components/lib/convert_series_to_datatable.ts#:~:text=title), [convert_series_to_datatable.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/vis_types/timeseries/public/application/components/lib/convert_series_to_datatable.test.ts#:~:text=title), [get_datasource_info.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/vis_types/timeseries/public/convert_to_lens/lib/datasource/get_datasource_info.test.ts#:~:text=title), [get_datasource_info.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/vis_types/timeseries/public/convert_to_lens/lib/datasource/get_datasource_info.test.ts#:~:text=title), [get_datasource_info.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/vis_types/timeseries/public/convert_to_lens/lib/datasource/get_datasource_info.test.ts#:~:text=title)+ 14 more | - | | | [abstract_search_strategy.ts](https://github.com/elastic/kibana/tree/main/src/plugins/vis_types/timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts#:~:text=getNonScriptedFields), [fetch_fields.ts](https://github.com/elastic/kibana/tree/main/src/plugins/vis_types/timeseries/public/application/lib/fetch_fields.ts#:~:text=getNonScriptedFields), [abstract_search_strategy.ts](https://github.com/elastic/kibana/tree/main/src/plugins/vis_types/timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts#:~:text=getNonScriptedFields), [fetch_fields.ts](https://github.com/elastic/kibana/tree/main/src/plugins/vis_types/timeseries/public/application/lib/fetch_fields.ts#:~:text=getNonScriptedFields) | - | +| | [index_patterns_utils.ts](https://github.com/elastic/kibana/tree/main/src/plugins/vis_types/timeseries/common/index_patterns_utils.ts#:~:text=title), [index_patterns_utils.ts](https://github.com/elastic/kibana/tree/main/src/plugins/vis_types/timeseries/common/index_patterns_utils.ts#:~:text=title), [get_fields.ts](https://github.com/elastic/kibana/tree/main/src/plugins/vis_types/timeseries/server/lib/get_fields.ts#:~:text=title), [index_patterns_utils.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/vis_types/timeseries/common/index_patterns_utils.test.ts#:~:text=title), [index_patterns_utils.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/vis_types/timeseries/common/index_patterns_utils.test.ts#:~:text=title), [convert_series_to_datatable.ts](https://github.com/elastic/kibana/tree/main/src/plugins/vis_types/timeseries/public/application/components/lib/convert_series_to_datatable.ts#:~:text=title), [convert_series_to_datatable.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/vis_types/timeseries/public/application/components/lib/convert_series_to_datatable.test.ts#:~:text=title), [get_datasource_info.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/vis_types/timeseries/public/convert_to_lens/lib/datasource/get_datasource_info.test.ts#:~:text=title), [get_datasource_info.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/vis_types/timeseries/public/convert_to_lens/lib/datasource/get_datasource_info.test.ts#:~:text=title), [get_datasource_info.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/vis_types/timeseries/public/convert_to_lens/lib/datasource/get_datasource_info.test.ts#:~:text=title)+ 2 more | - | | | [abstract_search_strategy.ts](https://github.com/elastic/kibana/tree/main/src/plugins/vis_types/timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts#:~:text=getNonScriptedFields), [fetch_fields.ts](https://github.com/elastic/kibana/tree/main/src/plugins/vis_types/timeseries/public/application/lib/fetch_fields.ts#:~:text=getNonScriptedFields) | - | +## visTypeVega + +| Deprecated API | Reference location(s) | Remove By | +| ---------------|-----------|-----------| +| | [search_api.ts](https://github.com/elastic/kibana/tree/main/src/plugins/vis_types/vega/public/data_model/search_api.ts#:~:text=title), [search_api.ts](https://github.com/elastic/kibana/tree/main/src/plugins/vis_types/vega/public/data_model/search_api.ts#:~:text=title) | - | +| | [search_api.ts](https://github.com/elastic/kibana/tree/main/src/plugins/vis_types/vega/public/data_model/search_api.ts#:~:text=title), [search_api.ts](https://github.com/elastic/kibana/tree/main/src/plugins/vis_types/vega/public/data_model/search_api.ts#:~:text=title) | - | +| | [search_api.ts](https://github.com/elastic/kibana/tree/main/src/plugins/vis_types/vega/public/data_model/search_api.ts#:~:text=title) | - | + + + ## visualizations | Deprecated API | Reference location(s) | Remove By | diff --git a/api_docs/deprecations_by_team.mdx b/api_docs/deprecations_by_team.mdx index 58604d901ae72..cb216706138de 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-10 +date: 2022-10-16 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -128,7 +128,7 @@ so TS and code-reference navigation might not highlight them. | | Plugin | Deprecated API | Reference location(s) | Remove By | | --------|-------|-----------|-----------| -| spaces | | [on_post_auth_interceptor.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/spaces/server/lib/request_interceptors/on_post_auth_interceptor.ts#:~:text=getKibanaFeatures), [spaces_usage_collector.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/spaces/server/usage_collection/spaces_usage_collector.ts#:~:text=getKibanaFeatures), [on_post_auth_interceptor.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/spaces/server/lib/request_interceptors/on_post_auth_interceptor.test.ts#:~:text=getKibanaFeatures), [app_authorization.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security/server/authorization/app_authorization.ts#:~:text=getKibanaFeatures), [privileges.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security/server/authorization/privileges/privileges.ts#:~:text=getKibanaFeatures), [authorization_service.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security/server/authorization/authorization_service.tsx#:~:text=getKibanaFeatures), [app_authorization.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security/server/authorization/app_authorization.test.ts#:~:text=getKibanaFeatures), [privileges.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security/server/authorization/privileges/privileges.test.ts#:~:text=getKibanaFeatures), [privileges.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security/server/authorization/privileges/privileges.test.ts#:~:text=getKibanaFeatures), [privileges.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security/server/authorization/privileges/privileges.test.ts#:~:text=getKibanaFeatures)+ 17 more | 8.8.0 | +| spaces | | [on_post_auth_interceptor.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/spaces/server/lib/request_interceptors/on_post_auth_interceptor.ts#:~:text=getKibanaFeatures), [spaces_usage_collector.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/spaces/server/usage_collection/spaces_usage_collector.ts#:~:text=getKibanaFeatures), [on_post_auth_interceptor.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/spaces/server/lib/request_interceptors/on_post_auth_interceptor.test.ts#:~:text=getKibanaFeatures), [app_authorization.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security/server/authorization/app_authorization.ts#:~:text=getKibanaFeatures), [privileges.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security/server/authorization/privileges/privileges.ts#:~:text=getKibanaFeatures), [authorization_service.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security/server/authorization/authorization_service.tsx#:~:text=getKibanaFeatures), [app_authorization.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security/server/authorization/app_authorization.test.ts#:~:text=getKibanaFeatures), [privileges.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security/server/authorization/privileges/privileges.test.ts#:~:text=getKibanaFeatures), [privileges.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security/server/authorization/privileges/privileges.test.ts#:~:text=getKibanaFeatures), [privileges.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security/server/authorization/privileges/privileges.test.ts#:~:text=getKibanaFeatures)+ 18 more | 8.8.0 | | spaces | | [spaces_usage_collector.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/spaces/server/usage_collection/spaces_usage_collector.ts#:~:text=license%24), [plugin.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/spaces/server/plugin.ts#:~:text=license%24), [plugin.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/spaces/server/plugin.ts#:~:text=license%24), [spaces_usage_collector.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/spaces/server/usage_collection/spaces_usage_collector.test.ts#:~:text=license%24), [plugin.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security/server/plugin.ts#:~:text=license%24) | 8.8.0 | | security | | [elasticsearch_role.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security/server/authorization/roles/elasticsearch_role.ts#:~:text=disabled), [role_utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security/server/lib/role_utils.ts#:~:text=disabled), [role_utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security/server/lib/role_utils.ts#:~:text=disabled), [primary_feature_privilege.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security/public/management/roles/model/primary_feature_privilege.ts#:~:text=disabled), [elasticsearch_role.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security/server/authorization/roles/elasticsearch_role.test.ts#:~:text=disabled), [kibana_features.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security/public/management/roles/__fixtures__/kibana_features.ts#:~:text=disabled), [put.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security/server/routes/authorization/roles/put.test.ts#:~:text=disabled), [put_payload.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security/server/routes/authorization/roles/model/put_payload.test.ts#:~:text=disabled) | 8.8.0 | | security | | [disable_ui_capabilities.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security/server/authorization/disable_ui_capabilities.ts#:~:text=requiredRoles) | 8.8.0 @@ -175,7 +175,7 @@ migrates to using the Kibana Privilege model: https://github.com/elastic/kibana/ | Plugin | Deprecated API | Reference location(s) | Remove By | | --------|-------|-----------|-----------| -| indexLifecycleManagement | | [license.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/index_lifecycle_management/server/services/license.ts#:~:text=license%24), [reindex_service.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.ts#:~:text=license%24), [reindex_service.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.test.ts#:~:text=license%24), [reindex_service.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.test.ts#:~:text=license%24), [license.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/painless_lab/server/services/license.ts#:~:text=license%24), [plugin.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/searchprofiler/server/plugin.ts#:~:text=license%24), [plugin.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/remote_clusters/server/plugin.ts#:~:text=license%24), [license.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/rollup/server/services/license.ts#:~:text=license%24), [license.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/snapshot_restore/server/services/license.ts#:~:text=license%24) | 8.8.0 | +| upgradeAssistant | | [reindex_service.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.ts#:~:text=license%24), [reindex_service.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.test.ts#:~:text=license%24), [reindex_service.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.test.ts#:~:text=license%24), [license.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/index_lifecycle_management/server/services/license.ts#:~:text=license%24), [license.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/painless_lab/server/services/license.ts#:~:text=license%24), [plugin.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/searchprofiler/server/plugin.ts#:~:text=license%24), [plugin.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/remote_clusters/server/plugin.ts#:~:text=license%24), [license.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/rollup/server/services/license.ts#:~:text=license%24), [license.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/snapshot_restore/server/services/license.ts#:~:text=license%24) | 8.8.0 | | licenseManagement | | [plugin.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/license_management/public/plugin.ts#:~:text=license%24), [plugin.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cross_cluster_replication/public/plugin.ts#:~:text=license%24), [plugin.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/painless_lab/public/plugin.tsx#:~:text=license%24), [plugin.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/painless_lab/public/plugin.tsx#:~:text=license%24), [plugin.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/searchprofiler/public/plugin.ts#:~:text=license%24), [plugin.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/searchprofiler/public/plugin.ts#:~:text=license%24), [plugin.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/watcher/public/plugin.ts#:~:text=license%24), [plugin.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/watcher/public/plugin.ts#:~:text=license%24) | 8.8.0 | @@ -192,5 +192,5 @@ migrates to using the Kibana Privilege model: https://github.com/elastic/kibana/ | Plugin | Deprecated API | Reference location(s) | Remove By | | --------|-------|-----------|-----------| -| management | | [application.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/management/public/application.tsx#:~:text=appBasePath) | 8.8.0 | -| visualizations | | [visualize_top_nav.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/visualizations/public/visualize_app/components/visualize_top_nav.tsx#:~:text=onAppLeave), [visualize_editor_common.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/visualizations/public/visualize_app/components/visualize_editor_common.tsx#:~:text=onAppLeave), [app.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/visualizations/public/visualize_app/app.tsx#:~:text=onAppLeave), [index.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/visualizations/public/visualize_app/index.tsx#:~:text=onAppLeave), [types.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/app_plugin/types.ts#:~:text=onAppLeave), [types.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/app_plugin/types.ts#:~:text=onAppLeave), [mounter.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/app_plugin/mounter.tsx#:~:text=onAppLeave) | 8.8.0 | \ No newline at end of file +| lens | | [types.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/app_plugin/types.ts#:~:text=onAppLeave), [types.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/app_plugin/types.ts#:~:text=onAppLeave), [mounter.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/lens/public/app_plugin/mounter.tsx#:~:text=onAppLeave), [visualize_top_nav.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/visualizations/public/visualize_app/components/visualize_top_nav.tsx#:~:text=onAppLeave), [visualize_editor_common.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/visualizations/public/visualize_app/components/visualize_editor_common.tsx#:~:text=onAppLeave), [app.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/visualizations/public/visualize_app/app.tsx#:~:text=onAppLeave), [index.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/visualizations/public/visualize_app/index.tsx#:~:text=onAppLeave) | 8.8.0 | +| management | | [application.tsx](https://github.com/elastic/kibana/tree/main/src/plugins/management/public/application.tsx#:~:text=appBasePath) | 8.8.0 | \ No newline at end of file diff --git a/api_docs/dev_tools.mdx b/api_docs/dev_tools.mdx index 1f599397cba74..7ed7748675577 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-10 +date: 2022-10-16 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 f0b145b742a48..b5145c14eacff 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-10 +date: 2022-10-16 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 33551d38d8eb7..64250ab9bfdfc 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-10 +date: 2022-10-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'discoverEnhanced'] --- import discoverEnhancedObj from './discover_enhanced.devdocs.json'; diff --git a/api_docs/embeddable.mdx b/api_docs/embeddable.mdx index ac8234957b13f..72511854c6052 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-10 +date: 2022-10-16 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 00b3b6c9f3008..62bfb673d04a0 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-10 +date: 2022-10-16 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 f9dc0ebec4adb..f8f40859433d3 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-10 +date: 2022-10-16 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 2aef259660758..018530094c76e 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-10 +date: 2022-10-16 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 4283b8368b2ea..9630e92d38a7a 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-10 +date: 2022-10-16 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 ff64843fa7edc..80382ccbeaa3a 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-10 +date: 2022-10-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'eventAnnotation'] --- import eventAnnotationObj from './event_annotation.devdocs.json'; diff --git a/api_docs/event_log.devdocs.json b/api_docs/event_log.devdocs.json index b4c0370096cc2..697461ca39d3c 100644 --- a/api_docs/event_log.devdocs.json +++ b/api_docs/event_log.devdocs.json @@ -1312,7 +1312,7 @@ "label": "data", "description": [], "signature": [ - "(Readonly<{ error?: Readonly<{ type?: string | undefined; id?: string | undefined; message?: string | undefined; code?: string | undefined; stack_trace?: string | undefined; } & {}> | undefined; tags?: string[] | undefined; log?: Readonly<{ logger?: string | undefined; level?: string | undefined; } & {}> | undefined; user?: Readonly<{ name?: string | undefined; } & {}> | undefined; message?: string | undefined; kibana?: Readonly<{ alert?: Readonly<{ rule?: Readonly<{ consumer?: string | undefined; execution?: Readonly<{ status?: string | undefined; metrics?: Readonly<{ number_of_triggered_actions?: string | number | undefined; number_of_generated_actions?: string | number | undefined; alert_counts?: Readonly<{ active?: string | number | undefined; recovered?: string | number | undefined; new?: string | number | undefined; } & {}> | undefined; number_of_searches?: string | number | undefined; total_indexing_duration_ms?: string | number | undefined; es_search_duration_ms?: string | number | undefined; total_search_duration_ms?: string | number | undefined; execution_gap_duration_s?: string | number | undefined; rule_type_run_duration_ms?: string | number | undefined; process_alerts_duration_ms?: string | number | undefined; trigger_actions_duration_ms?: string | number | undefined; process_rule_duration_ms?: string | number | undefined; claim_to_start_duration_ms?: string | number | undefined; prepare_rule_duration_ms?: string | number | undefined; total_run_duration_ms?: string | number | undefined; total_enrichment_duration_ms?: string | number | undefined; } & {}> | undefined; uuid?: string | undefined; status_order?: string | number | undefined; } & {}> | undefined; rule_type_id?: string | undefined; } & {}> | undefined; } & {}> | undefined; version?: string | undefined; alerting?: Readonly<{ status?: string | undefined; instance_id?: string | undefined; action_group_id?: string | undefined; action_subgroup?: string | undefined; } & {}> | undefined; server_uuid?: string | undefined; task?: Readonly<{ id?: string | undefined; schedule_delay?: string | number | undefined; scheduled?: string | undefined; } & {}> | undefined; saved_objects?: Readonly<{ type?: string | undefined; id?: string | undefined; namespace?: string | undefined; rel?: string | undefined; type_id?: string | undefined; } & {}>[] | undefined; space_ids?: string[] | undefined; } & {}> | undefined; ecs?: Readonly<{ version?: string | undefined; } & {}> | undefined; rule?: Readonly<{ name?: string | undefined; description?: string | undefined; category?: string | undefined; id?: string | undefined; version?: string | undefined; license?: string | undefined; reference?: string | undefined; author?: string[] | undefined; ruleset?: string | undefined; uuid?: string | undefined; } & {}> | undefined; event?: Readonly<{ start?: string | undefined; category?: string[] | undefined; type?: string[] | undefined; id?: string | undefined; created?: string | undefined; outcome?: string | undefined; end?: string | undefined; original?: string | undefined; duration?: string | number | undefined; code?: string | undefined; url?: string | undefined; action?: string | undefined; kind?: string | undefined; hash?: string | undefined; severity?: string | number | undefined; dataset?: string | undefined; ingested?: string | undefined; module?: string | undefined; provider?: string | undefined; reason?: string | undefined; reference?: string | undefined; risk_score?: number | undefined; risk_score_norm?: number | undefined; sequence?: string | number | undefined; timezone?: string | undefined; } & {}> | undefined; '@timestamp'?: string | undefined; } & {}> | undefined)[]" + "(Readonly<{ error?: Readonly<{ type?: string | undefined; id?: string | undefined; message?: string | undefined; code?: string | undefined; stack_trace?: string | undefined; } & {}> | undefined; tags?: string[] | undefined; log?: Readonly<{ logger?: string | undefined; level?: string | undefined; } & {}> | undefined; user?: Readonly<{ name?: string | undefined; } & {}> | undefined; message?: string | undefined; kibana?: Readonly<{ alert?: Readonly<{ rule?: Readonly<{ consumer?: string | undefined; execution?: Readonly<{ status?: string | undefined; metrics?: Readonly<{ number_of_triggered_actions?: string | number | undefined; number_of_generated_actions?: string | number | undefined; alert_counts?: Readonly<{ active?: string | number | undefined; recovered?: string | number | undefined; new?: string | number | undefined; } & {}> | undefined; number_of_searches?: string | number | undefined; total_indexing_duration_ms?: string | number | undefined; es_search_duration_ms?: string | number | undefined; total_search_duration_ms?: string | number | undefined; execution_gap_duration_s?: string | number | undefined; rule_type_run_duration_ms?: string | number | undefined; process_alerts_duration_ms?: string | number | undefined; trigger_actions_duration_ms?: string | number | undefined; process_rule_duration_ms?: string | number | undefined; claim_to_start_duration_ms?: string | number | undefined; prepare_rule_duration_ms?: string | number | undefined; total_run_duration_ms?: string | number | undefined; total_enrichment_duration_ms?: string | number | undefined; } & {}> | undefined; uuid?: string | undefined; status_order?: string | number | undefined; } & {}> | undefined; rule_type_id?: string | undefined; } & {}> | undefined; } & {}> | undefined; version?: string | undefined; alerting?: Readonly<{ status?: string | undefined; outcome?: string | undefined; instance_id?: string | undefined; action_group_id?: string | undefined; action_subgroup?: string | undefined; } & {}> | undefined; server_uuid?: string | undefined; task?: Readonly<{ id?: string | undefined; schedule_delay?: string | number | undefined; scheduled?: string | undefined; } & {}> | undefined; saved_objects?: Readonly<{ type?: string | undefined; id?: string | undefined; namespace?: string | undefined; rel?: string | undefined; type_id?: string | undefined; } & {}>[] | undefined; space_ids?: string[] | undefined; } & {}> | undefined; ecs?: Readonly<{ version?: string | undefined; } & {}> | undefined; rule?: Readonly<{ name?: string | undefined; description?: string | undefined; category?: string | undefined; id?: string | undefined; version?: string | undefined; license?: string | undefined; reference?: string | undefined; author?: string[] | undefined; ruleset?: string | undefined; uuid?: string | undefined; } & {}> | undefined; event?: Readonly<{ start?: string | undefined; category?: string[] | undefined; type?: string[] | undefined; id?: string | undefined; created?: string | undefined; outcome?: string | undefined; end?: string | undefined; original?: string | undefined; duration?: string | number | undefined; code?: string | undefined; url?: string | undefined; action?: string | undefined; kind?: string | undefined; hash?: string | undefined; severity?: string | number | undefined; dataset?: string | undefined; ingested?: string | undefined; module?: string | undefined; provider?: string | undefined; reason?: string | undefined; reference?: string | undefined; risk_score?: number | undefined; risk_score_norm?: number | undefined; sequence?: string | number | undefined; timezone?: string | undefined; } & {}> | undefined; '@timestamp'?: string | undefined; } & {}> | undefined)[]" ], "path": "x-pack/plugins/event_log/server/es/cluster_client_adapter.ts", "deprecated": false, @@ -1332,7 +1332,7 @@ "label": "IEvent", "description": [], "signature": [ - "DeepPartial | undefined; tags?: string[] | undefined; log?: Readonly<{ logger?: string | undefined; level?: string | undefined; } & {}> | undefined; user?: Readonly<{ name?: string | undefined; } & {}> | undefined; message?: string | undefined; kibana?: Readonly<{ alert?: Readonly<{ rule?: Readonly<{ consumer?: string | undefined; execution?: Readonly<{ status?: string | undefined; metrics?: Readonly<{ number_of_triggered_actions?: string | number | undefined; number_of_generated_actions?: string | number | undefined; alert_counts?: Readonly<{ active?: string | number | undefined; recovered?: string | number | undefined; new?: string | number | undefined; } & {}> | undefined; number_of_searches?: string | number | undefined; total_indexing_duration_ms?: string | number | undefined; es_search_duration_ms?: string | number | undefined; total_search_duration_ms?: string | number | undefined; execution_gap_duration_s?: string | number | undefined; rule_type_run_duration_ms?: string | number | undefined; process_alerts_duration_ms?: string | number | undefined; trigger_actions_duration_ms?: string | number | undefined; process_rule_duration_ms?: string | number | undefined; claim_to_start_duration_ms?: string | number | undefined; prepare_rule_duration_ms?: string | number | undefined; total_run_duration_ms?: string | number | undefined; total_enrichment_duration_ms?: string | number | undefined; } & {}> | undefined; uuid?: string | undefined; status_order?: string | number | undefined; } & {}> | undefined; rule_type_id?: string | undefined; } & {}> | undefined; } & {}> | undefined; version?: string | undefined; alerting?: Readonly<{ status?: string | undefined; instance_id?: string | undefined; action_group_id?: string | undefined; action_subgroup?: string | undefined; } & {}> | undefined; server_uuid?: string | undefined; task?: Readonly<{ id?: string | undefined; schedule_delay?: string | number | undefined; scheduled?: string | undefined; } & {}> | undefined; saved_objects?: Readonly<{ type?: string | undefined; id?: string | undefined; namespace?: string | undefined; rel?: string | undefined; type_id?: string | undefined; } & {}>[] | undefined; space_ids?: string[] | undefined; } & {}> | undefined; ecs?: Readonly<{ version?: string | undefined; } & {}> | undefined; rule?: Readonly<{ name?: string | undefined; description?: string | undefined; category?: string | undefined; id?: string | undefined; version?: string | undefined; license?: string | undefined; reference?: string | undefined; author?: string[] | undefined; ruleset?: string | undefined; uuid?: string | undefined; } & {}> | undefined; event?: Readonly<{ start?: string | undefined; category?: string[] | undefined; type?: string[] | undefined; id?: string | undefined; created?: string | undefined; outcome?: string | undefined; end?: string | undefined; original?: string | undefined; duration?: string | number | undefined; code?: string | undefined; url?: string | undefined; action?: string | undefined; kind?: string | undefined; hash?: string | undefined; severity?: string | number | undefined; dataset?: string | undefined; ingested?: string | undefined; module?: string | undefined; provider?: string | undefined; reason?: string | undefined; reference?: string | undefined; risk_score?: number | undefined; risk_score_norm?: number | undefined; sequence?: string | number | undefined; timezone?: string | undefined; } & {}> | undefined; '@timestamp'?: string | undefined; } & {}>>> | undefined" + "DeepPartial | undefined; tags?: string[] | undefined; log?: Readonly<{ logger?: string | undefined; level?: string | undefined; } & {}> | undefined; user?: Readonly<{ name?: string | undefined; } & {}> | undefined; message?: string | undefined; kibana?: Readonly<{ alert?: Readonly<{ rule?: Readonly<{ consumer?: string | undefined; execution?: Readonly<{ status?: string | undefined; metrics?: Readonly<{ number_of_triggered_actions?: string | number | undefined; number_of_generated_actions?: string | number | undefined; alert_counts?: Readonly<{ active?: string | number | undefined; recovered?: string | number | undefined; new?: string | number | undefined; } & {}> | undefined; number_of_searches?: string | number | undefined; total_indexing_duration_ms?: string | number | undefined; es_search_duration_ms?: string | number | undefined; total_search_duration_ms?: string | number | undefined; execution_gap_duration_s?: string | number | undefined; rule_type_run_duration_ms?: string | number | undefined; process_alerts_duration_ms?: string | number | undefined; trigger_actions_duration_ms?: string | number | undefined; process_rule_duration_ms?: string | number | undefined; claim_to_start_duration_ms?: string | number | undefined; prepare_rule_duration_ms?: string | number | undefined; total_run_duration_ms?: string | number | undefined; total_enrichment_duration_ms?: string | number | undefined; } & {}> | undefined; uuid?: string | undefined; status_order?: string | number | undefined; } & {}> | undefined; rule_type_id?: string | undefined; } & {}> | undefined; } & {}> | undefined; version?: string | undefined; alerting?: Readonly<{ status?: string | undefined; outcome?: string | undefined; instance_id?: string | undefined; action_group_id?: string | undefined; action_subgroup?: string | undefined; } & {}> | undefined; server_uuid?: string | undefined; task?: Readonly<{ id?: string | undefined; schedule_delay?: string | number | undefined; scheduled?: string | undefined; } & {}> | undefined; saved_objects?: Readonly<{ type?: string | undefined; id?: string | undefined; namespace?: string | undefined; rel?: string | undefined; type_id?: string | undefined; } & {}>[] | undefined; space_ids?: string[] | undefined; } & {}> | undefined; ecs?: Readonly<{ version?: string | undefined; } & {}> | undefined; rule?: Readonly<{ name?: string | undefined; description?: string | undefined; category?: string | undefined; id?: string | undefined; version?: string | undefined; license?: string | undefined; reference?: string | undefined; author?: string[] | undefined; ruleset?: string | undefined; uuid?: string | undefined; } & {}> | undefined; event?: Readonly<{ start?: string | undefined; category?: string[] | undefined; type?: string[] | undefined; id?: string | undefined; created?: string | undefined; outcome?: string | undefined; end?: string | undefined; original?: string | undefined; duration?: string | number | undefined; code?: string | undefined; url?: string | undefined; action?: string | undefined; kind?: string | undefined; hash?: string | undefined; severity?: string | number | undefined; dataset?: string | undefined; ingested?: string | undefined; module?: string | undefined; provider?: string | undefined; reason?: string | undefined; reference?: string | undefined; risk_score?: number | undefined; risk_score_norm?: number | undefined; sequence?: string | number | undefined; timezone?: string | undefined; } & {}> | undefined; '@timestamp'?: string | undefined; } & {}>>> | undefined" ], "path": "x-pack/plugins/event_log/generated/schemas.ts", "deprecated": false, @@ -1347,7 +1347,7 @@ "label": "IValidatedEvent", "description": [], "signature": [ - "Readonly<{ error?: Readonly<{ type?: string | undefined; id?: string | undefined; message?: string | undefined; code?: string | undefined; stack_trace?: string | undefined; } & {}> | undefined; tags?: string[] | undefined; log?: Readonly<{ logger?: string | undefined; level?: string | undefined; } & {}> | undefined; user?: Readonly<{ name?: string | undefined; } & {}> | undefined; message?: string | undefined; kibana?: Readonly<{ alert?: Readonly<{ rule?: Readonly<{ consumer?: string | undefined; execution?: Readonly<{ status?: string | undefined; metrics?: Readonly<{ number_of_triggered_actions?: string | number | undefined; number_of_generated_actions?: string | number | undefined; alert_counts?: Readonly<{ active?: string | number | undefined; recovered?: string | number | undefined; new?: string | number | undefined; } & {}> | undefined; number_of_searches?: string | number | undefined; total_indexing_duration_ms?: string | number | undefined; es_search_duration_ms?: string | number | undefined; total_search_duration_ms?: string | number | undefined; execution_gap_duration_s?: string | number | undefined; rule_type_run_duration_ms?: string | number | undefined; process_alerts_duration_ms?: string | number | undefined; trigger_actions_duration_ms?: string | number | undefined; process_rule_duration_ms?: string | number | undefined; claim_to_start_duration_ms?: string | number | undefined; prepare_rule_duration_ms?: string | number | undefined; total_run_duration_ms?: string | number | undefined; total_enrichment_duration_ms?: string | number | undefined; } & {}> | undefined; uuid?: string | undefined; status_order?: string | number | undefined; } & {}> | undefined; rule_type_id?: string | undefined; } & {}> | undefined; } & {}> | undefined; version?: string | undefined; alerting?: Readonly<{ status?: string | undefined; instance_id?: string | undefined; action_group_id?: string | undefined; action_subgroup?: string | undefined; } & {}> | undefined; server_uuid?: string | undefined; task?: Readonly<{ id?: string | undefined; schedule_delay?: string | number | undefined; scheduled?: string | undefined; } & {}> | undefined; saved_objects?: Readonly<{ type?: string | undefined; id?: string | undefined; namespace?: string | undefined; rel?: string | undefined; type_id?: string | undefined; } & {}>[] | undefined; space_ids?: string[] | undefined; } & {}> | undefined; ecs?: Readonly<{ version?: string | undefined; } & {}> | undefined; rule?: Readonly<{ name?: string | undefined; description?: string | undefined; category?: string | undefined; id?: string | undefined; version?: string | undefined; license?: string | undefined; reference?: string | undefined; author?: string[] | undefined; ruleset?: string | undefined; uuid?: string | undefined; } & {}> | undefined; event?: Readonly<{ start?: string | undefined; category?: string[] | undefined; type?: string[] | undefined; id?: string | undefined; created?: string | undefined; outcome?: string | undefined; end?: string | undefined; original?: string | undefined; duration?: string | number | undefined; code?: string | undefined; url?: string | undefined; action?: string | undefined; kind?: string | undefined; hash?: string | undefined; severity?: string | number | undefined; dataset?: string | undefined; ingested?: string | undefined; module?: string | undefined; provider?: string | undefined; reason?: string | undefined; reference?: string | undefined; risk_score?: number | undefined; risk_score_norm?: number | undefined; sequence?: string | number | undefined; timezone?: string | undefined; } & {}> | undefined; '@timestamp'?: string | undefined; } & {}> | undefined" + "Readonly<{ error?: Readonly<{ type?: string | undefined; id?: string | undefined; message?: string | undefined; code?: string | undefined; stack_trace?: string | undefined; } & {}> | undefined; tags?: string[] | undefined; log?: Readonly<{ logger?: string | undefined; level?: string | undefined; } & {}> | undefined; user?: Readonly<{ name?: string | undefined; } & {}> | undefined; message?: string | undefined; kibana?: Readonly<{ alert?: Readonly<{ rule?: Readonly<{ consumer?: string | undefined; execution?: Readonly<{ status?: string | undefined; metrics?: Readonly<{ number_of_triggered_actions?: string | number | undefined; number_of_generated_actions?: string | number | undefined; alert_counts?: Readonly<{ active?: string | number | undefined; recovered?: string | number | undefined; new?: string | number | undefined; } & {}> | undefined; number_of_searches?: string | number | undefined; total_indexing_duration_ms?: string | number | undefined; es_search_duration_ms?: string | number | undefined; total_search_duration_ms?: string | number | undefined; execution_gap_duration_s?: string | number | undefined; rule_type_run_duration_ms?: string | number | undefined; process_alerts_duration_ms?: string | number | undefined; trigger_actions_duration_ms?: string | number | undefined; process_rule_duration_ms?: string | number | undefined; claim_to_start_duration_ms?: string | number | undefined; prepare_rule_duration_ms?: string | number | undefined; total_run_duration_ms?: string | number | undefined; total_enrichment_duration_ms?: string | number | undefined; } & {}> | undefined; uuid?: string | undefined; status_order?: string | number | undefined; } & {}> | undefined; rule_type_id?: string | undefined; } & {}> | undefined; } & {}> | undefined; version?: string | undefined; alerting?: Readonly<{ status?: string | undefined; outcome?: string | undefined; instance_id?: string | undefined; action_group_id?: string | undefined; action_subgroup?: string | undefined; } & {}> | undefined; server_uuid?: string | undefined; task?: Readonly<{ id?: string | undefined; schedule_delay?: string | number | undefined; scheduled?: string | undefined; } & {}> | undefined; saved_objects?: Readonly<{ type?: string | undefined; id?: string | undefined; namespace?: string | undefined; rel?: string | undefined; type_id?: string | undefined; } & {}>[] | undefined; space_ids?: string[] | undefined; } & {}> | undefined; ecs?: Readonly<{ version?: string | undefined; } & {}> | undefined; rule?: Readonly<{ name?: string | undefined; description?: string | undefined; category?: string | undefined; id?: string | undefined; version?: string | undefined; license?: string | undefined; reference?: string | undefined; author?: string[] | undefined; ruleset?: string | undefined; uuid?: string | undefined; } & {}> | undefined; event?: Readonly<{ start?: string | undefined; category?: string[] | undefined; type?: string[] | undefined; id?: string | undefined; created?: string | undefined; outcome?: string | undefined; end?: string | undefined; original?: string | undefined; duration?: string | number | undefined; code?: string | undefined; url?: string | undefined; action?: string | undefined; kind?: string | undefined; hash?: string | undefined; severity?: string | number | undefined; dataset?: string | undefined; ingested?: string | undefined; module?: string | undefined; provider?: string | undefined; reason?: string | undefined; reference?: string | undefined; risk_score?: number | undefined; risk_score_norm?: number | undefined; sequence?: string | number | undefined; timezone?: string | undefined; } & {}> | undefined; '@timestamp'?: string | undefined; } & {}> | undefined" ], "path": "x-pack/plugins/event_log/generated/schemas.ts", "deprecated": false, diff --git a/api_docs/event_log.mdx b/api_docs/event_log.mdx index 01f3f85e83ae3..2b6acf592a50d 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-10 +date: 2022-10-16 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 d6cf5c3d25754..5cab9fbbe7d94 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-10 +date: 2022-10-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionError'] --- import expressionErrorObj from './expression_error.devdocs.json'; diff --git a/api_docs/expression_gauge.devdocs.json b/api_docs/expression_gauge.devdocs.json index 1575310553e8e..7869c0eedcb1c 100644 --- a/api_docs/expression_gauge.devdocs.json +++ b/api_docs/expression_gauge.devdocs.json @@ -550,6 +550,17 @@ "path": "src/plugins/chart_expressions/expression_gauge/common/types/expression_functions.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "expressionGauge", + "id": "def-common.GaugeExpressionProps.canNavigateToLens", + "type": "boolean", + "tags": [], + "label": "canNavigateToLens", + "description": [], + "path": "src/plugins/chart_expressions/expression_gauge/common/types/expression_functions.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false diff --git a/api_docs/expression_gauge.mdx b/api_docs/expression_gauge.mdx index 1fe3db16572f0..6e8e163994669 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-10 +date: 2022-10-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionGauge'] --- import expressionGaugeObj from './expression_gauge.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 | |-------------------|-----------|------------------------|-----------------| -| 57 | 0 | 57 | 2 | +| 58 | 0 | 58 | 2 | ## Client diff --git a/api_docs/expression_heatmap.devdocs.json b/api_docs/expression_heatmap.devdocs.json index dc63246351b8a..4e53b8fde2123 100644 --- a/api_docs/expression_heatmap.devdocs.json +++ b/api_docs/expression_heatmap.devdocs.json @@ -436,6 +436,17 @@ "path": "src/plugins/chart_expressions/expression_heatmap/common/types/expression_functions.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "expressionHeatmap", + "id": "def-common.HeatmapExpressionProps.syncTooltips", + "type": "boolean", + "tags": [], + "label": "syncTooltips", + "description": [], + "path": "src/plugins/chart_expressions/expression_heatmap/common/types/expression_functions.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false @@ -573,6 +584,8 @@ }, "; chartsThemeService: ", "Theme", + "; chartsActiveCursorService: ", + "ActiveCursor", "; datatableUtilities: ", { "pluginId": "data", @@ -607,7 +620,7 @@ "section": "def-public.PersistedState", "text": "PersistedState" }, - "; interactive: boolean; renderComplete: () => void; }" + "; interactive: boolean; syncTooltips: 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 dd0f849bf2e00..6830ca5c571a8 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-10 +date: 2022-10-16 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 | |-------------------|-----------|------------------------|-----------------| -| 105 | 0 | 101 | 3 | +| 106 | 0 | 102 | 3 | ## Common diff --git a/api_docs/expression_image.mdx b/api_docs/expression_image.mdx index 73ebc3735408f..ff7a8de07ec68 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-10 +date: 2022-10-16 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 3a6e7dee6c2bf..42a01634150a4 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-10 +date: 2022-10-16 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 f2a60f4396a7d..b51d5b55443bb 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-10 +date: 2022-10-16 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 536c4ed7764e9..b27c385a1a5ba 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-10 +date: 2022-10-16 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 0321ed48ea421..ff72d4d0a34dc 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-10 +date: 2022-10-16 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 43832994473b1..916161f5e7275 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-10 +date: 2022-10-16 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 8735e4a7b91b9..2b301f76884d3 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-10 +date: 2022-10-16 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 f10823d12ac9d..5edd9b78f6877 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-10 +date: 2022-10-16 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 ea1cfeadc6141..4333f72b86f9e 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-10 +date: 2022-10-16 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 70749833d4563..9378c2a614083 100644 --- a/api_docs/expression_x_y.devdocs.json +++ b/api_docs/expression_x_y.devdocs.json @@ -37,7 +37,23 @@ "initialIsOpen": false } ], - "objects": [] + "objects": [ + { + "parentPluginId": "expressionXY", + "id": "def-public.LayerTypes", + "type": "Object", + "tags": [], + "label": "LayerTypes", + "description": [], + "signature": [ + "{ readonly DATA: \"data\"; readonly REFERENCELINE: \"referenceLine\"; readonly ANNOTATIONS: \"annotations\"; }" + ], + "path": "src/plugins/chart_expressions/expression_xy/common/constants.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + } + ] }, "server": { "classes": [], @@ -1775,6 +1791,42 @@ "path": "src/plugins/chart_expressions/expression_xy/common/types/expression_renderers.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "expressionXY", + "id": "def-common.XYChartProps.syncTooltips", + "type": "boolean", + "tags": [], + "label": "syncTooltips", + "description": [], + "path": "src/plugins/chart_expressions/expression_xy/common/types/expression_renderers.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "expressionXY", + "id": "def-common.XYChartProps.syncColors", + "type": "boolean", + "tags": [], + "label": "syncColors", + "description": [], + "path": "src/plugins/chart_expressions/expression_xy/common/types/expression_renderers.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "expressionXY", + "id": "def-common.XYChartProps.canNavigateToLens", + "type": "CompoundType", + "tags": [], + "label": "canNavigateToLens", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "src/plugins/chart_expressions/expression_xy/common/types/expression_renderers.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false @@ -2673,6 +2725,22 @@ "initialIsOpen": false } ], - "objects": [] + "objects": [ + { + "parentPluginId": "expressionXY", + "id": "def-common.LayerTypes", + "type": "Object", + "tags": [], + "label": "LayerTypes", + "description": [], + "signature": [ + "{ readonly DATA: \"data\"; readonly REFERENCELINE: \"referenceLine\"; readonly ANNOTATIONS: \"annotations\"; }" + ], + "path": "src/plugins/chart_expressions/expression_xy/common/constants.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + } + ] } } \ No newline at end of file diff --git a/api_docs/expression_x_y.mdx b/api_docs/expression_x_y.mdx index 5c3926722ab59..d202f0c1383ef 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-10 +date: 2022-10-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionXY'] --- import expressionXYObj from './expression_x_y.devdocs.json'; @@ -21,10 +21,13 @@ Contact [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 153 | 0 | 143 | 9 | +| 158 | 0 | 148 | 9 | ## Client +### Objects + + ### Consts, variables and types @@ -35,6 +38,9 @@ Contact [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) ## Common +### Objects + + ### Interfaces diff --git a/api_docs/expressions.mdx b/api_docs/expressions.mdx index 825f043405431..514981b4f11fb 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-10 +date: 2022-10-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressions'] --- import expressionsObj from './expressions.devdocs.json'; diff --git a/api_docs/features.devdocs.json b/api_docs/features.devdocs.json index a6e9773502284..cbbe75fe20fa4 100644 --- a/api_docs/features.devdocs.json +++ b/api_docs/features.devdocs.json @@ -2335,6 +2335,10 @@ "plugin": "security", "path": "x-pack/plugins/security/server/authorization/privileges/privileges.test.ts" }, + { + "plugin": "security", + "path": "x-pack/plugins/security/server/authorization/privileges/privileges.test.ts" + }, { "plugin": "spaces", "path": "x-pack/plugins/spaces/server/lib/request_interceptors/on_post_auth_interceptor.test.ts" diff --git a/api_docs/features.mdx b/api_docs/features.mdx index 416f97990d566..58760c689b15d 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-10 +date: 2022-10-16 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 9ead59b5563f6..c127d352c392f 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-10 +date: 2022-10-16 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 bf3db3e921d0c..b34c6e1563627 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-10 +date: 2022-10-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fileUpload'] --- import fileUploadObj from './file_upload.devdocs.json'; diff --git a/api_docs/files.devdocs.json b/api_docs/files.devdocs.json index aaf7a55eb4c7f..86537866c421c 100644 --- a/api_docs/files.devdocs.json +++ b/api_docs/files.devdocs.json @@ -284,7 +284,7 @@ "\nList all file objects, of a given {@link FileKind}.\n" ], "signature": [ - "(args: Readonly<{ page?: number | undefined; perPage?: number | undefined; } & {}> & { kind: string; }) => Promise<{ files: ", + "(args: Readonly<{ name?: string | string[] | undefined; status?: string | string[] | undefined; meta?: Readonly<{} & {}> | undefined; extension?: string | string[] | undefined; } & {}> & Readonly<{ page?: number | undefined; perPage?: number | undefined; } & {}> & { kind: string; }) => Promise<{ files: ", { "pluginId": "files", "scope": "common", @@ -292,7 +292,7 @@ "section": "def-common.FileJSON", "text": "FileJSON" }, - "[]; }>" + "[]; total: number; }>" ], "path": "x-pack/plugins/files/public/types.ts", "deprecated": false, @@ -1093,7 +1093,7 @@ "section": "def-common.FileJSON", "text": "FileJSON" }, - "[]; }; update: { file: ", + "[]; total: number; }; update: { file: ", { "pluginId": "files", "scope": "common", @@ -1141,7 +1141,7 @@ "section": "def-common.FileJSON", "text": "FileJSON" }, - "[]; }; }" + "[]; total: number; }; }" ], "path": "x-pack/plugins/files/public/types.ts", "deprecated": false, @@ -1174,7 +1174,7 @@ "section": "def-common.FileJSON", "text": "FileJSON" }, - "; }>; list: (arg?: Omit & { kind: string; }, \"kind\"> | undefined) => Promise<{ files: ", + "; }>; list: (arg?: Omit | undefined; extension?: string | string[] | undefined; } & {}> & Readonly<{ page?: number | undefined; perPage?: number | undefined; } & {}> & { kind: string; }, \"kind\"> | undefined) => Promise<{ files: ", { "pluginId": "files", "scope": "common", @@ -1182,7 +1182,7 @@ "section": "def-common.FileJSON", "text": "FileJSON" }, - "[]; }>; update: (arg: Omit | undefined; alt?: string | undefined; } & {}> & Readonly<{} & { id: string; }> & { kind: string; }, \"kind\">) => Promise<{ file: ", + "[]; total: number; }>; update: (arg: Omit | undefined; alt?: string | undefined; } & {}> & Readonly<{} & { id: string; }> & { kind: string; }, \"kind\">) => Promise<{ file: ", { "pluginId": "files", "scope": "common", @@ -1238,7 +1238,7 @@ "section": "def-common.FileJSON", "text": "FileJSON" }, - "[]; }>; }" + "[]; total: number; }>; }" ], "path": "x-pack/plugins/files/public/types.ts", "deprecated": false, @@ -1648,7 +1648,9 @@ "TransportRequestOptions", " | undefined): Promise<", "UpdateResponse", - ">; }; [kInternal]: symbol | null; [kAsyncSearch]: symbol | null; [kAutoscaling]: symbol | null; [kCat]: symbol | null; [kCcr]: symbol | null; [kCluster]: symbol | null; [kDanglingIndices]: symbol | null; [kEnrich]: symbol | null; [kEql]: symbol | null; [kFeatures]: symbol | null; [kFleet]: symbol | null; [kGraph]: symbol | null; [kIlm]: symbol | null; [kIndices]: symbol | null; [kIngest]: symbol | null; [kLicense]: symbol | null; [kLogstash]: symbol | null; [kMigration]: symbol | null; [kMl]: symbol | null; [kMonitoring]: symbol | null; [kNodes]: symbol | null; [kRollup]: symbol | null; [kSearchableSnapshots]: symbol | null; [kSecurity]: symbol | null; [kShutdown]: symbol | null; [kSlm]: symbol | null; [kSnapshot]: symbol | null; [kSql]: symbol | null; [kSsl]: symbol | null; [kTasks]: symbol | null; [kTextStructure]: symbol | null; [kTransform]: symbol | null; [kWatcher]: symbol | null; [kXpack]: symbol | null; transport: ", + ">; }; asyncSearch: ", + "default", + "; [kInternal]: symbol | null; [kAsyncSearch]: symbol | null; [kAutoscaling]: symbol | null; [kCat]: symbol | null; [kCcr]: symbol | null; [kCluster]: symbol | null; [kDanglingIndices]: symbol | null; [kEnrich]: symbol | null; [kEql]: symbol | null; [kFeatures]: symbol | null; [kFleet]: symbol | null; [kGraph]: symbol | null; [kIlm]: symbol | null; [kIndices]: symbol | null; [kIngest]: symbol | null; [kLicense]: symbol | null; [kLogstash]: symbol | null; [kMigration]: symbol | null; [kMl]: symbol | null; [kMonitoring]: symbol | null; [kNodes]: symbol | null; [kRollup]: symbol | null; [kSearchableSnapshots]: symbol | null; [kSecurity]: symbol | null; [kShutdown]: symbol | null; [kSlm]: symbol | null; [kSnapshot]: symbol | null; [kSql]: symbol | null; [kSsl]: symbol | null; [kTasks]: symbol | null; [kTextStructure]: symbol | null; [kTransform]: symbol | null; [kWatcher]: symbol | null; [kXpack]: symbol | null; transport: ", "default", "; helpers: ", "default", @@ -1658,8 +1660,6 @@ "default", "; Internal: ", "default", - "; asyncSearch: ", - "default", "; autoscaling: ", "default", "; bulk: { (this: That, params: ", @@ -3228,65 +3228,6 @@ ], "returnComment": [] }, - { - "parentPluginId": "files", - "id": "def-server.FileClient.list", - "type": "Function", - "tags": [], - "label": "list", - "description": [ - "\nSee {@link FileMetadataClient.list}\n" - ], - "signature": [ - "(arg?: ", - { - "pluginId": "files", - "scope": "server", - "docId": "kibFilesPluginApi", - "section": "def-server.ListArg", - "text": "ListArg" - }, - " | undefined) => Promise<", - { - "pluginId": "files", - "scope": "common", - "docId": "kibFilesPluginApi", - "section": "def-common.File", - "text": "File" - }, - "[]>" - ], - "path": "x-pack/plugins/files/server/file_client/types.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "files", - "id": "def-server.FileClient.list.$1", - "type": "Object", - "tags": [], - "label": "arg", - "description": [ - "- Argument to list files" - ], - "signature": [ - { - "pluginId": "files", - "scope": "server", - "docId": "kibFilesPluginApi", - "section": "def-server.ListArg", - "text": "ListArg" - }, - " | undefined" - ], - "path": "x-pack/plugins/files/server/file_client/types.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": false - } - ], - "returnComment": [] - }, { "parentPluginId": "files", "id": "def-server.FileClient.find", @@ -3297,7 +3238,7 @@ "\nSee {@link FileMetadataClient.find}.\n" ], "signature": [ - "(arg: ", + "(arg?: ", { "pluginId": "files", "scope": "server", @@ -3305,7 +3246,7 @@ "section": "def-server.FindFileArgs", "text": "FindFileArgs" }, - ") => Promise<", + " | undefined) => Promise<{ files: ", { "pluginId": "files", "scope": "common", @@ -3313,7 +3254,7 @@ "section": "def-common.File", "text": "File" }, - "[]>" + "[]; total: number; }>" ], "path": "x-pack/plugins/files/server/file_client/types.ts", "deprecated": false, @@ -3335,12 +3276,13 @@ "docId": "kibFilesPluginApi", "section": "def-server.FindFileArgs", "text": "FindFileArgs" - } + }, + " | undefined" ], "path": "x-pack/plugins/files/server/file_client/types.ts", "deprecated": false, "trackAdoption": false, - "isRequired": true + "isRequired": false } ], "returnComment": [] @@ -3802,65 +3744,6 @@ ], "returnComment": [] }, - { - "parentPluginId": "files", - "id": "def-server.FileMetadataClient.list", - "type": "Function", - "tags": [], - "label": "list", - "description": [ - "\nList all instances of metadata for a file kind.\n" - ], - "signature": [ - "(arg?: ", - { - "pluginId": "files", - "scope": "server", - "docId": "kibFilesPluginApi", - "section": "def-server.ListArg", - "text": "ListArg" - }, - " | undefined) => Promise<", - { - "pluginId": "files", - "scope": "server", - "docId": "kibFilesPluginApi", - "section": "def-server.FileDescriptor", - "text": "FileDescriptor" - }, - "[]>" - ], - "path": "x-pack/plugins/files/server/file_client/file_metadata_client/file_metadata_client.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "files", - "id": "def-server.FileMetadataClient.list.$1", - "type": "Object", - "tags": [], - "label": "arg", - "description": [ - "- Arguments to list file metadata" - ], - "signature": [ - { - "pluginId": "files", - "scope": "server", - "docId": "kibFilesPluginApi", - "section": "def-server.ListArg", - "text": "ListArg" - }, - " | undefined" - ], - "path": "x-pack/plugins/files/server/file_client/file_metadata_client/file_metadata_client.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": false - } - ], - "returnComment": [] - }, { "parentPluginId": "files", "id": "def-server.FileMetadataClient.find", @@ -3871,7 +3754,7 @@ "\nSearch for a set of file kind instances that match the filters.\n" ], "signature": [ - "(arg: ", + "(arg?: ", { "pluginId": "files", "scope": "server", @@ -3879,7 +3762,7 @@ "section": "def-server.FindFileArgs", "text": "FindFileArgs" }, - ") => Promise<", + " | undefined) => Promise<{ total: number; files: ", { "pluginId": "files", "scope": "server", @@ -3887,7 +3770,7 @@ "section": "def-server.FileDescriptor", "text": "FileDescriptor" }, - "[]>" + "[]; }>" ], "path": "x-pack/plugins/files/server/file_client/file_metadata_client/file_metadata_client.ts", "deprecated": false, @@ -3909,12 +3792,13 @@ "docId": "kibFilesPluginApi", "section": "def-server.FindFileArgs", "text": "FindFileArgs" - } + }, + " | undefined" ], "path": "x-pack/plugins/files/server/file_client/file_metadata_client/file_metadata_client.ts", "deprecated": false, "trackAdoption": false, - "isRequired": true + "isRequired": false } ], "returnComment": [] @@ -4317,7 +4201,7 @@ "section": "def-server.FindFileArgs", "text": "FindFileArgs" }, - ") => Promise<", + ") => Promise<{ files: ", { "pluginId": "files", "scope": "common", @@ -4325,7 +4209,7 @@ "section": "def-common.FileJSON", "text": "FileJSON" }, - "[]>" + "[]; total: number; }>" ], "path": "x-pack/plugins/files/server/file_service/file_service.ts", "deprecated": false, @@ -4357,64 +4241,6 @@ ], "returnComment": [] }, - { - "parentPluginId": "files", - "id": "def-server.FileServiceStart.list", - "type": "Function", - "tags": [], - "label": "list", - "description": [ - "\nList all files of specific file kind.\n" - ], - "signature": [ - "(args: ", - { - "pluginId": "files", - "scope": "server", - "docId": "kibFilesPluginApi", - "section": "def-server.ListFilesArgs", - "text": "ListFilesArgs" - }, - ") => Promise<", - { - "pluginId": "files", - "scope": "common", - "docId": "kibFilesPluginApi", - "section": "def-common.File", - "text": "File" - }, - "[]>" - ], - "path": "x-pack/plugins/files/server/file_service/file_service.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "files", - "id": "def-server.FileServiceStart.list.$1", - "type": "Object", - "tags": [], - "label": "args", - "description": [ - "- list files args" - ], - "signature": [ - { - "pluginId": "files", - "scope": "server", - "docId": "kibFilesPluginApi", - "section": "def-server.ListFilesArgs", - "text": "ListFilesArgs" - } - ], - "path": "x-pack/plugins/files/server/file_service/file_service.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, { "parentPluginId": "files", "id": "def-server.FileServiceStart.getShareObject", @@ -5157,53 +4983,6 @@ ], "initialIsOpen": false }, - { - "parentPluginId": "files", - "id": "def-server.ListArg", - "type": "Interface", - "tags": [], - "label": "ListArg", - "description": [], - "signature": [ - { - "pluginId": "files", - "scope": "server", - "docId": "kibFilesPluginApi", - "section": "def-server.ListArg", - "text": "ListArg" - }, - " extends ", - { - "pluginId": "files", - "scope": "common", - "docId": "kibFilesPluginApi", - "section": "def-common.Pagination", - "text": "Pagination" - } - ], - "path": "x-pack/plugins/files/server/file_client/file_metadata_client/file_metadata_client.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "files", - "id": "def-server.ListArg.fileKind", - "type": "string", - "tags": [], - "label": "fileKind", - "description": [ - "\nThe file kind to scope this query to" - ], - "signature": [ - "string | undefined" - ], - "path": "x-pack/plugins/files/server/file_client/file_metadata_client/file_metadata_client.ts", - "deprecated": false, - "trackAdoption": false - } - ], - "initialIsOpen": false - }, { "parentPluginId": "files", "id": "def-server.ListArgs", @@ -5253,52 +5032,6 @@ ], "initialIsOpen": false }, - { - "parentPluginId": "files", - "id": "def-server.ListFilesArgs", - "type": "Interface", - "tags": [], - "label": "ListFilesArgs", - "description": [ - "\nArguments list files." - ], - "signature": [ - { - "pluginId": "files", - "scope": "server", - "docId": "kibFilesPluginApi", - "section": "def-server.ListFilesArgs", - "text": "ListFilesArgs" - }, - " extends ", - { - "pluginId": "files", - "scope": "common", - "docId": "kibFilesPluginApi", - "section": "def-common.Pagination", - "text": "Pagination" - } - ], - "path": "x-pack/plugins/files/server/file_service/file_action_types.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "files", - "id": "def-server.ListFilesArgs.fileKind", - "type": "string", - "tags": [], - "label": "fileKind", - "description": [ - "\nFile kind, must correspond to a registered {@link FileKind}." - ], - "path": "x-pack/plugins/files/server/file_service/file_action_types.ts", - "deprecated": false, - "trackAdoption": false - } - ], - "initialIsOpen": false - }, { "parentPluginId": "files", "id": "def-server.UpdateArgs", diff --git a/api_docs/files.mdx b/api_docs/files.mdx index e71dfb9e8652f..bcfb1e0c9879f 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-10 +date: 2022-10-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'files'] --- import filesObj from './files.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-app-services](https://github.com/orgs/elastic/teams/tea | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 270 | 0 | 15 | 2 | +| 260 | 0 | 14 | 2 | ## Client diff --git a/api_docs/fleet.devdocs.json b/api_docs/fleet.devdocs.json index 292965453dec7..21d05ee976bb4 100644 --- a/api_docs/fleet.devdocs.json +++ b/api_docs/fleet.devdocs.json @@ -5271,10 +5271,10 @@ }, { "parentPluginId": "fleet", - "id": "def-server.PackageClient.getRegistryPackage", + "id": "def-server.PackageClient.getPackage", "type": "Function", "tags": [], - "label": "getRegistryPackage", + "label": "getPackage", "description": [], "signature": [ "(packageName: string, packageVersion: string) => Promise<{ packageInfo: ", @@ -5282,8 +5282,8 @@ "pluginId": "fleet", "scope": "common", "docId": "kibFleetPluginApi", - "section": "def-common.RegistryPackage", - "text": "RegistryPackage" + "section": "def-common.ArchivePackage", + "text": "ArchivePackage" }, "; paths: string[]; }>" ], @@ -5293,7 +5293,7 @@ "children": [ { "parentPluginId": "fleet", - "id": "def-server.PackageClient.getRegistryPackage.$1", + "id": "def-server.PackageClient.getPackage.$1", "type": "string", "tags": [], "label": "packageName", @@ -5308,7 +5308,7 @@ }, { "parentPluginId": "fleet", - "id": "def-server.PackageClient.getRegistryPackage.$2", + "id": "def-server.PackageClient.getPackage.$2", "type": "string", "tags": [], "label": "packageVersion", diff --git a/api_docs/fleet.mdx b/api_docs/fleet.mdx index 82149c338ffde..f4f61dd3b3123 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-10 +date: 2022-10-16 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 bd9ccebf846d7..925d55c808c07 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-10 +date: 2022-10-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'globalSearch'] --- import globalSearchObj from './global_search.devdocs.json'; diff --git a/api_docs/guided_onboarding.devdocs.json b/api_docs/guided_onboarding.devdocs.json index 5b5809dbbe1e8..701721e92edd3 100644 --- a/api_docs/guided_onboarding.devdocs.json +++ b/api_docs/guided_onboarding.devdocs.json @@ -108,7 +108,7 @@ "label": "status", "description": [], "signature": [ - "\"complete\" | \"in_progress\" | \"inactive\" | \"active\"" + "\"complete\" | \"in_progress\" | \"ready_to_complete\" | \"inactive\" | \"active\"" ], "path": "src/plugins/guided_onboarding/common/types.ts", "deprecated": false, diff --git a/api_docs/guided_onboarding.mdx b/api_docs/guided_onboarding.mdx index 1021f353f39d5..87301a8a9ba43 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-10 +date: 2022-10-16 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 a1269fecd710d..693c339b69cd8 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-10 +date: 2022-10-16 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 d64fb3896ad9d..0643429047c03 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-10 +date: 2022-10-16 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 c0db624b8d38d..b47905802e1c5 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-10 +date: 2022-10-16 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 4e9dd1b904ede..c4b3a15d72b09 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-10 +date: 2022-10-16 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 c81edba15ec6b..b5d5eabf85964 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-10 +date: 2022-10-16 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 208c8049e38b4..7d934c8c4ca11 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-10 +date: 2022-10-16 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 083f69d0939a1..db812226f7acb 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-10 +date: 2022-10-16 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 61d044d8d2f42..51086e8bc3624 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-10 +date: 2022-10-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/aiops-components'] --- import kbnAiopsComponentsObj from './kbn_aiops_components.devdocs.json'; diff --git a/api_docs/kbn_aiops_utils.devdocs.json b/api_docs/kbn_aiops_utils.devdocs.json index 5fae256126a14..9a6e5f07f153e 100644 --- a/api_docs/kbn_aiops_utils.devdocs.json +++ b/api_docs/kbn_aiops_utils.devdocs.json @@ -190,7 +190,7 @@ "Headers", ", logger: ", "Logger", - ", flushFix: boolean | undefined) => StreamFactoryReturnType" + ", compressOverride: boolean | undefined, flushFix: boolean | undefined) => StreamFactoryReturnType" ], "path": "x-pack/packages/ml/aiops_utils/src/stream_factory.ts", "deprecated": false, @@ -219,7 +219,9 @@ "type": "Object", "tags": [], "label": "logger", - "description": [], + "description": [ + "- Kibana logger." + ], "signature": [ "Logger" ], @@ -233,8 +235,27 @@ "id": "def-common.streamFactory.$3", "type": "CompoundType", "tags": [], + "label": "compressOverride", + "description": [ + "- Optional flag to override header based compression setting." + ], + "signature": [ + "boolean | undefined" + ], + "path": "x-pack/packages/ml/aiops_utils/src/stream_factory.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + }, + { + "parentPluginId": "@kbn/aiops-utils", + "id": "def-common.streamFactory.$4", + "type": "CompoundType", + "tags": [], "label": "flushFix", - "description": [], + "description": [ + "- Adds an attribute with a random string payload to overcome buffer flushing with certain proxy configurations." + ], "signature": [ "boolean | undefined" ], @@ -263,7 +284,7 @@ "Headers", ", logger: ", "Logger", - ", flushFix: boolean) => StreamFactoryReturnType" + ", compressOverride: boolean, flushFix: boolean) => StreamFactoryReturnType" ], "path": "x-pack/packages/ml/aiops_utils/src/stream_factory.ts", "deprecated": false, @@ -292,7 +313,9 @@ "type": "Object", "tags": [], "label": "logger", - "description": [], + "description": [ + "- Kibana logger." + ], "signature": [ "Logger" ], @@ -306,8 +329,27 @@ "id": "def-common.streamFactory.$3", "type": "boolean", "tags": [], + "label": "compressOverride", + "description": [ + "- Optional flag to override header based compression setting." + ], + "signature": [ + "boolean" + ], + "path": "x-pack/packages/ml/aiops_utils/src/stream_factory.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/aiops-utils", + "id": "def-common.streamFactory.$4", + "type": "boolean", + "tags": [], "label": "flushFix", - "description": [], + "description": [ + "- Adds an attribute with a random string payload to overcome buffer flushing with certain proxy configurations." + ], "signature": [ "boolean" ], diff --git a/api_docs/kbn_aiops_utils.mdx b/api_docs/kbn_aiops_utils.mdx index 3cd0f613a9e3d..8957e5b2de6e7 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-10 +date: 2022-10-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/aiops-utils'] --- import kbnAiopsUtilsObj from './kbn_aiops_utils.devdocs.json'; @@ -21,7 +21,7 @@ Contact Machine Learning UI for questions regarding this plugin. | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 51 | 0 | 26 | 0 | +| 53 | 0 | 22 | 0 | ## Common diff --git a/api_docs/kbn_alerts.mdx b/api_docs/kbn_alerts.mdx index e177b66a85837..7a8870cf48fcb 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-10 +date: 2022-10-16 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 b7fc346931109..7d8b664379cac 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-10 +date: 2022-10-16 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 28a6f6bafc1af..0a06ec8ec2af8 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-10 +date: 2022-10-16 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 070f03039547f..e95a65dc107ad 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-10 +date: 2022-10-16 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 8c7ceac1d78f9..4ac866259bf48 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-10 +date: 2022-10-16 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 7a21c30fd3843..87df3051c0d2b 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-10 +date: 2022-10-16 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 c1926cbf98c9a..006375afb4e19 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-10 +date: 2022-10-16 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 c9629dc573b1d..59bba06406a1a 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-10 +date: 2022-10-16 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.devdocs.json b/api_docs/kbn_apm_synthtrace.devdocs.json index 565fde2f17163..394028d4c885e 100644 --- a/api_docs/kbn_apm_synthtrace.devdocs.json +++ b/api_docs/kbn_apm_synthtrace.devdocs.json @@ -1022,9 +1022,9 @@ "section": "def-server.ApmException", "text": "ApmException" }, - "[]; 'error.grouping_name': string; 'error.grouping_key': string; 'host.name': string; 'host.hostname': string; 'kubernetes.pod.uid': string; 'kubernetes.pod.name': string; 'metricset.name': string; observer: ", + "[]; 'error.grouping_name': string; 'error.grouping_key': string; 'host.name': string; 'host.hostname': string; 'http.request.method': string; 'http.response.status_code': number; 'kubernetes.pod.uid': string; 'kubernetes.pod.name': string; 'metricset.name': string; observer: ", "Observer", - "; 'parent.id': string; 'processor.event': string; 'processor.name': string; 'trace.id': string; 'transaction.name': string; 'transaction.type': string; 'transaction.id': string; 'transaction.duration.us': number; 'transaction.duration.histogram': { values: number[]; counts: number[]; }; 'transaction.sampled': true; 'service.name': string; 'service.version': string; 'service.environment': string; 'service.node.name': string; 'service.runtime.name': string; 'service.runtime.version': string; 'service.framework.name': string; 'service.target.name': string; 'service.target.type': string; 'span.id': string; 'span.name': string; 'span.type': string; 'span.subtype': string; 'span.duration.us': number; 'span.destination.service.name': string; 'span.destination.service.resource': string; 'span.destination.service.type': string; 'span.destination.service.response_time.sum.us': number; 'span.destination.service.response_time.count': number; 'span.self_time.count': number; 'span.self_time.sum.us': number; 'span.links': { trace: { id: string; }; span: { id: string; }; }[]; 'cloud.provider': string; 'cloud.project.name': string; 'cloud.service.name': string; 'cloud.availability_zone': string; 'cloud.machine.type': string; 'cloud.region': string; 'host.os.platform': string; 'faas.id': string; 'faas.name': string; 'faas.coldstart': boolean; 'faas.execution': string; 'faas.trigger.type': string; 'faas.trigger.request_id': string; }> & Partial<{ 'system.process.memory.size': number; 'system.memory.actual.free': number; 'system.memory.total': number; 'system.cpu.total.norm.pct': number; 'system.process.memory.rss.bytes': number; 'system.process.cpu.total.norm.pct': number; 'jvm.memory.heap.used': number; 'jvm.memory.non_heap.used': number; 'jvm.thread.count': number; 'faas.billed_duration': number; 'faas.timeout': number; 'faas.coldstart_duration': number; 'faas.duration': number; }>" + "; 'parent.id': string; 'processor.event': string; 'processor.name': string; 'trace.id': string; 'transaction.name': string; 'transaction.type': string; 'transaction.id': string; 'transaction.duration.us': number; 'transaction.duration.histogram': { values: number[]; counts: number[]; }; 'transaction.sampled': true; 'service.name': string; 'service.version': string; 'service.environment': string; 'service.node.name': string; 'service.runtime.name': string; 'service.runtime.version': string; 'service.framework.name': string; 'service.target.name': string; 'service.target.type': string; 'span.action': string; 'span.id': string; 'span.name': string; 'span.type': string; 'span.subtype': string; 'span.duration.us': number; 'span.destination.service.resource': string; 'span.destination.service.response_time.sum.us': number; 'span.destination.service.response_time.count': number; 'span.self_time.count': number; 'span.self_time.sum.us': number; 'span.links': { trace: { id: string; }; span: { id: string; }; }[]; 'cloud.provider': string; 'cloud.project.name': string; 'cloud.service.name': string; 'cloud.availability_zone': string; 'cloud.machine.type': string; 'cloud.region': string; 'host.os.platform': string; 'faas.id': string; 'faas.name': string; 'faas.coldstart': boolean; 'faas.execution': string; 'faas.trigger.type': string; 'faas.trigger.request_id': string; }> & Partial<{ 'system.process.memory.size': number; 'system.memory.actual.free': number; 'system.memory.total': number; 'system.cpu.total.norm.pct': number; 'system.process.memory.rss.bytes': number; 'system.process.cpu.total.norm.pct': number; 'jvm.memory.heap.used': number; 'jvm.memory.non_heap.used': number; 'jvm.thread.count': number; 'faas.billed_duration': number; 'faas.timeout': number; 'faas.coldstart_duration': number; 'faas.duration': number; }>" ], "path": "packages/kbn-apm-synthtrace/src/lib/apm/apm_fields.ts", "deprecated": false, @@ -1132,9 +1132,9 @@ "section": "def-server.ApmException", "text": "ApmException" }, - "[] | undefined; 'error.grouping_name'?: string | undefined; 'error.grouping_key'?: string | undefined; 'host.name'?: string | undefined; 'host.hostname'?: string | undefined; 'kubernetes.pod.uid'?: string | undefined; 'kubernetes.pod.name'?: string | undefined; observer?: ", + "[] | undefined; 'error.grouping_name'?: string | undefined; 'error.grouping_key'?: string | undefined; 'host.name'?: string | undefined; 'host.hostname'?: string | undefined; 'http.request.method'?: string | undefined; 'http.response.status_code'?: number | undefined; 'kubernetes.pod.uid'?: string | undefined; 'kubernetes.pod.name'?: string | undefined; observer?: ", "Observer", - " | undefined; 'parent.id'?: string | undefined; 'processor.event'?: string | undefined; 'processor.name'?: string | undefined; 'trace.id'?: string | undefined; 'transaction.name'?: string | undefined; 'transaction.type'?: string | undefined; 'transaction.id'?: string | undefined; 'transaction.duration.us'?: number | undefined; 'transaction.sampled'?: true | undefined; 'service.name'?: string | undefined; 'service.version'?: string | undefined; 'service.environment'?: string | undefined; 'service.node.name'?: string | undefined; 'service.runtime.name'?: string | undefined; 'service.runtime.version'?: string | undefined; 'service.framework.name'?: string | undefined; 'service.target.name'?: string | undefined; 'service.target.type'?: string | undefined; 'span.id'?: string | undefined; 'span.name'?: string | undefined; 'span.type'?: string | undefined; 'span.subtype'?: string | undefined; 'span.duration.us'?: number | undefined; 'span.destination.service.name'?: string | undefined; 'span.destination.service.resource'?: string | undefined; 'span.destination.service.type'?: string | undefined; 'span.destination.service.response_time.sum.us'?: number | undefined; 'span.destination.service.response_time.count'?: number | undefined; 'span.self_time.count'?: number | undefined; 'span.self_time.sum.us'?: number | undefined; 'span.links'?: { trace: { id: string; }; span: { id: string; }; }[] | undefined; 'cloud.provider'?: string | undefined; 'cloud.project.name'?: string | undefined; 'cloud.service.name'?: string | undefined; 'cloud.availability_zone'?: string | undefined; 'cloud.machine.type'?: string | undefined; 'cloud.region'?: string | undefined; 'host.os.platform'?: string | undefined; 'faas.id'?: string | undefined; 'faas.name'?: string | undefined; 'faas.coldstart'?: boolean | undefined; 'faas.execution'?: string | undefined; 'faas.trigger.type'?: string | undefined; 'faas.trigger.request_id'?: string | undefined; 'system.process.memory.size'?: number | undefined; 'system.memory.actual.free'?: number | undefined; 'system.memory.total'?: number | undefined; 'system.cpu.total.norm.pct'?: number | undefined; 'system.process.memory.rss.bytes'?: number | undefined; 'system.process.cpu.total.norm.pct'?: number | undefined; 'jvm.memory.heap.used'?: number | undefined; 'jvm.memory.non_heap.used'?: number | undefined; 'jvm.thread.count'?: number | undefined; 'faas.billed_duration'?: number | undefined; 'faas.timeout'?: number | undefined; 'faas.coldstart_duration'?: number | undefined; 'faas.duration'?: number | undefined; }[]" + " | undefined; 'parent.id'?: string | undefined; 'processor.event'?: string | undefined; 'processor.name'?: string | undefined; 'trace.id'?: string | undefined; 'transaction.name'?: string | undefined; 'transaction.type'?: string | undefined; 'transaction.id'?: string | undefined; 'transaction.duration.us'?: number | undefined; 'transaction.sampled'?: true | undefined; 'service.name'?: string | undefined; 'service.version'?: string | undefined; 'service.environment'?: string | undefined; 'service.node.name'?: string | undefined; 'service.runtime.name'?: string | undefined; 'service.runtime.version'?: string | undefined; 'service.framework.name'?: string | undefined; 'service.target.name'?: string | undefined; 'service.target.type'?: string | undefined; 'span.action'?: string | undefined; 'span.id'?: string | undefined; 'span.name'?: string | undefined; 'span.type'?: string | undefined; 'span.subtype'?: string | undefined; 'span.duration.us'?: number | undefined; 'span.destination.service.resource'?: string | undefined; 'span.destination.service.response_time.sum.us'?: number | undefined; 'span.destination.service.response_time.count'?: number | undefined; 'span.self_time.count'?: number | undefined; 'span.self_time.sum.us'?: number | undefined; 'span.links'?: { trace: { id: string; }; span: { id: string; }; }[] | undefined; 'cloud.provider'?: string | undefined; 'cloud.project.name'?: string | undefined; 'cloud.service.name'?: string | undefined; 'cloud.availability_zone'?: string | undefined; 'cloud.machine.type'?: string | undefined; 'cloud.region'?: string | undefined; 'host.os.platform'?: string | undefined; 'faas.id'?: string | undefined; 'faas.name'?: string | undefined; 'faas.coldstart'?: boolean | undefined; 'faas.execution'?: string | undefined; 'faas.trigger.type'?: string | undefined; 'faas.trigger.request_id'?: string | undefined; 'system.process.memory.size'?: number | undefined; 'system.memory.actual.free'?: number | undefined; 'system.memory.total'?: number | undefined; 'system.cpu.total.norm.pct'?: number | undefined; 'system.process.memory.rss.bytes'?: number | undefined; 'system.process.cpu.total.norm.pct'?: number | undefined; 'jvm.memory.heap.used'?: number | undefined; 'jvm.memory.non_heap.used'?: number | undefined; 'jvm.thread.count'?: number | undefined; 'faas.billed_duration'?: number | undefined; 'faas.timeout'?: number | undefined; 'faas.coldstart_duration'?: number | undefined; 'faas.duration'?: number | undefined; }[]" ], "path": "packages/kbn-apm-synthtrace/src/lib/apm/index.ts", "deprecated": false, @@ -1188,9 +1188,9 @@ "section": "def-server.ApmException", "text": "ApmException" }, - "[] | undefined; 'error.grouping_name'?: string | undefined; 'error.grouping_key'?: string | undefined; 'host.name'?: string | undefined; 'host.hostname'?: string | undefined; 'kubernetes.pod.uid'?: string | undefined; 'kubernetes.pod.name'?: string | undefined; observer?: ", + "[] | undefined; 'error.grouping_name'?: string | undefined; 'error.grouping_key'?: string | undefined; 'host.name'?: string | undefined; 'host.hostname'?: string | undefined; 'http.request.method'?: string | undefined; 'http.response.status_code'?: number | undefined; 'kubernetes.pod.uid'?: string | undefined; 'kubernetes.pod.name'?: string | undefined; observer?: ", "Observer", - " | undefined; 'parent.id'?: string | undefined; 'processor.event'?: string | undefined; 'processor.name'?: string | undefined; 'trace.id'?: string | undefined; 'transaction.name'?: string | undefined; 'transaction.type'?: string | undefined; 'transaction.id'?: string | undefined; 'transaction.duration.us'?: number | undefined; 'transaction.duration.histogram'?: { values: number[]; counts: number[]; } | undefined; 'transaction.sampled'?: true | undefined; 'service.name'?: string | undefined; 'service.version'?: string | undefined; 'service.environment'?: string | undefined; 'service.node.name'?: string | undefined; 'service.runtime.name'?: string | undefined; 'service.runtime.version'?: string | undefined; 'service.framework.name'?: string | undefined; 'service.target.name'?: string | undefined; 'service.target.type'?: string | undefined; 'span.id'?: string | undefined; 'span.name'?: string | undefined; 'span.type'?: string | undefined; 'span.subtype'?: string | undefined; 'span.duration.us'?: number | undefined; 'span.destination.service.name'?: string | undefined; 'span.destination.service.resource'?: string | undefined; 'span.destination.service.type'?: string | undefined; 'span.self_time.count'?: number | undefined; 'span.self_time.sum.us'?: number | undefined; 'span.links'?: { trace: { id: string; }; span: { id: string; }; }[] | undefined; 'cloud.provider'?: string | undefined; 'cloud.project.name'?: string | undefined; 'cloud.service.name'?: string | undefined; 'cloud.availability_zone'?: string | undefined; 'cloud.machine.type'?: string | undefined; 'cloud.region'?: string | undefined; 'host.os.platform'?: string | undefined; 'faas.id'?: string | undefined; 'faas.name'?: string | undefined; 'faas.coldstart'?: boolean | undefined; 'faas.execution'?: string | undefined; 'faas.trigger.type'?: string | undefined; 'faas.trigger.request_id'?: string | undefined; 'system.process.memory.size'?: number | undefined; 'system.memory.actual.free'?: number | undefined; 'system.memory.total'?: number | undefined; 'system.cpu.total.norm.pct'?: number | undefined; 'system.process.memory.rss.bytes'?: number | undefined; 'system.process.cpu.total.norm.pct'?: number | undefined; 'jvm.memory.heap.used'?: number | undefined; 'jvm.memory.non_heap.used'?: number | undefined; 'jvm.thread.count'?: number | undefined; 'faas.billed_duration'?: number | undefined; 'faas.timeout'?: number | undefined; 'faas.coldstart_duration'?: number | undefined; 'faas.duration'?: number | undefined; }[]" + " | undefined; 'parent.id'?: string | undefined; 'processor.event'?: string | undefined; 'processor.name'?: string | undefined; 'trace.id'?: string | undefined; 'transaction.name'?: string | undefined; 'transaction.type'?: string | undefined; 'transaction.id'?: string | undefined; 'transaction.duration.us'?: number | undefined; 'transaction.duration.histogram'?: { values: number[]; counts: number[]; } | undefined; 'transaction.sampled'?: true | undefined; 'service.name'?: string | undefined; 'service.version'?: string | undefined; 'service.environment'?: string | undefined; 'service.node.name'?: string | undefined; 'service.runtime.name'?: string | undefined; 'service.runtime.version'?: string | undefined; 'service.framework.name'?: string | undefined; 'service.target.name'?: string | undefined; 'service.target.type'?: string | undefined; 'span.action'?: string | undefined; 'span.id'?: string | undefined; 'span.name'?: string | undefined; 'span.type'?: string | undefined; 'span.subtype'?: string | undefined; 'span.duration.us'?: number | undefined; 'span.destination.service.resource'?: string | undefined; 'span.self_time.count'?: number | undefined; 'span.self_time.sum.us'?: number | undefined; 'span.links'?: { trace: { id: string; }; span: { id: string; }; }[] | undefined; 'cloud.provider'?: string | undefined; 'cloud.project.name'?: string | undefined; 'cloud.service.name'?: string | undefined; 'cloud.availability_zone'?: string | undefined; 'cloud.machine.type'?: string | undefined; 'cloud.region'?: string | undefined; 'host.os.platform'?: string | undefined; 'faas.id'?: string | undefined; 'faas.name'?: string | undefined; 'faas.coldstart'?: boolean | undefined; 'faas.execution'?: string | undefined; 'faas.trigger.type'?: string | undefined; 'faas.trigger.request_id'?: string | undefined; 'system.process.memory.size'?: number | undefined; 'system.memory.actual.free'?: number | undefined; 'system.memory.total'?: number | undefined; 'system.cpu.total.norm.pct'?: number | undefined; 'system.process.memory.rss.bytes'?: number | undefined; 'system.process.cpu.total.norm.pct'?: number | undefined; 'jvm.memory.heap.used'?: number | undefined; 'jvm.memory.non_heap.used'?: number | undefined; 'jvm.thread.count'?: number | undefined; 'faas.billed_duration'?: number | undefined; 'faas.timeout'?: number | undefined; 'faas.coldstart_duration'?: number | undefined; 'faas.duration'?: number | undefined; }[]" ], "path": "packages/kbn-apm-synthtrace/src/lib/apm/index.ts", "deprecated": false, diff --git a/api_docs/kbn_apm_synthtrace.mdx b/api_docs/kbn_apm_synthtrace.mdx index 44d2e38a95375..9844cf32d84aa 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-10 +date: 2022-10-16 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 e96342c7ce840..a85dd257691ed 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-10 +date: 2022-10-16 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 3abeee268d46e..70471dd9e2f33 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-10 +date: 2022-10-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/axe-config'] --- import kbnAxeConfigObj from './kbn_axe_config.devdocs.json'; diff --git a/api_docs/kbn_cases_components.devdocs.json b/api_docs/kbn_cases_components.devdocs.json new file mode 100644 index 0000000000000..77285328875af --- /dev/null +++ b/api_docs/kbn_cases_components.devdocs.json @@ -0,0 +1,90 @@ +{ + "id": "@kbn/cases-components", + "client": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "server": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "common": { + "classes": [], + "functions": [ + { + "parentPluginId": "@kbn/cases-components", + "id": "def-common.getStatusConfiguration", + "type": "Function", + "tags": [], + "label": "getStatusConfiguration", + "description": [], + "signature": [ + "() => { open: { color: string; label: string; icon: \"folderOpen\"; }; \"in-progress\": { color: string; label: string; icon: \"folderExclamation\"; }; closed: { color: string; label: string; icon: \"folderCheck\"; }; }" + ], + "path": "packages/kbn-cases-components/src/status/config.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/cases-components", + "id": "def-common.Status", + "type": "Function", + "tags": [], + "label": "Status", + "description": [], + "signature": [ + "React.NamedExoticComponent" + ], + "path": "packages/kbn-cases-components/src/status/status.tsx", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "@kbn/cases-components", + "id": "def-common.Status.$1", + "type": "Uncategorized", + "tags": [], + "label": "props", + "description": [], + "signature": [ + "P" + ], + "path": "node_modules/@types/react/index.d.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + } + ], + "interfaces": [], + "enums": [ + { + "parentPluginId": "@kbn/cases-components", + "id": "def-common.CaseStatuses", + "type": "Enum", + "tags": [], + "label": "CaseStatuses", + "description": [], + "path": "packages/kbn-cases-components/src/status/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + } + ], + "misc": [], + "objects": [] + } +} \ No newline at end of file diff --git a/api_docs/kbn_cases_components.mdx b/api_docs/kbn_cases_components.mdx new file mode 100644 index 0000000000000..f188870df8c19 --- /dev/null +++ b/api_docs/kbn_cases_components.mdx @@ -0,0 +1,33 @@ +--- +#### +#### 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: kibKbnCasesComponentsPluginApi +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-16 +tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cases-components'] +--- +import kbnCasesComponentsObj from './kbn_cases_components.devdocs.json'; + + + +Contact [Owner missing] for questions regarding this plugin. + +**Code health stats** + +| Public API count | Any count | Items lacking comments | Missing exports | +|-------------------|-----------|------------------------|-----------------| +| 4 | 0 | 3 | 0 | + +## Common + +### Functions + + +### Enums + + diff --git a/api_docs/kbn_chart_icons.mdx b/api_docs/kbn_chart_icons.mdx index 45276f22d3586..efc09b5274f19 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-10 +date: 2022-10-16 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 cd266cfa11bcd..350dadd335149 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-10 +date: 2022-10-16 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 a975d89c203cc..9e2a3f5cddaca 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-10 +date: 2022-10-16 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 254af0805e3cf..271ea175dfb8e 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-10 +date: 2022-10-16 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 2639fcb9a105a..84050c92e098b 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-10 +date: 2022-10-16 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 ae700c05f3647..89a527fd46efa 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-10 +date: 2022-10-16 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 ffebb3323e821..bcbf4e4dd13bd 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-10 +date: 2022-10-16 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 177cc1d2c88f5..0f819cb64b7b6 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-10 +date: 2022-10-16 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 668d543ce208e..0d03a469bbde1 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-10 +date: 2022-10-16 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 8ec280432b055..8bd6cdc311c29 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-10 +date: 2022-10-16 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 18c7af5ca7546..fb1ee32ae2d22 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-10 +date: 2022-10-16 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 6a584f10cc266..3ab7d56eeefcb 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-10 +date: 2022-10-16 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 56ae80db62968..eb5801f37ba93 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-10 +date: 2022-10-16 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 ae1bff84123b5..fced027326d9e 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-10 +date: 2022-10-16 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 206cc86999bb5..50a616a033641 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-10 +date: 2022-10-16 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 10f93de93e697..85ad4d96f9176 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-10 +date: 2022-10-16 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 2220baea064f8..0ddd4164d975c 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-10 +date: 2022-10-16 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 2451c9adfa293..b0170cbfa825d 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-10 +date: 2022-10-16 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 6dffd3fe3eab0..f0766d8025053 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-10 +date: 2022-10-16 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 374a205d6d7eb..3c130f261079f 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-10 +date: 2022-10-16 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 d77d53ffa1912..cc16fd056c348 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-10 +date: 2022-10-16 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 a0adf2433ba90..e752d5755d0cc 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-10 +date: 2022-10-16 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 ff353e7206588..96b4dc4fbc2a8 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-10 +date: 2022-10-16 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 b1482ac80cfc8..028ba280ec370 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-10 +date: 2022-10-16 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 3052f18231f88..1e238df837afa 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-10 +date: 2022-10-16 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 a374fa4b72bfd..1dce4a9f22db0 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-10 +date: 2022-10-16 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 1452d1eca68de..b3331e6ada2f8 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-10 +date: 2022-10-16 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 2fa1a2398f3c7..16e2210ff0212 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-10 +date: 2022-10-16 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 58247b909688c..a45692f11eb88 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-10 +date: 2022-10-16 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 0c2303c8d7b49..5347c5aa1bd46 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-10 +date: 2022-10-16 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 acbec545278f5..fdd586372f115 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-10 +date: 2022-10-16 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 6b49aeb6ad2db..b38156152f642 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-10 +date: 2022-10-16 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 758606f2c966f..070c885b34966 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-10 +date: 2022-10-16 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 8ef722c82ebb5..886ee4fb6456d 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-10 +date: 2022-10-16 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 75bee5daa99f5..466e8de6ecd16 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-10 +date: 2022-10-16 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 ff88c65e59c67..c5c92944473b0 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-10 +date: 2022-10-16 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 a64b529d30a99..cf2720501a921 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-10 +date: 2022-10-16 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 cf83c7e9bf2fa..d913c0936a8e9 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-10 +date: 2022-10-16 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 7786d5b668cf5..9e9b0882b654e 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-10 +date: 2022-10-16 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 403da6112f339..876362556fb1b 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-10 +date: 2022-10-16 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 1f6219d03955c..bcade72bc8344 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-10 +date: 2022-10-16 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 b28f3f07c9703..24f5ffd633441 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-10 +date: 2022-10-16 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 2aae17b574f69..74e70c351ec44 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-10 +date: 2022-10-16 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 d646839a1a1cc..37daee4930c25 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-10 +date: 2022-10-16 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 bbc274c925599..c1fe0986c30d2 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-10 +date: 2022-10-16 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.devdocs.json b/api_docs/kbn_core_elasticsearch_client_server_mocks.devdocs.json index dc17ba9d371c0..4a5e46fda1b9f 100644 --- a/api_docs/kbn_core_elasticsearch_client_server_mocks.devdocs.json +++ b/api_docs/kbn_core_elasticsearch_client_server_mocks.devdocs.json @@ -412,7 +412,7 @@ "UpdateRequest", ", options?: ", "TransportRequestOptions", - " | undefined]>; [kInternal]: symbol | null; [kAsyncSearch]: symbol | null; [kAutoscaling]: symbol | null; [kCat]: symbol | null; [kCcr]: symbol | null; [kCluster]: symbol | null; [kDanglingIndices]: symbol | null; [kEnrich]: symbol | null; [kEql]: symbol | null; [kFeatures]: symbol | null; [kFleet]: symbol | null; [kGraph]: symbol | null; [kIlm]: symbol | null; [kIndices]: symbol | null; [kIngest]: symbol | null; [kLicense]: symbol | null; [kLogstash]: symbol | null; [kMigration]: symbol | null; [kMl]: symbol | null; [kMonitoring]: symbol | null; [kNodes]: symbol | null; [kRollup]: symbol | null; [kSearchableSnapshots]: symbol | null; [kSecurity]: symbol | null; [kShutdown]: symbol | null; [kSlm]: symbol | null; [kSnapshot]: symbol | null; [kSql]: symbol | null; [kSsl]: symbol | null; [kTasks]: symbol | null; [kTextStructure]: symbol | null; [kTransform]: symbol | null; [kWatcher]: symbol | null; [kXpack]: symbol | null; transport: ", + " | undefined]>; asyncSearch: ", { "pluginId": "@kbn/core-elasticsearch-client-server-mocks", "scope": "server", @@ -422,7 +422,7 @@ }, "<", "default", - ">; helpers: ", + ">; [kInternal]: symbol | null; [kAsyncSearch]: symbol | null; [kAutoscaling]: symbol | null; [kCat]: symbol | null; [kCcr]: symbol | null; [kCluster]: symbol | null; [kDanglingIndices]: symbol | null; [kEnrich]: symbol | null; [kEql]: symbol | null; [kFeatures]: symbol | null; [kFleet]: symbol | null; [kGraph]: symbol | null; [kIlm]: symbol | null; [kIndices]: symbol | null; [kIngest]: symbol | null; [kLicense]: symbol | null; [kLogstash]: symbol | null; [kMigration]: symbol | null; [kMl]: symbol | null; [kMonitoring]: symbol | null; [kNodes]: symbol | null; [kRollup]: symbol | null; [kSearchableSnapshots]: symbol | null; [kSecurity]: symbol | null; [kShutdown]: symbol | null; [kSlm]: symbol | null; [kSnapshot]: symbol | null; [kSql]: symbol | null; [kSsl]: symbol | null; [kTasks]: symbol | null; [kTextStructure]: symbol | null; [kTransform]: symbol | null; [kWatcher]: symbol | null; [kXpack]: symbol | null; transport: ", { "pluginId": "@kbn/core-elasticsearch-client-server-mocks", "scope": "server", @@ -432,29 +432,29 @@ }, "<", "default", - ">; child: ", + ">; helpers: ", { "pluginId": "@kbn/core-elasticsearch-client-server-mocks", "scope": "server", "docId": "kibKbnCoreElasticsearchClientServerMocksPluginApi", - "section": "def-server.ClientApiMockInstance", - "text": "ClientApiMockInstance" + "section": "def-server.DeeplyMockedApi", + "text": "DeeplyMockedApi" }, "<", "default", - ", [opts: ", - "ClientOptions", - "]>; Internal: ", + ">; child: ", { "pluginId": "@kbn/core-elasticsearch-client-server-mocks", "scope": "server", "docId": "kibKbnCoreElasticsearchClientServerMocksPluginApi", - "section": "def-server.DeeplyMockedApi", - "text": "DeeplyMockedApi" + "section": "def-server.ClientApiMockInstance", + "text": "ClientApiMockInstance" }, "<", "default", - ">; asyncSearch: ", + ", [opts: ", + "ClientOptions", + "]>; Internal: ", { "pluginId": "@kbn/core-elasticsearch-client-server-mocks", "scope": "server", @@ -1523,7 +1523,7 @@ "UpdateRequest", ", options?: ", "TransportRequestOptions", - " | undefined]>; [kInternal]: symbol | null; [kAsyncSearch]: symbol | null; [kAutoscaling]: symbol | null; [kCat]: symbol | null; [kCcr]: symbol | null; [kCluster]: symbol | null; [kDanglingIndices]: symbol | null; [kEnrich]: symbol | null; [kEql]: symbol | null; [kFeatures]: symbol | null; [kFleet]: symbol | null; [kGraph]: symbol | null; [kIlm]: symbol | null; [kIndices]: symbol | null; [kIngest]: symbol | null; [kLicense]: symbol | null; [kLogstash]: symbol | null; [kMigration]: symbol | null; [kMl]: symbol | null; [kMonitoring]: symbol | null; [kNodes]: symbol | null; [kRollup]: symbol | null; [kSearchableSnapshots]: symbol | null; [kSecurity]: symbol | null; [kShutdown]: symbol | null; [kSlm]: symbol | null; [kSnapshot]: symbol | null; [kSql]: symbol | null; [kSsl]: symbol | null; [kTasks]: symbol | null; [kTextStructure]: symbol | null; [kTransform]: symbol | null; [kWatcher]: symbol | null; [kXpack]: symbol | null; transport: ", + " | undefined]>; asyncSearch: ", { "pluginId": "@kbn/core-elasticsearch-client-server-mocks", "scope": "server", @@ -1533,7 +1533,7 @@ }, "<", "default", - ">; helpers: ", + ">; [kInternal]: symbol | null; [kAsyncSearch]: symbol | null; [kAutoscaling]: symbol | null; [kCat]: symbol | null; [kCcr]: symbol | null; [kCluster]: symbol | null; [kDanglingIndices]: symbol | null; [kEnrich]: symbol | null; [kEql]: symbol | null; [kFeatures]: symbol | null; [kFleet]: symbol | null; [kGraph]: symbol | null; [kIlm]: symbol | null; [kIndices]: symbol | null; [kIngest]: symbol | null; [kLicense]: symbol | null; [kLogstash]: symbol | null; [kMigration]: symbol | null; [kMl]: symbol | null; [kMonitoring]: symbol | null; [kNodes]: symbol | null; [kRollup]: symbol | null; [kSearchableSnapshots]: symbol | null; [kSecurity]: symbol | null; [kShutdown]: symbol | null; [kSlm]: symbol | null; [kSnapshot]: symbol | null; [kSql]: symbol | null; [kSsl]: symbol | null; [kTasks]: symbol | null; [kTextStructure]: symbol | null; [kTransform]: symbol | null; [kWatcher]: symbol | null; [kXpack]: symbol | null; transport: ", { "pluginId": "@kbn/core-elasticsearch-client-server-mocks", "scope": "server", @@ -1543,29 +1543,29 @@ }, "<", "default", - ">; child: ", + ">; helpers: ", { "pluginId": "@kbn/core-elasticsearch-client-server-mocks", "scope": "server", "docId": "kibKbnCoreElasticsearchClientServerMocksPluginApi", - "section": "def-server.ClientApiMockInstance", - "text": "ClientApiMockInstance" + "section": "def-server.DeeplyMockedApi", + "text": "DeeplyMockedApi" }, "<", "default", - ", [opts: ", - "ClientOptions", - "]>; Internal: ", + ">; child: ", { "pluginId": "@kbn/core-elasticsearch-client-server-mocks", "scope": "server", "docId": "kibKbnCoreElasticsearchClientServerMocksPluginApi", - "section": "def-server.DeeplyMockedApi", - "text": "DeeplyMockedApi" + "section": "def-server.ClientApiMockInstance", + "text": "ClientApiMockInstance" }, "<", "default", - ">; asyncSearch: ", + ", [opts: ", + "ClientOptions", + "]>; Internal: ", { "pluginId": "@kbn/core-elasticsearch-client-server-mocks", "scope": "server", @@ -2588,7 +2588,7 @@ "UpdateRequest", ", options?: ", "TransportRequestOptions", - " | undefined]>; [kInternal]: symbol | null; [kAsyncSearch]: symbol | null; [kAutoscaling]: symbol | null; [kCat]: symbol | null; [kCcr]: symbol | null; [kCluster]: symbol | null; [kDanglingIndices]: symbol | null; [kEnrich]: symbol | null; [kEql]: symbol | null; [kFeatures]: symbol | null; [kFleet]: symbol | null; [kGraph]: symbol | null; [kIlm]: symbol | null; [kIndices]: symbol | null; [kIngest]: symbol | null; [kLicense]: symbol | null; [kLogstash]: symbol | null; [kMigration]: symbol | null; [kMl]: symbol | null; [kMonitoring]: symbol | null; [kNodes]: symbol | null; [kRollup]: symbol | null; [kSearchableSnapshots]: symbol | null; [kSecurity]: symbol | null; [kShutdown]: symbol | null; [kSlm]: symbol | null; [kSnapshot]: symbol | null; [kSql]: symbol | null; [kSsl]: symbol | null; [kTasks]: symbol | null; [kTextStructure]: symbol | null; [kTransform]: symbol | null; [kWatcher]: symbol | null; [kXpack]: symbol | null; transport: ", + " | undefined]>; asyncSearch: ", { "pluginId": "@kbn/core-elasticsearch-client-server-mocks", "scope": "server", @@ -2598,7 +2598,7 @@ }, "<", "default", - ">; helpers: ", + ">; [kInternal]: symbol | null; [kAsyncSearch]: symbol | null; [kAutoscaling]: symbol | null; [kCat]: symbol | null; [kCcr]: symbol | null; [kCluster]: symbol | null; [kDanglingIndices]: symbol | null; [kEnrich]: symbol | null; [kEql]: symbol | null; [kFeatures]: symbol | null; [kFleet]: symbol | null; [kGraph]: symbol | null; [kIlm]: symbol | null; [kIndices]: symbol | null; [kIngest]: symbol | null; [kLicense]: symbol | null; [kLogstash]: symbol | null; [kMigration]: symbol | null; [kMl]: symbol | null; [kMonitoring]: symbol | null; [kNodes]: symbol | null; [kRollup]: symbol | null; [kSearchableSnapshots]: symbol | null; [kSecurity]: symbol | null; [kShutdown]: symbol | null; [kSlm]: symbol | null; [kSnapshot]: symbol | null; [kSql]: symbol | null; [kSsl]: symbol | null; [kTasks]: symbol | null; [kTextStructure]: symbol | null; [kTransform]: symbol | null; [kWatcher]: symbol | null; [kXpack]: symbol | null; transport: ", { "pluginId": "@kbn/core-elasticsearch-client-server-mocks", "scope": "server", @@ -2608,29 +2608,29 @@ }, "<", "default", - ">; child: ", + ">; helpers: ", { "pluginId": "@kbn/core-elasticsearch-client-server-mocks", "scope": "server", "docId": "kibKbnCoreElasticsearchClientServerMocksPluginApi", - "section": "def-server.ClientApiMockInstance", - "text": "ClientApiMockInstance" + "section": "def-server.DeeplyMockedApi", + "text": "DeeplyMockedApi" }, "<", "default", - ", [opts: ", - "ClientOptions", - "]>; Internal: ", + ">; child: ", { "pluginId": "@kbn/core-elasticsearch-client-server-mocks", "scope": "server", "docId": "kibKbnCoreElasticsearchClientServerMocksPluginApi", - "section": "def-server.DeeplyMockedApi", - "text": "DeeplyMockedApi" + "section": "def-server.ClientApiMockInstance", + "text": "ClientApiMockInstance" }, "<", "default", - ">; asyncSearch: ", + ", [opts: ", + "ClientOptions", + "]>; Internal: ", { "pluginId": "@kbn/core-elasticsearch-client-server-mocks", "scope": "server", @@ -3720,7 +3720,7 @@ "UpdateRequest", ", options?: ", "TransportRequestOptions", - " | undefined]>; [kInternal]: symbol | null; [kAsyncSearch]: symbol | null; [kAutoscaling]: symbol | null; [kCat]: symbol | null; [kCcr]: symbol | null; [kCluster]: symbol | null; [kDanglingIndices]: symbol | null; [kEnrich]: symbol | null; [kEql]: symbol | null; [kFeatures]: symbol | null; [kFleet]: symbol | null; [kGraph]: symbol | null; [kIlm]: symbol | null; [kIndices]: symbol | null; [kIngest]: symbol | null; [kLicense]: symbol | null; [kLogstash]: symbol | null; [kMigration]: symbol | null; [kMl]: symbol | null; [kMonitoring]: symbol | null; [kNodes]: symbol | null; [kRollup]: symbol | null; [kSearchableSnapshots]: symbol | null; [kSecurity]: symbol | null; [kShutdown]: symbol | null; [kSlm]: symbol | null; [kSnapshot]: symbol | null; [kSql]: symbol | null; [kSsl]: symbol | null; [kTasks]: symbol | null; [kTextStructure]: symbol | null; [kTransform]: symbol | null; [kWatcher]: symbol | null; [kXpack]: symbol | null; transport: ", + " | undefined]>; asyncSearch: ", { "pluginId": "@kbn/core-elasticsearch-client-server-mocks", "scope": "server", @@ -3730,7 +3730,7 @@ }, "<", "default", - ">; helpers: ", + ">; [kInternal]: symbol | null; [kAsyncSearch]: symbol | null; [kAutoscaling]: symbol | null; [kCat]: symbol | null; [kCcr]: symbol | null; [kCluster]: symbol | null; [kDanglingIndices]: symbol | null; [kEnrich]: symbol | null; [kEql]: symbol | null; [kFeatures]: symbol | null; [kFleet]: symbol | null; [kGraph]: symbol | null; [kIlm]: symbol | null; [kIndices]: symbol | null; [kIngest]: symbol | null; [kLicense]: symbol | null; [kLogstash]: symbol | null; [kMigration]: symbol | null; [kMl]: symbol | null; [kMonitoring]: symbol | null; [kNodes]: symbol | null; [kRollup]: symbol | null; [kSearchableSnapshots]: symbol | null; [kSecurity]: symbol | null; [kShutdown]: symbol | null; [kSlm]: symbol | null; [kSnapshot]: symbol | null; [kSql]: symbol | null; [kSsl]: symbol | null; [kTasks]: symbol | null; [kTextStructure]: symbol | null; [kTransform]: symbol | null; [kWatcher]: symbol | null; [kXpack]: symbol | null; transport: ", { "pluginId": "@kbn/core-elasticsearch-client-server-mocks", "scope": "server", @@ -3740,29 +3740,29 @@ }, "<", "default", - ">; child: ", + ">; helpers: ", { "pluginId": "@kbn/core-elasticsearch-client-server-mocks", "scope": "server", "docId": "kibKbnCoreElasticsearchClientServerMocksPluginApi", - "section": "def-server.ClientApiMockInstance", - "text": "ClientApiMockInstance" + "section": "def-server.DeeplyMockedApi", + "text": "DeeplyMockedApi" }, "<", "default", - ", [opts: ", - "ClientOptions", - "]>; Internal: ", + ">; child: ", { "pluginId": "@kbn/core-elasticsearch-client-server-mocks", "scope": "server", "docId": "kibKbnCoreElasticsearchClientServerMocksPluginApi", - "section": "def-server.DeeplyMockedApi", - "text": "DeeplyMockedApi" + "section": "def-server.ClientApiMockInstance", + "text": "ClientApiMockInstance" }, "<", "default", - ">; asyncSearch: ", + ", [opts: ", + "ClientOptions", + "]>; Internal: ", { "pluginId": "@kbn/core-elasticsearch-client-server-mocks", "scope": "server", diff --git a/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx b/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx index f13371eb32d33..c1e0a5405895c 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-10 +date: 2022-10-16 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.devdocs.json b/api_docs/kbn_core_elasticsearch_server.devdocs.json index a6bbfb7a58cb9..6137810e54074 100644 --- a/api_docs/kbn_core_elasticsearch_server.devdocs.json +++ b/api_docs/kbn_core_elasticsearch_server.devdocs.json @@ -64,6 +64,31 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "@kbn/core-elasticsearch-server", + "id": "def-server.ElasticsearchClientConfig.maxIdleSockets", + "type": "number", + "tags": [], + "label": "maxIdleSockets", + "description": [], + "path": "packages/core/elasticsearch/core-elasticsearch-server/src/client/client_config.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-elasticsearch-server", + "id": "def-server.ElasticsearchClientConfig.idleSocketTimeout", + "type": "Object", + "tags": [], + "label": "idleSocketTimeout", + "description": [], + "signature": [ + "moment.Duration" + ], + "path": "packages/core/elasticsearch/core-elasticsearch-server/src/client/client_config.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "@kbn/core-elasticsearch-server", "id": "def-server.ElasticsearchClientConfig.compression", @@ -1053,7 +1078,9 @@ "TransportRequestOptions", " | undefined): Promise<", "UpdateResponse", - ">; }; [kInternal]: symbol | null; [kAsyncSearch]: symbol | null; [kAutoscaling]: symbol | null; [kCat]: symbol | null; [kCcr]: symbol | null; [kCluster]: symbol | null; [kDanglingIndices]: symbol | null; [kEnrich]: symbol | null; [kEql]: symbol | null; [kFeatures]: symbol | null; [kFleet]: symbol | null; [kGraph]: symbol | null; [kIlm]: symbol | null; [kIndices]: symbol | null; [kIngest]: symbol | null; [kLicense]: symbol | null; [kLogstash]: symbol | null; [kMigration]: symbol | null; [kMl]: symbol | null; [kMonitoring]: symbol | null; [kNodes]: symbol | null; [kRollup]: symbol | null; [kSearchableSnapshots]: symbol | null; [kSecurity]: symbol | null; [kShutdown]: symbol | null; [kSlm]: symbol | null; [kSnapshot]: symbol | null; [kSql]: symbol | null; [kSsl]: symbol | null; [kTasks]: symbol | null; [kTextStructure]: symbol | null; [kTransform]: symbol | null; [kWatcher]: symbol | null; [kXpack]: symbol | null; transport: ", + ">; }; asyncSearch: ", + "default", + "; [kInternal]: symbol | null; [kAsyncSearch]: symbol | null; [kAutoscaling]: symbol | null; [kCat]: symbol | null; [kCcr]: symbol | null; [kCluster]: symbol | null; [kDanglingIndices]: symbol | null; [kEnrich]: symbol | null; [kEql]: symbol | null; [kFeatures]: symbol | null; [kFleet]: symbol | null; [kGraph]: symbol | null; [kIlm]: symbol | null; [kIndices]: symbol | null; [kIngest]: symbol | null; [kLicense]: symbol | null; [kLogstash]: symbol | null; [kMigration]: symbol | null; [kMl]: symbol | null; [kMonitoring]: symbol | null; [kNodes]: symbol | null; [kRollup]: symbol | null; [kSearchableSnapshots]: symbol | null; [kSecurity]: symbol | null; [kShutdown]: symbol | null; [kSlm]: symbol | null; [kSnapshot]: symbol | null; [kSql]: symbol | null; [kSsl]: symbol | null; [kTasks]: symbol | null; [kTextStructure]: symbol | null; [kTransform]: symbol | null; [kWatcher]: symbol | null; [kXpack]: symbol | null; transport: ", "default", "; helpers: ", "default", @@ -1063,8 +1090,6 @@ "default", "; Internal: ", "default", - "; asyncSearch: ", - "default", "; autoscaling: ", "default", "; bulk: { (this: That, params: ", @@ -2252,6 +2277,35 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "@kbn/core-elasticsearch-server", + "id": "def-server.IElasticsearchConfig.maxIdleSockets", + "type": "number", + "tags": [], + "label": "maxIdleSockets", + "description": [ + "\nThe maximum number of idle sockets to keep open between Kibana and Elasticsearch. If more sockets become idle, they will be closed." + ], + "path": "packages/core/elasticsearch/core-elasticsearch-server/src/elasticsearch_config.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-elasticsearch-server", + "id": "def-server.IElasticsearchConfig.idleSocketTimeout", + "type": "Object", + "tags": [], + "label": "idleSocketTimeout", + "description": [ + "\nThe timeout for idle sockets kept open between Kibana and Elasticsearch. If the socket is idle for longer than this timeout, it will be closed." + ], + "signature": [ + "moment.Duration" + ], + "path": "packages/core/elasticsearch/core-elasticsearch-server/src/elasticsearch_config.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "@kbn/core-elasticsearch-server", "id": "def-server.IElasticsearchConfig.compression", @@ -2669,7 +2723,9 @@ "TransportRequestOptions", " | undefined): Promise<", "UpdateResponse", - ">; }; [kInternal]: symbol | null; [kAsyncSearch]: symbol | null; [kAutoscaling]: symbol | null; [kCat]: symbol | null; [kCcr]: symbol | null; [kCluster]: symbol | null; [kDanglingIndices]: symbol | null; [kEnrich]: symbol | null; [kEql]: symbol | null; [kFeatures]: symbol | null; [kFleet]: symbol | null; [kGraph]: symbol | null; [kIlm]: symbol | null; [kIndices]: symbol | null; [kIngest]: symbol | null; [kLicense]: symbol | null; [kLogstash]: symbol | null; [kMigration]: symbol | null; [kMl]: symbol | null; [kMonitoring]: symbol | null; [kNodes]: symbol | null; [kRollup]: symbol | null; [kSearchableSnapshots]: symbol | null; [kSecurity]: symbol | null; [kShutdown]: symbol | null; [kSlm]: symbol | null; [kSnapshot]: symbol | null; [kSql]: symbol | null; [kSsl]: symbol | null; [kTasks]: symbol | null; [kTextStructure]: symbol | null; [kTransform]: symbol | null; [kWatcher]: symbol | null; [kXpack]: symbol | null; transport: ", + ">; }; asyncSearch: ", + "default", + "; [kInternal]: symbol | null; [kAsyncSearch]: symbol | null; [kAutoscaling]: symbol | null; [kCat]: symbol | null; [kCcr]: symbol | null; [kCluster]: symbol | null; [kDanglingIndices]: symbol | null; [kEnrich]: symbol | null; [kEql]: symbol | null; [kFeatures]: symbol | null; [kFleet]: symbol | null; [kGraph]: symbol | null; [kIlm]: symbol | null; [kIndices]: symbol | null; [kIngest]: symbol | null; [kLicense]: symbol | null; [kLogstash]: symbol | null; [kMigration]: symbol | null; [kMl]: symbol | null; [kMonitoring]: symbol | null; [kNodes]: symbol | null; [kRollup]: symbol | null; [kSearchableSnapshots]: symbol | null; [kSecurity]: symbol | null; [kShutdown]: symbol | null; [kSlm]: symbol | null; [kSnapshot]: symbol | null; [kSql]: symbol | null; [kSsl]: symbol | null; [kTasks]: symbol | null; [kTextStructure]: symbol | null; [kTransform]: symbol | null; [kWatcher]: symbol | null; [kXpack]: symbol | null; transport: ", "default", "; helpers: ", "default", @@ -2679,8 +2735,6 @@ "default", "; Internal: ", "default", - "; asyncSearch: ", - "default", "; autoscaling: ", "default", "; bulk: { (this: That, params: ", @@ -3873,7 +3927,9 @@ "TransportRequestOptions", " | undefined): Promise<", "UpdateResponse", - ">; }; [kInternal]: symbol | null; [kAsyncSearch]: symbol | null; [kAutoscaling]: symbol | null; [kCat]: symbol | null; [kCcr]: symbol | null; [kCluster]: symbol | null; [kDanglingIndices]: symbol | null; [kEnrich]: symbol | null; [kEql]: symbol | null; [kFeatures]: symbol | null; [kFleet]: symbol | null; [kGraph]: symbol | null; [kIlm]: symbol | null; [kIndices]: symbol | null; [kIngest]: symbol | null; [kLicense]: symbol | null; [kLogstash]: symbol | null; [kMigration]: symbol | null; [kMl]: symbol | null; [kMonitoring]: symbol | null; [kNodes]: symbol | null; [kRollup]: symbol | null; [kSearchableSnapshots]: symbol | null; [kSecurity]: symbol | null; [kShutdown]: symbol | null; [kSlm]: symbol | null; [kSnapshot]: symbol | null; [kSql]: symbol | null; [kSsl]: symbol | null; [kTasks]: symbol | null; [kTextStructure]: symbol | null; [kTransform]: symbol | null; [kWatcher]: symbol | null; [kXpack]: symbol | null; transport: ", + ">; }; asyncSearch: ", + "default", + "; [kInternal]: symbol | null; [kAsyncSearch]: symbol | null; [kAutoscaling]: symbol | null; [kCat]: symbol | null; [kCcr]: symbol | null; [kCluster]: symbol | null; [kDanglingIndices]: symbol | null; [kEnrich]: symbol | null; [kEql]: symbol | null; [kFeatures]: symbol | null; [kFleet]: symbol | null; [kGraph]: symbol | null; [kIlm]: symbol | null; [kIndices]: symbol | null; [kIngest]: symbol | null; [kLicense]: symbol | null; [kLogstash]: symbol | null; [kMigration]: symbol | null; [kMl]: symbol | null; [kMonitoring]: symbol | null; [kNodes]: symbol | null; [kRollup]: symbol | null; [kSearchableSnapshots]: symbol | null; [kSecurity]: symbol | null; [kShutdown]: symbol | null; [kSlm]: symbol | null; [kSnapshot]: symbol | null; [kSql]: symbol | null; [kSsl]: symbol | null; [kTasks]: symbol | null; [kTextStructure]: symbol | null; [kTransform]: symbol | null; [kWatcher]: symbol | null; [kXpack]: symbol | null; transport: ", "default", "; helpers: ", "default", @@ -3883,8 +3939,6 @@ "default", "; Internal: ", "default", - "; asyncSearch: ", - "default", "; autoscaling: ", "default", "; bulk: { (this: That, params: ", @@ -5324,7 +5378,9 @@ "TransportRequestOptions", " | undefined): Promise<", "UpdateResponse", - ">; }; [kInternal]: symbol | null; [kAsyncSearch]: symbol | null; [kAutoscaling]: symbol | null; [kCat]: symbol | null; [kCcr]: symbol | null; [kCluster]: symbol | null; [kDanglingIndices]: symbol | null; [kEnrich]: symbol | null; [kEql]: symbol | null; [kFeatures]: symbol | null; [kFleet]: symbol | null; [kGraph]: symbol | null; [kIlm]: symbol | null; [kIndices]: symbol | null; [kIngest]: symbol | null; [kLicense]: symbol | null; [kLogstash]: symbol | null; [kMigration]: symbol | null; [kMl]: symbol | null; [kMonitoring]: symbol | null; [kNodes]: symbol | null; [kRollup]: symbol | null; [kSearchableSnapshots]: symbol | null; [kSecurity]: symbol | null; [kShutdown]: symbol | null; [kSlm]: symbol | null; [kSnapshot]: symbol | null; [kSql]: symbol | null; [kSsl]: symbol | null; [kTasks]: symbol | null; [kTextStructure]: symbol | null; [kTransform]: symbol | null; [kWatcher]: symbol | null; [kXpack]: symbol | null; transport: ", + ">; }; asyncSearch: ", + "default", + "; [kInternal]: symbol | null; [kAsyncSearch]: symbol | null; [kAutoscaling]: symbol | null; [kCat]: symbol | null; [kCcr]: symbol | null; [kCluster]: symbol | null; [kDanglingIndices]: symbol | null; [kEnrich]: symbol | null; [kEql]: symbol | null; [kFeatures]: symbol | null; [kFleet]: symbol | null; [kGraph]: symbol | null; [kIlm]: symbol | null; [kIndices]: symbol | null; [kIngest]: symbol | null; [kLicense]: symbol | null; [kLogstash]: symbol | null; [kMigration]: symbol | null; [kMl]: symbol | null; [kMonitoring]: symbol | null; [kNodes]: symbol | null; [kRollup]: symbol | null; [kSearchableSnapshots]: symbol | null; [kSecurity]: symbol | null; [kShutdown]: symbol | null; [kSlm]: symbol | null; [kSnapshot]: symbol | null; [kSql]: symbol | null; [kSsl]: symbol | null; [kTasks]: symbol | null; [kTextStructure]: symbol | null; [kTransform]: symbol | null; [kWatcher]: symbol | null; [kXpack]: symbol | null; transport: ", "default", "; helpers: ", "default", @@ -5334,8 +5390,6 @@ "default", "; Internal: ", "default", - "; asyncSearch: ", - "default", "; autoscaling: ", "default", "; bulk: { (this: That, params: ", diff --git a/api_docs/kbn_core_elasticsearch_server.mdx b/api_docs/kbn_core_elasticsearch_server.mdx index 9a166f9484d64..5109fa0859bee 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-10 +date: 2022-10-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-server'] --- import kbnCoreElasticsearchServerObj from './kbn_core_elasticsearch_server.devdocs.json'; @@ -21,7 +21,7 @@ Contact Kibana Core for questions regarding this plugin. | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 99 | 0 | 51 | 0 | +| 103 | 0 | 53 | 0 | ## Server diff --git a/api_docs/kbn_core_elasticsearch_server_internal.devdocs.json b/api_docs/kbn_core_elasticsearch_server_internal.devdocs.json index 248c3b356fa14..92b9cc5394746 100644 --- a/api_docs/kbn_core_elasticsearch_server_internal.devdocs.json +++ b/api_docs/kbn_core_elasticsearch_server_internal.devdocs.json @@ -216,7 +216,9 @@ "TransportRequestOptions", " | undefined): Promise<", "UpdateResponse", - ">; }; [kInternal]: symbol | null; [kAsyncSearch]: symbol | null; [kAutoscaling]: symbol | null; [kCat]: symbol | null; [kCcr]: symbol | null; [kCluster]: symbol | null; [kDanglingIndices]: symbol | null; [kEnrich]: symbol | null; [kEql]: symbol | null; [kFeatures]: symbol | null; [kFleet]: symbol | null; [kGraph]: symbol | null; [kIlm]: symbol | null; [kIndices]: symbol | null; [kIngest]: symbol | null; [kLicense]: symbol | null; [kLogstash]: symbol | null; [kMigration]: symbol | null; [kMl]: symbol | null; [kMonitoring]: symbol | null; [kNodes]: symbol | null; [kRollup]: symbol | null; [kSearchableSnapshots]: symbol | null; [kSecurity]: symbol | null; [kShutdown]: symbol | null; [kSlm]: symbol | null; [kSnapshot]: symbol | null; [kSql]: symbol | null; [kSsl]: symbol | null; [kTasks]: symbol | null; [kTextStructure]: symbol | null; [kTransform]: symbol | null; [kWatcher]: symbol | null; [kXpack]: symbol | null; transport: ", + ">; }; asyncSearch: ", + "default", + "; [kInternal]: symbol | null; [kAsyncSearch]: symbol | null; [kAutoscaling]: symbol | null; [kCat]: symbol | null; [kCcr]: symbol | null; [kCluster]: symbol | null; [kDanglingIndices]: symbol | null; [kEnrich]: symbol | null; [kEql]: symbol | null; [kFeatures]: symbol | null; [kFleet]: symbol | null; [kGraph]: symbol | null; [kIlm]: symbol | null; [kIndices]: symbol | null; [kIngest]: symbol | null; [kLicense]: symbol | null; [kLogstash]: symbol | null; [kMigration]: symbol | null; [kMl]: symbol | null; [kMonitoring]: symbol | null; [kNodes]: symbol | null; [kRollup]: symbol | null; [kSearchableSnapshots]: symbol | null; [kSecurity]: symbol | null; [kShutdown]: symbol | null; [kSlm]: symbol | null; [kSnapshot]: symbol | null; [kSql]: symbol | null; [kSsl]: symbol | null; [kTasks]: symbol | null; [kTextStructure]: symbol | null; [kTransform]: symbol | null; [kWatcher]: symbol | null; [kXpack]: symbol | null; transport: ", "default", "; helpers: ", "default", @@ -226,8 +228,6 @@ "default", "; Internal: ", "default", - "; asyncSearch: ", - "default", "; autoscaling: ", "default", "; bulk: { (this: That, params: ", @@ -1799,7 +1799,9 @@ "TransportRequestOptions", " | undefined): Promise<", "UpdateResponse", - ">; }; [kInternal]: symbol | null; [kAsyncSearch]: symbol | null; [kAutoscaling]: symbol | null; [kCat]: symbol | null; [kCcr]: symbol | null; [kCluster]: symbol | null; [kDanglingIndices]: symbol | null; [kEnrich]: symbol | null; [kEql]: symbol | null; [kFeatures]: symbol | null; [kFleet]: symbol | null; [kGraph]: symbol | null; [kIlm]: symbol | null; [kIndices]: symbol | null; [kIngest]: symbol | null; [kLicense]: symbol | null; [kLogstash]: symbol | null; [kMigration]: symbol | null; [kMl]: symbol | null; [kMonitoring]: symbol | null; [kNodes]: symbol | null; [kRollup]: symbol | null; [kSearchableSnapshots]: symbol | null; [kSecurity]: symbol | null; [kShutdown]: symbol | null; [kSlm]: symbol | null; [kSnapshot]: symbol | null; [kSql]: symbol | null; [kSsl]: symbol | null; [kTasks]: symbol | null; [kTextStructure]: symbol | null; [kTransform]: symbol | null; [kWatcher]: symbol | null; [kXpack]: symbol | null; transport: ", + ">; }; asyncSearch: ", + "default", + "; [kInternal]: symbol | null; [kAsyncSearch]: symbol | null; [kAutoscaling]: symbol | null; [kCat]: symbol | null; [kCcr]: symbol | null; [kCluster]: symbol | null; [kDanglingIndices]: symbol | null; [kEnrich]: symbol | null; [kEql]: symbol | null; [kFeatures]: symbol | null; [kFleet]: symbol | null; [kGraph]: symbol | null; [kIlm]: symbol | null; [kIndices]: symbol | null; [kIngest]: symbol | null; [kLicense]: symbol | null; [kLogstash]: symbol | null; [kMigration]: symbol | null; [kMl]: symbol | null; [kMonitoring]: symbol | null; [kNodes]: symbol | null; [kRollup]: symbol | null; [kSearchableSnapshots]: symbol | null; [kSecurity]: symbol | null; [kShutdown]: symbol | null; [kSlm]: symbol | null; [kSnapshot]: symbol | null; [kSql]: symbol | null; [kSsl]: symbol | null; [kTasks]: symbol | null; [kTextStructure]: symbol | null; [kTransform]: symbol | null; [kWatcher]: symbol | null; [kXpack]: symbol | null; transport: ", "default", "; helpers: ", "default", @@ -1809,8 +1811,6 @@ "default", "; Internal: ", "default", - "; asyncSearch: ", - "default", "; autoscaling: ", "default", "; bulk: { (this: That, params: ", @@ -2884,7 +2884,7 @@ "label": "ElasticsearchConfigType", "description": [], "signature": [ - "{ readonly username?: string | undefined; readonly password?: string | undefined; readonly serviceAccountToken?: string | undefined; readonly requestTimeout: moment.Duration; readonly compression: boolean; readonly ssl: Readonly<{ key?: string | undefined; certificateAuthorities?: string | string[] | undefined; certificate?: string | undefined; keyPassphrase?: string | undefined; } & { verificationMode: \"none\" | \"full\" | \"certificate\"; keystore: Readonly<{ path?: string | undefined; password?: string | undefined; } & {}>; truststore: Readonly<{ path?: string | undefined; password?: string | undefined; } & {}>; alwaysPresentCertificate: boolean; }>; readonly healthCheck: Readonly<{} & { delay: moment.Duration; }>; readonly customHeaders: Record; readonly hosts: string | string[]; readonly sniffOnStart: boolean; readonly sniffInterval: false | moment.Duration; readonly sniffOnConnectionFault: boolean; readonly maxSockets: number; readonly requestHeadersWhitelist: string | string[]; readonly shardTimeout: moment.Duration; readonly pingTimeout: moment.Duration; readonly logQueries: boolean; readonly apiVersion: string; readonly ignoreVersionMismatch: boolean; readonly skipStartupConnectionCheck: boolean; }" + "{ readonly username?: string | undefined; readonly password?: string | undefined; readonly serviceAccountToken?: string | undefined; readonly requestTimeout: moment.Duration; readonly compression: boolean; readonly ssl: Readonly<{ key?: string | undefined; certificateAuthorities?: string | string[] | undefined; certificate?: string | undefined; keyPassphrase?: string | undefined; } & { verificationMode: \"none\" | \"full\" | \"certificate\"; keystore: Readonly<{ path?: string | undefined; password?: string | undefined; } & {}>; truststore: Readonly<{ path?: string | undefined; password?: string | undefined; } & {}>; alwaysPresentCertificate: boolean; }>; readonly healthCheck: Readonly<{} & { delay: moment.Duration; }>; readonly customHeaders: Record; readonly hosts: string | string[]; readonly sniffOnStart: boolean; readonly sniffInterval: false | moment.Duration; readonly sniffOnConnectionFault: boolean; readonly maxSockets: number; readonly maxIdleSockets: number; readonly idleSocketTimeout: moment.Duration; readonly requestHeadersWhitelist: string | string[]; readonly shardTimeout: moment.Duration; readonly pingTimeout: moment.Duration; readonly logQueries: boolean; readonly apiVersion: string; readonly ignoreVersionMismatch: boolean; readonly skipStartupConnectionCheck: boolean; }" ], "path": "packages/core/elasticsearch/core-elasticsearch-server-internal/src/elasticsearch_config.ts", "deprecated": false, @@ -2914,7 +2914,11 @@ "Type", "; maxSockets: ", "Type", - "; compression: ", + "; maxIdleSockets: ", + "Type", + "; idleSocketTimeout: ", + "Type", + "; compression: ", "Type", "; username: ", "Type", diff --git a/api_docs/kbn_core_elasticsearch_server_internal.mdx b/api_docs/kbn_core_elasticsearch_server_internal.mdx index b7f7ae66ec615..cdbf0e965e38e 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-10 +date: 2022-10-16 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 7651de084b9a9..72ac95a61402b 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-10 +date: 2022-10-16 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 61c1ac3f1ac5f..5d66896e6c31f 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-10 +date: 2022-10-16 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 49ddcada894e4..ad1db0949f15e 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-10 +date: 2022-10-16 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 03a2cd43f9145..2a3ca40a0f228 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-10 +date: 2022-10-16 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 411798fcb340e..9dcd49635e9d6 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-10 +date: 2022-10-16 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 380ab162b9c61..a5bf57ec6dc0b 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-10 +date: 2022-10-16 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 fb62ecaef4a4c..4f1f21caf2486 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-10 +date: 2022-10-16 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 45029383a8e06..ac9951443a2f6 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-10 +date: 2022-10-16 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 c8de0fc49cd9e..faa5e4b01da0b 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-10 +date: 2022-10-16 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 41b4cdf396fab..58b2c220b58e7 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-10 +date: 2022-10-16 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 b0aebe4d000fb..ef0237e41ce01 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-10 +date: 2022-10-16 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 b09cce2f10598..a44d55f32d9d8 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-10 +date: 2022-10-16 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 2d5738cf8ed25..32d204e8c0375 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-10 +date: 2022-10-16 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 a5986b8db688b..7c3eb60ebaee1 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-10 +date: 2022-10-16 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 ec1bafeee45e2..776cf5d9deb90 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-10 +date: 2022-10-16 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 7b60c4634ffa5..28c13c76e3065 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-10 +date: 2022-10-16 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 acbda3533b883..1f17d4cdcff21 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-10 +date: 2022-10-16 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 533d1af83814c..6948bb7fdcbec 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-10 +date: 2022-10-16 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 d7c3c5d569dd4..21890b66bfb99 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-10 +date: 2022-10-16 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 100517bf79a77..9047b6ad0d644 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-10 +date: 2022-10-16 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 a7ccc3b652e73..299a4209754ff 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-10 +date: 2022-10-16 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 19c25e8b0395b..ba5ab02e7256f 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-10 +date: 2022-10-16 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 414aad8ed5b84..23201c4e70fd6 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-10 +date: 2022-10-16 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 8b9c843e68fcd..f77d9aa63145b 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-10 +date: 2022-10-16 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 abe1586bedf14..57b6075cc9680 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-10 +date: 2022-10-16 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 05a8f02808490..43f3f92fb6054 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-10 +date: 2022-10-16 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 4db46422eeffe..4eb2ee49ea907 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-10 +date: 2022-10-16 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 77771a9c4e01f..530c07ceb0f73 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-10 +date: 2022-10-16 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 102e9d27d27dc..798f24ffcb301 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-10 +date: 2022-10-16 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 ce3c5558f9386..aec1c1500ef3b 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-10 +date: 2022-10-16 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 346b9f5a1a97e..e9e5226d61ed0 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-10 +date: 2022-10-16 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 dc28aa0d05f95..87c3468c7b838 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-10 +date: 2022-10-16 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 f17c613a29524..74b0e1a46070e 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-10 +date: 2022-10-16 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 e9103d35d715e..f946ab84de190 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-10 +date: 2022-10-16 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 86bc7cd276cb0..8216aac785de3 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-10 +date: 2022-10-16 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 e8d18ffa85999..3b913a8c9bfac 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-10 +date: 2022-10-16 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 2da058044c31d..cd2f5abc6b193 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-10 +date: 2022-10-16 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 0fd6658b66ccf..c03e61cda88a3 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-10 +date: 2022-10-16 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 5ea9405ce0bdf..a929378405925 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-10 +date: 2022-10-16 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 b33d09367059e..a882d087ac51a 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-10 +date: 2022-10-16 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 b6588e68f0ad7..420eee41e1907 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-10 +date: 2022-10-16 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 9f08d7e3befda..f5bb4da7e98fe 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-10 +date: 2022-10-16 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 e8eb390e07292..856e6d7647332 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-10 +date: 2022-10-16 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 16403bb05f5a0..20117f6797391 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-10 +date: 2022-10-16 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 3da8129abb0ab..5463a341a455e 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-10 +date: 2022-10-16 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 cee2a79f8fac6..a9c2cfd6e7890 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-10 +date: 2022-10-16 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 ae1b4654b8e87..13f621bb7a354 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-10 +date: 2022-10-16 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 83c7283e11de1..3a9f6bbcd4c7a 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-10 +date: 2022-10-16 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 9ae964ddb4e34..5f4f513112113 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-10 +date: 2022-10-16 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 8e7ad4d161b99..7b7171092992d 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-10 +date: 2022-10-16 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 474f6ab09bdac..13cd689382571 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-10 +date: 2022-10-16 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 e1bd6b5ef59e3..49c1c292b3ab1 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-10 +date: 2022-10-16 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 d07f78ffb9d56..3dc513465b96f 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-10 +date: 2022-10-16 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 656ab7187bbaa..68be3765fa5af 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-10 +date: 2022-10-16 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 dec4f69c482e2..0f93b6c22a167 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-10 +date: 2022-10-16 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 a2418521db9c7..cbe55ffdc0b70 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-10 +date: 2022-10-16 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 676f282449efe..c4729d36aeff3 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-10 +date: 2022-10-16 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 9aad3e0b93103..480f6eb5787ee 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-10 +date: 2022-10-16 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 39c0978cc6d07..ed51d331587c5 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-10 +date: 2022-10-16 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 41988c7f87ccf..97892fd25a820 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-10 +date: 2022-10-16 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 b666f07c63691..bf2ad9d05669b 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-10 +date: 2022-10-16 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 9d385203d5418..aaff0cb6e63bc 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-10 +date: 2022-10-16 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 c373b57c1273b..68113f52a7847 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-10 +date: 2022-10-16 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 cff107daa7111..0842906e0b4fe 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-10 +date: 2022-10-16 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 4890a7483790b..9e65c03477bf9 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-10 +date: 2022-10-16 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 e76ae1fd05bb1..f63bbabd64825 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-10 +date: 2022-10-16 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 2f47670abdfec..de60d91c83d62 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-10 +date: 2022-10-16 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 7415fc8f24013..9bc34e703718d 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-10 +date: 2022-10-16 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 e72c29db35935..d669901d916c0 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-10 +date: 2022-10-16 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 16a8f9bb1f80c..999560e8991fd 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-10 +date: 2022-10-16 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 58f98e15e9203..2147de7aaab88 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-10 +date: 2022-10-16 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 fcf15987f1274..e390197fe0c94 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-10 +date: 2022-10-16 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 326c1611c791a..cd71166ca4821 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-10 +date: 2022-10-16 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 07756a85c7175..53449b00c0d37 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-10 +date: 2022-10-16 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.devdocs.json b/api_docs/kbn_core_saved_objects_migration_server_internal.devdocs.json index 3e01e7bbd7649..ac1eddca54b9b 100644 --- a/api_docs/kbn_core_saved_objects_migration_server_internal.devdocs.json +++ b/api_docs/kbn_core_saved_objects_migration_server_internal.devdocs.json @@ -1927,7 +1927,9 @@ "TransportRequestOptions", " | undefined): Promise<", "UpdateResponse", - ">; }; [kInternal]: symbol | null; [kAsyncSearch]: symbol | null; [kAutoscaling]: symbol | null; [kCat]: symbol | null; [kCcr]: symbol | null; [kCluster]: symbol | null; [kDanglingIndices]: symbol | null; [kEnrich]: symbol | null; [kEql]: symbol | null; [kFeatures]: symbol | null; [kFleet]: symbol | null; [kGraph]: symbol | null; [kIlm]: symbol | null; [kIndices]: symbol | null; [kIngest]: symbol | null; [kLicense]: symbol | null; [kLogstash]: symbol | null; [kMigration]: symbol | null; [kMl]: symbol | null; [kMonitoring]: symbol | null; [kNodes]: symbol | null; [kRollup]: symbol | null; [kSearchableSnapshots]: symbol | null; [kSecurity]: symbol | null; [kShutdown]: symbol | null; [kSlm]: symbol | null; [kSnapshot]: symbol | null; [kSql]: symbol | null; [kSsl]: symbol | null; [kTasks]: symbol | null; [kTextStructure]: symbol | null; [kTransform]: symbol | null; [kWatcher]: symbol | null; [kXpack]: symbol | null; transport: ", + ">; }; asyncSearch: ", + "default", + "; [kInternal]: symbol | null; [kAsyncSearch]: symbol | null; [kAutoscaling]: symbol | null; [kCat]: symbol | null; [kCcr]: symbol | null; [kCluster]: symbol | null; [kDanglingIndices]: symbol | null; [kEnrich]: symbol | null; [kEql]: symbol | null; [kFeatures]: symbol | null; [kFleet]: symbol | null; [kGraph]: symbol | null; [kIlm]: symbol | null; [kIndices]: symbol | null; [kIngest]: symbol | null; [kLicense]: symbol | null; [kLogstash]: symbol | null; [kMigration]: symbol | null; [kMl]: symbol | null; [kMonitoring]: symbol | null; [kNodes]: symbol | null; [kRollup]: symbol | null; [kSearchableSnapshots]: symbol | null; [kSecurity]: symbol | null; [kShutdown]: symbol | null; [kSlm]: symbol | null; [kSnapshot]: symbol | null; [kSql]: symbol | null; [kSsl]: symbol | null; [kTasks]: symbol | null; [kTextStructure]: symbol | null; [kTransform]: symbol | null; [kWatcher]: symbol | null; [kXpack]: symbol | null; transport: ", "default", "; helpers: ", "default", @@ -1937,8 +1939,6 @@ "default", "; Internal: ", "default", - "; asyncSearch: ", - "default", "; autoscaling: ", "default", "; bulk: { (this: That, params: ", 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 10230a6232201..b455d10f95716 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-10 +date: 2022-10-16 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 536a73abac4a7..41431902fc88c 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-10 +date: 2022-10-16 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 0b8e044f0b574..a38c756458ced 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-10 +date: 2022-10-16 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 74fbe52d0069c..f3e89a552398f 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-10 +date: 2022-10-16 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 d266a38b89a25..ecb240fa09b28 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-10 +date: 2022-10-16 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 ebd8bbf47dc93..3dfd9bb24c689 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-10 +date: 2022-10-16 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 223043281e54a..ac64ac5ee71d3 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-10 +date: 2022-10-16 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 639c80dd16184..8e99d9f2e9ccc 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-10 +date: 2022-10-16 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 4abe99291214a..2456f540fb7bb 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-10 +date: 2022-10-16 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 88d04e4eeea0b..557de5e75e7b4 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-10 +date: 2022-10-16 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 5a3230d00fcbc..a3de5fe9d39b4 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-10 +date: 2022-10-16 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 d42b15ff5b04b..fe3e18df2e0c5 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-10 +date: 2022-10-16 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 60fd56639a01b..fa4c286387859 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-10 +date: 2022-10-16 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 1d26649f21f59..411903cb3f92b 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-10 +date: 2022-10-16 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 1b42667d99bb0..d52704b4e760c 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-10 +date: 2022-10-16 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 e69c72b770b7a..ddd27cfe2e540 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-10 +date: 2022-10-16 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 f3b5cbe8e0712..e032ce1b40433 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-10 +date: 2022-10-16 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 f7428dc798396..80ed2cf079b03 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-10 +date: 2022-10-16 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 3489c2c081f45..ec3f56ec55fe9 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-10 +date: 2022-10-16 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 8f8093426e22e..fbc2a7cc93ef2 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-10 +date: 2022-10-16 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 c91d9beb9d48f..7965e17cf47b0 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-10 +date: 2022-10-16 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 634a41ec1fe52..34c6dae8d01d7 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-10 +date: 2022-10-16 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 04d3804c3387a..d08626c1d2395 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-10 +date: 2022-10-16 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 e1878987d59e7..efaf2cda4a458 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-10 +date: 2022-10-16 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 8bac77409ac02..66e29b472407f 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-10 +date: 2022-10-16 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 3761c0054f0df..05948a22a8c5f 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-10 +date: 2022-10-16 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 c75090a9b6142..926dfff700791 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-10 +date: 2022-10-16 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 2b4f692045595..e6213c01a12f4 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-10 +date: 2022-10-16 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 7c8b276e834cc..67a58efafcace 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-10 +date: 2022-10-16 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 e0fd07d2de51a..81f4abb95bb89 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-10 +date: 2022-10-16 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 18d746039c14b..21d2c3fe1447e 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-10 +date: 2022-10-16 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 bcbe3e6f0708a..fb10a23bce0a2 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-10 +date: 2022-10-16 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 582d465be5a63..5a6bc9c992edf 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-10 +date: 2022-10-16 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 743a82b68b2e2..fe7d4097cbb05 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-10 +date: 2022-10-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-utils'] --- import kbnDevUtilsObj from './kbn_dev_utils.devdocs.json'; diff --git a/api_docs/kbn_doc_links.devdocs.json b/api_docs/kbn_doc_links.devdocs.json index fd01dbf8e5503..e656d78a1fef4 100644 --- a/api_docs/kbn_doc_links.devdocs.json +++ b/api_docs/kbn_doc_links.devdocs.json @@ -300,7 +300,7 @@ "label": "enterpriseSearch", "description": [], "signature": [ - "{ readonly apiKeys: string; readonly bulkApi: string; readonly configuration: string; readonly connectors: string; readonly connectorsMongoDB: string; readonly connectorsMySQL: string; readonly connectorsWorkplaceSearch: string; readonly contentExtraction: string; readonly crawlerGettingStarted: string; readonly crawlerManaging: string; readonly crawlerOverview: string; readonly deployTrainedModels: string; readonly documentLevelSecurity: string; readonly ingestPipelines: string; readonly languageAnalyzers: string; readonly languageClients: string; readonly licenseManagement: string; readonly mailService: string; readonly start: string; readonly troubleshootSetup: string; readonly usersAccess: string; }" + "{ readonly apiKeys: string; readonly bulkApi: string; readonly configuration: string; readonly connectors: string; readonly connectorsMongoDB: string; readonly connectorsMySQL: string; readonly connectorsWorkplaceSearch: string; readonly crawlerGettingStarted: string; readonly crawlerManaging: string; readonly crawlerOverview: string; readonly deployTrainedModels: string; readonly documentLevelSecurity: string; readonly ingestPipelines: string; readonly languageAnalyzers: string; readonly languageClients: string; readonly licenseManagement: string; readonly mailService: string; readonly start: string; readonly troubleshootSetup: string; readonly usersAccess: string; }" ], "path": "packages/kbn-doc-links/src/types.ts", "deprecated": false, @@ -546,7 +546,7 @@ "label": "securitySolution", "description": [], "signature": [ - "{ readonly trustedApps: string; readonly eventFilters: string; readonly blocklist: string; readonly endpointArtifacts: string; readonly policyResponseTroubleshooting: { full_disk_access: string; macos_system_ext: string; linux_deadlock: string; }; readonly packageActionTroubleshooting: { es_connection: string; }; readonly threatIntelInt: string; readonly responseActions: string; readonly configureEndpointIntegrationPolicy: string; }" + "{ readonly trustedApps: string; readonly eventFilters: string; readonly blocklist: string; readonly endpointArtifacts: string; readonly policyResponseTroubleshooting: { full_disk_access: string; macos_system_ext: string; linux_deadlock: string; }; readonly packageActionTroubleshooting: { es_connection: string; }; readonly threatIntelInt: string; readonly responseActions: string; readonly configureEndpointIntegrationPolicy: string; readonly exceptions: { value_lists: string; }; }" ], "path": "packages/kbn-doc-links/src/types.ts", "deprecated": false, diff --git a/api_docs/kbn_doc_links.mdx b/api_docs/kbn_doc_links.mdx index 5989572689e52..4568e3f0a6e89 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-10 +date: 2022-10-16 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 c95fc1e111f64..2ce598a48c40c 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-10 +date: 2022-10-16 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 177ceb72f72dc..62e66fad01094 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-10 +date: 2022-10-16 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 5dca8c1133830..e8efa11035641 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-10 +date: 2022-10-16 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 53ef00e7813c8..1c775ba9bc20d 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-10 +date: 2022-10-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-errors'] --- import kbnEsErrorsObj from './kbn_es_errors.devdocs.json'; diff --git a/api_docs/kbn_es_query.devdocs.json b/api_docs/kbn_es_query.devdocs.json index 3bd7db808950c..fafb95160c5b2 100644 --- a/api_docs/kbn_es_query.devdocs.json +++ b/api_docs/kbn_es_query.devdocs.json @@ -104,6 +104,47 @@ } ], "functions": [ + { + "parentPluginId": "@kbn/es-query", + "id": "def-common.buildCombinedFilter", + "type": "Function", + "tags": [], + "label": "buildCombinedFilter", + "description": [ + "\nBuilds an COMBINED filter. An COMBINED filter is a filter with multiple sub-filters. Each sub-filter (FilterItem) represents a\ncondition." + ], + "signature": [ + "(filters: ", + "FilterItem", + "[]) => ", + "CombinedFilter" + ], + "path": "packages/kbn-es-query/src/filters/build_filters/combined_filter.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/es-query", + "id": "def-common.buildCombinedFilter.$1", + "type": "Array", + "tags": [], + "label": "filters", + "description": [ + "An array of CombinedFilterItem" + ], + "signature": [ + "FilterItem", + "[]" + ], + "path": "packages/kbn-es-query/src/filters/build_filters/combined_filter.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, { "parentPluginId": "@kbn/es-query", "id": "def-common.buildCustomFilter", @@ -765,47 +806,6 @@ "returnComment": [], "initialIsOpen": false }, - { - "parentPluginId": "@kbn/es-query", - "id": "def-common.buildOrFilter", - "type": "Function", - "tags": [], - "label": "buildOrFilter", - "description": [ - "\nBuilds an OR filter. An OR filter is a filter with multiple sub-filters. Each sub-filter (FilterItem) represents a\ncondition." - ], - "signature": [ - "(filters: ", - "FilterItem", - "[]) => ", - "OrFilter" - ], - "path": "packages/kbn-es-query/src/filters/build_filters/or_filter.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "@kbn/es-query", - "id": "def-common.buildOrFilter.$1", - "type": "Array", - "tags": [], - "label": "filters", - "description": [ - "An array of OrFilterItem" - ], - "signature": [ - "FilterItem", - "[]" - ], - "path": "packages/kbn-es-query/src/filters/build_filters/or_filter.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [], - "initialIsOpen": false - }, { "parentPluginId": "@kbn/es-query", "id": "def-common.buildPhraseFilter", @@ -2249,6 +2249,53 @@ "returnComment": [], "initialIsOpen": false }, + { + "parentPluginId": "@kbn/es-query", + "id": "def-common.isCombinedFilter", + "type": "Function", + "tags": [], + "label": "isCombinedFilter", + "description": [], + "signature": [ + "(filter: ", + { + "pluginId": "@kbn/es-query", + "scope": "common", + "docId": "kibKbnEsQueryPluginApi", + "section": "def-common.Filter", + "text": "Filter" + }, + ") => boolean" + ], + "path": "packages/kbn-es-query/src/filters/build_filters/combined_filter.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/es-query", + "id": "def-common.isCombinedFilter.$1", + "type": "Object", + "tags": [], + "label": "filter", + "description": [], + "signature": [ + { + "pluginId": "@kbn/es-query", + "scope": "common", + "docId": "kibKbnEsQueryPluginApi", + "section": "def-common.Filter", + "text": "Filter" + } + ], + "path": "packages/kbn-es-query/src/filters/build_filters/combined_filter.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, { "parentPluginId": "@kbn/es-query", "id": "def-common.isDataViewFieldSubtypeMulti", @@ -2740,53 +2787,6 @@ "returnComment": [], "initialIsOpen": false }, - { - "parentPluginId": "@kbn/es-query", - "id": "def-common.isOrFilter", - "type": "Function", - "tags": [], - "label": "isOrFilter", - "description": [], - "signature": [ - "(filter: ", - { - "pluginId": "@kbn/es-query", - "scope": "common", - "docId": "kibKbnEsQueryPluginApi", - "section": "def-common.Filter", - "text": "Filter" - }, - ") => boolean" - ], - "path": "packages/kbn-es-query/src/filters/build_filters/or_filter.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "@kbn/es-query", - "id": "def-common.isOrFilter.$1", - "type": "Object", - "tags": [], - "label": "filter", - "description": [], - "signature": [ - { - "pluginId": "@kbn/es-query", - "scope": "common", - "docId": "kibKbnEsQueryPluginApi", - "section": "def-common.Filter", - "text": "Filter" - } - ], - "path": "packages/kbn-es-query/src/filters/build_filters/or_filter.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [], - "initialIsOpen": false - }, { "parentPluginId": "@kbn/es-query", "id": "def-common.isPhraseFilter", diff --git a/api_docs/kbn_es_query.mdx b/api_docs/kbn_es_query.mdx index 903a72f04b9bb..f1a537dee470d 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-10 +date: 2022-10-16 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 de03102edaaec..9dc2fe514e8cd 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-10 +date: 2022-10-16 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 c328060468254..e3f044deeab4e 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-10 +date: 2022-10-16 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 3b1d69004f2d9..a878ce21a937a 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-10 +date: 2022-10-16 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 99c56f93be934..2a4f5be209c2d 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-10 +date: 2022-10-16 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 1374a4aec1d96..07bafc8d8075f 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-10 +date: 2022-10-16 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 51789356f12dd..3b8f8d12a273a 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-10 +date: 2022-10-16 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 aef3268c9bfba..073235905b300 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-10 +date: 2022-10-16 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 66aba654ff775..f97bbe1bbcf48 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-10 +date: 2022-10-16 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 4b7223d26561f..e155ec70b1bdb 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-10 +date: 2022-10-16 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 240a64c2264ac..ee97e4569aa02 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-10 +date: 2022-10-16 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 cccab042144a3..922bd3d4524ea 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-10 +date: 2022-10-16 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 c9db829a85be3..9ea89bd5ed6ad 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-10 +date: 2022-10-16 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 fd6582ff8a7c5..68ccbcb691811 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-10 +date: 2022-10-16 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 c6b3c5a349b3b..198ef26c8971a 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-10 +date: 2022-10-16 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 929f3442b07fd..8fef127c2555a 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-10 +date: 2022-10-16 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 ea265ce6a91d3..436256c104d6e 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-10 +date: 2022-10-16 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 620cc2a26b48c..eb4dbd6eeac2d 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-10 +date: 2022-10-16 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 a407fb3d00675..b4519889ad623 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-10 +date: 2022-10-16 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 f8f1c0cbbf18e..cf9b2d6ebddae 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-10 +date: 2022-10-16 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 d9ca0522727a6..040edb474a3cc 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-10 +date: 2022-10-16 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 598854d6f14f6..4158abdfc6272 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-10 +date: 2022-10-16 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 7dd21a446f77f..c4dc14d53f819 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-10 +date: 2022-10-16 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 02b13bbb589b9..8eb5e7c290141 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-10 +date: 2022-10-16 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 f7394b06d8d9e..5599ec3fbab2c 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-10 +date: 2022-10-16 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 0687bfe1ceb56..70a643d02f693 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-10 +date: 2022-10-16 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 7eeb0479f984e..5665d17a0d204 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-10 +date: 2022-10-16 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 8d45d987a956e..d9d1b49371748 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-10 +date: 2022-10-16 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 10368217e8d44..2f7f690e5255d 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-10 +date: 2022-10-16 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 dc1bc2010d831..9bbdee31484fd 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-10 +date: 2022-10-16 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 3fa082077bf04..d8141ae2c8c8a 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-10 +date: 2022-10-16 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 fd1c4a622607c..38420aabec934 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-10 +date: 2022-10-16 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 91f1073961202..dc7ffc6376f2a 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-10 +date: 2022-10-16 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 a2dc7b6bb5fb0..7121e755cefbd 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-10 +date: 2022-10-16 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 b4a5ffe67fbb5..679bc7c0ae48b 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-10 +date: 2022-10-16 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.devdocs.json b/api_docs/kbn_rule_data_utils.devdocs.json index 513060301f142..adb2f74e16015 100644 --- a/api_docs/kbn_rule_data_utils.devdocs.json +++ b/api_docs/kbn_rule_data_utils.devdocs.json @@ -927,7 +927,7 @@ "label": "AlertConsumers", "description": [], "signature": [ - "\"infrastructure\" | \"observability\" | \"logs\" | \"apm\" | \"uptime\" | \"siem\"" + "\"infrastructure\" | \"apm\" | \"observability\" | \"logs\" | \"uptime\" | \"siem\"" ], "path": "packages/kbn-rule-data-utils/src/alerts_as_data_rbac.ts", "deprecated": false, @@ -1122,7 +1122,7 @@ "label": "ValidFeatureId", "description": [], "signature": [ - "\"infrastructure\" | \"observability\" | \"logs\" | \"apm\" | \"uptime\" | \"siem\"" + "\"infrastructure\" | \"apm\" | \"observability\" | \"logs\" | \"uptime\" | \"siem\"" ], "path": "packages/kbn-rule-data-utils/src/alerts_as_data_rbac.ts", "deprecated": false, diff --git a/api_docs/kbn_rule_data_utils.mdx b/api_docs/kbn_rule_data_utils.mdx index 8842f16f95521..96732ad4a12a0 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-10 +date: 2022-10-16 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 c1162de9f27a8..084861de5cfe9 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-10 +date: 2022-10-16 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.devdocs.json b/api_docs/kbn_securitysolution_es_utils.devdocs.json index a96bb0f4d470e..e209c3759d537 100644 --- a/api_docs/kbn_securitysolution_es_utils.devdocs.json +++ b/api_docs/kbn_securitysolution_es_utils.devdocs.json @@ -631,14 +631,14 @@ "TransportRequestOptions", " | undefined): Promise<", "UpdateResponse", - ">; }; [kInternal]: symbol | null; [kAsyncSearch]: symbol | null; [kAutoscaling]: symbol | null; [kCat]: symbol | null; [kCcr]: symbol | null; [kCluster]: symbol | null; [kDanglingIndices]: symbol | null; [kEnrich]: symbol | null; [kEql]: symbol | null; [kFeatures]: symbol | null; [kFleet]: symbol | null; [kGraph]: symbol | null; [kIlm]: symbol | null; [kIndices]: symbol | null; [kIngest]: symbol | null; [kLicense]: symbol | null; [kLogstash]: symbol | null; [kMigration]: symbol | null; [kMl]: symbol | null; [kMonitoring]: symbol | null; [kNodes]: symbol | null; [kRollup]: symbol | null; [kSearchableSnapshots]: symbol | null; [kSecurity]: symbol | null; [kShutdown]: symbol | null; [kSlm]: symbol | null; [kSnapshot]: symbol | null; [kSql]: symbol | null; [kSsl]: symbol | null; [kTasks]: symbol | null; [kTextStructure]: symbol | null; [kTransform]: symbol | null; [kWatcher]: symbol | null; [kXpack]: symbol | null; transport: ", + ">; }; asyncSearch: ", + "default", + "; [kInternal]: symbol | null; [kAsyncSearch]: symbol | null; [kAutoscaling]: symbol | null; [kCat]: symbol | null; [kCcr]: symbol | null; [kCluster]: symbol | null; [kDanglingIndices]: symbol | null; [kEnrich]: symbol | null; [kEql]: symbol | null; [kFeatures]: symbol | null; [kFleet]: symbol | null; [kGraph]: symbol | null; [kIlm]: symbol | null; [kIndices]: symbol | null; [kIngest]: symbol | null; [kLicense]: symbol | null; [kLogstash]: symbol | null; [kMigration]: symbol | null; [kMl]: symbol | null; [kMonitoring]: symbol | null; [kNodes]: symbol | null; [kRollup]: symbol | null; [kSearchableSnapshots]: symbol | null; [kSecurity]: symbol | null; [kShutdown]: symbol | null; [kSlm]: symbol | null; [kSnapshot]: symbol | null; [kSql]: symbol | null; [kSsl]: symbol | null; [kTasks]: symbol | null; [kTextStructure]: symbol | null; [kTransform]: symbol | null; [kWatcher]: symbol | null; [kXpack]: symbol | null; transport: ", "default", "; helpers: ", "default", "; Internal: ", "default", - "; asyncSearch: ", - "default", "; autoscaling: ", "default", "; bulk: { (this: That, params: ", @@ -1877,14 +1877,14 @@ "TransportRequestOptions", " | undefined): Promise<", "UpdateResponse", - ">; }; [kInternal]: symbol | null; [kAsyncSearch]: symbol | null; [kAutoscaling]: symbol | null; [kCat]: symbol | null; [kCcr]: symbol | null; [kCluster]: symbol | null; [kDanglingIndices]: symbol | null; [kEnrich]: symbol | null; [kEql]: symbol | null; [kFeatures]: symbol | null; [kFleet]: symbol | null; [kGraph]: symbol | null; [kIlm]: symbol | null; [kIndices]: symbol | null; [kIngest]: symbol | null; [kLicense]: symbol | null; [kLogstash]: symbol | null; [kMigration]: symbol | null; [kMl]: symbol | null; [kMonitoring]: symbol | null; [kNodes]: symbol | null; [kRollup]: symbol | null; [kSearchableSnapshots]: symbol | null; [kSecurity]: symbol | null; [kShutdown]: symbol | null; [kSlm]: symbol | null; [kSnapshot]: symbol | null; [kSql]: symbol | null; [kSsl]: symbol | null; [kTasks]: symbol | null; [kTextStructure]: symbol | null; [kTransform]: symbol | null; [kWatcher]: symbol | null; [kXpack]: symbol | null; transport: ", + ">; }; asyncSearch: ", + "default", + "; [kInternal]: symbol | null; [kAsyncSearch]: symbol | null; [kAutoscaling]: symbol | null; [kCat]: symbol | null; [kCcr]: symbol | null; [kCluster]: symbol | null; [kDanglingIndices]: symbol | null; [kEnrich]: symbol | null; [kEql]: symbol | null; [kFeatures]: symbol | null; [kFleet]: symbol | null; [kGraph]: symbol | null; [kIlm]: symbol | null; [kIndices]: symbol | null; [kIngest]: symbol | null; [kLicense]: symbol | null; [kLogstash]: symbol | null; [kMigration]: symbol | null; [kMl]: symbol | null; [kMonitoring]: symbol | null; [kNodes]: symbol | null; [kRollup]: symbol | null; [kSearchableSnapshots]: symbol | null; [kSecurity]: symbol | null; [kShutdown]: symbol | null; [kSlm]: symbol | null; [kSnapshot]: symbol | null; [kSql]: symbol | null; [kSsl]: symbol | null; [kTasks]: symbol | null; [kTextStructure]: symbol | null; [kTransform]: symbol | null; [kWatcher]: symbol | null; [kXpack]: symbol | null; transport: ", "default", "; helpers: ", "default", "; Internal: ", "default", - "; asyncSearch: ", - "default", "; autoscaling: ", "default", "; bulk: { (this: That, params: ", diff --git a/api_docs/kbn_securitysolution_es_utils.mdx b/api_docs/kbn_securitysolution_es_utils.mdx index 55450f4d392ab..bdb920ef1cffc 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-10 +date: 2022-10-16 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 75ed0a758d7b4..03529212c449b 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-10 +date: 2022-10-16 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 99d48e0e7c4c4..1ae6fc0da2dc4 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-10 +date: 2022-10-16 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 47e94eafc034e..8cae190caef9a 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-10 +date: 2022-10-16 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 0efde1f2fc5e5..f26769348dba0 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-10 +date: 2022-10-16 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 879dab8d19863..fb6ca7031ff01 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-10 +date: 2022-10-16 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 d5f0dd0f088f4..02c0a1945e488 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-10 +date: 2022-10-16 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 eb7870fb27812..5906abdaf56c3 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-10 +date: 2022-10-16 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 a72acb71f8343..8ca2ca65c6098 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-10 +date: 2022-10-16 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 818f3cedcf431..4ee684d51e80a 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-10 +date: 2022-10-16 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 d3b238f064f04..6fbb952869d38 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-10 +date: 2022-10-16 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 9819937553c2c..044c99db23987 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-10 +date: 2022-10-16 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 3fe4182737cb1..7bcdc5915070e 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-10 +date: 2022-10-16 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 cffd24280bd80..1ee1e30eb073f 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-10 +date: 2022-10-16 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 63492dc74b4a0..8d2822bd00ea9 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-10 +date: 2022-10-16 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 f129163c988e9..f134cecc46ade 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-10 +date: 2022-10-16 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 44d456487ad02..e653ecebe69b5 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-10 +date: 2022-10-16 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 01725450e1a3f..8a39a4fe0f83f 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-10 +date: 2022-10-16 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 1ca4cca275861..70287c0a0ab88 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-10 +date: 2022-10-16 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 54896916668a9..58a3cf876c9a4 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-10 +date: 2022-10-16 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 0c858f6846b3c..1dc183f6bb7f9 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-10 +date: 2022-10-16 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 78c646f343f8e..c17e9c90aa0ca 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-10 +date: 2022-10-16 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 fe98104746134..8c736f881ed6d 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-10 +date: 2022-10-16 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 2d756c72ea7a1..b6015cde6fbe2 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-10 +date: 2022-10-16 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 a8ac95588218f..4641fe86b3ba6 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-10 +date: 2022-10-16 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 7926794780d49..175a47e8a1d92 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-10 +date: 2022-10-16 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 5c8075601d9a8..513f1c749e2c6 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-10 +date: 2022-10-16 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 df0736b573f17..9a847d4596617 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-10 +date: 2022-10-16 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 39ee413fc7676..a27c0161ab6e0 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-10 +date: 2022-10-16 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 edab8ba9cdeda..754e6c35c37ae 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-10 +date: 2022-10-16 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 3238e35f522ab..3c1b487edc2ea 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-10 +date: 2022-10-16 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 d91e3c960d34c..4843d42f55322 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-10 +date: 2022-10-16 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 c908ad8566edb..348fd5af662f8 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-10 +date: 2022-10-16 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 19fa427b65ad9..baf22a9d18399 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-10 +date: 2022-10-16 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 039d9ad79e772..984f8749b6440 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-10 +date: 2022-10-16 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 691755b31bb3a..ac4557f9b72a0 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-10 +date: 2022-10-16 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 838f60da629eb..c1248545c9a2d 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-10 +date: 2022-10-16 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 753b087e6f375..faeaf3caaa41e 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-10 +date: 2022-10-16 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 c2935ffb7d512..10ad9bf6e79ed 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-10 +date: 2022-10-16 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 0d2b31cecba0e..63f9364d27492 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-10 +date: 2022-10-16 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 e73b81401efa6..206b5b2b649e2 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-10 +date: 2022-10-16 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 d5317c0029e9c..254f37e9ac455 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-10 +date: 2022-10-16 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 c93ed16d6f152..6f5f54ebca0a8 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-10 +date: 2022-10-16 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 07dcb1a3659d0..e82aea34861a4 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-10 +date: 2022-10-16 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 2e32807ed0a2e..23ea14c741dc8 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-10 +date: 2022-10-16 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 04a276c4eb964..5c0dc324464d5 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-10 +date: 2022-10-16 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 bfa6f898f4309..a4c5b5f5d5459 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-10 +date: 2022-10-16 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 bb0dc9dcf8166..ed05da7a4b139 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-10 +date: 2022-10-16 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 a1e8dbf164f44..0654138dfb7b5 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-10 +date: 2022-10-16 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 393f75434d833..0720b2fd79b6c 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-10 +date: 2022-10-16 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 3e90ec8fb19e9..5f53724bdcd32 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-10 +date: 2022-10-16 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 1b1c168133c53..92c9a98c230bb 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-10 +date: 2022-10-16 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 8d1abc35c23dc..06893a1ed3d8f 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-10 +date: 2022-10-16 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 d108fa2cf7a0a..8ab899c109d5a 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-10 +date: 2022-10-16 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 c0ec429464c4e..20d368f0c1d60 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-10 +date: 2022-10-16 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 b0967bc0c569a..d6c06fc96bc62 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-10 +date: 2022-10-16 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 418262e39279d..37ac8e4ab5200 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-10 +date: 2022-10-16 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 662803563e248..0b8e43a7de87d 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-10 +date: 2022-10-16 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 0d1e452936370..40220059bb6e0 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-10 +date: 2022-10-16 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 83b89a98d54b2..21e38114c08c1 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-10 +date: 2022-10-16 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 6f9e09103095d..9084b13801814 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-10 +date: 2022-10-16 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 8ea2cb868f741..2dfd980bebd77 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-10 +date: 2022-10-16 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 c35811e02734d..e83a24395b7c4 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-10 +date: 2022-10-16 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 fa1459a1b6c14..39d2c4f758888 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-10 +date: 2022-10-16 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 6749b467d5b11..285035a4d158d 100644 --- a/api_docs/lens.devdocs.json +++ b/api_docs/lens.devdocs.json @@ -1065,7 +1065,7 @@ "text": "FieldBasedIndexPatternColumn" } ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/cardinality.tsx", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/cardinality.tsx", "deprecated": false, "trackAdoption": false, "children": [ @@ -1079,7 +1079,7 @@ "signature": [ "\"unique_count\"" ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/cardinality.tsx", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/cardinality.tsx", "deprecated": false, "trackAdoption": false }, @@ -1095,7 +1095,7 @@ "ValueFormatConfig", " | undefined; } | undefined" ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/cardinality.tsx", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/cardinality.tsx", "deprecated": false, "trackAdoption": false } @@ -1818,7 +1818,7 @@ "text": "FieldBasedIndexPatternColumn" } ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/date_histogram.tsx", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/date_histogram.tsx", "deprecated": false, "trackAdoption": false, "children": [ @@ -1832,7 +1832,7 @@ "signature": [ "\"date_histogram\"" ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/date_histogram.tsx", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/date_histogram.tsx", "deprecated": false, "trackAdoption": false }, @@ -1846,7 +1846,7 @@ "signature": [ "{ interval: string; ignoreTimeRange?: boolean | undefined; includeEmptyRows?: boolean | undefined; dropPartials?: boolean | undefined; }" ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/date_histogram.tsx", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/date_histogram.tsx", "deprecated": false, "trackAdoption": false } @@ -1871,7 +1871,7 @@ " extends ", "BaseIndexPatternColumn" ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/column_types.ts", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/column_types.ts", "deprecated": false, "trackAdoption": false, "children": [ @@ -1882,7 +1882,7 @@ "tags": [], "label": "sourceField", "description": [], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/column_types.ts", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/column_types.ts", "deprecated": false, "trackAdoption": false } @@ -1907,7 +1907,7 @@ " extends ", "BaseIndexPatternColumn" ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filters.tsx", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/filters/filters.tsx", "deprecated": false, "trackAdoption": false, "children": [ @@ -1921,7 +1921,7 @@ "signature": [ "\"filters\"" ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filters.tsx", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/filters/filters.tsx", "deprecated": false, "trackAdoption": false }, @@ -1937,7 +1937,126 @@ "Filter", "[]; }" ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filters.tsx", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/filters/filters.tsx", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "lens", + "id": "def-public.FormBasedLayer", + "type": "Interface", + "tags": [], + "label": "FormBasedLayer", + "description": [], + "path": "x-pack/plugins/lens/public/datasources/form_based/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "lens", + "id": "def-public.FormBasedLayer.columnOrder", + "type": "Array", + "tags": [], + "label": "columnOrder", + "description": [], + "signature": [ + "string[]" + ], + "path": "x-pack/plugins/lens/public/datasources/form_based/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "lens", + "id": "def-public.FormBasedLayer.columns", + "type": "Object", + "tags": [], + "label": "columns", + "description": [], + "signature": [ + "{ [x: string]: ", + { + "pluginId": "lens", + "scope": "public", + "docId": "kibLensPluginApi", + "section": "def-public.GenericIndexPatternColumn", + "text": "GenericIndexPatternColumn" + }, + "; }" + ], + "path": "x-pack/plugins/lens/public/datasources/form_based/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "lens", + "id": "def-public.FormBasedLayer.indexPatternId", + "type": "string", + "tags": [], + "label": "indexPatternId", + "description": [], + "path": "x-pack/plugins/lens/public/datasources/form_based/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "lens", + "id": "def-public.FormBasedLayer.incompleteColumns", + "type": "Object", + "tags": [], + "label": "incompleteColumns", + "description": [], + "signature": [ + "Record | undefined" + ], + "path": "x-pack/plugins/lens/public/datasources/form_based/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "lens", + "id": "def-public.FormBasedPersistedState", + "type": "Interface", + "tags": [], + "label": "FormBasedPersistedState", + "description": [], + "path": "x-pack/plugins/lens/public/datasources/form_based/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "lens", + "id": "def-public.FormBasedPersistedState.layers", + "type": "Object", + "tags": [], + "label": "layers", + "description": [], + "signature": [ + "{ [x: string]: Omit<", + { + "pluginId": "lens", + "scope": "public", + "docId": "kibLensPluginApi", + "section": "def-public.FormBasedLayer", + "text": "FormBasedLayer" + }, + ", \"indexPatternId\">; }" + ], + "path": "x-pack/plugins/lens/public/datasources/form_based/types.ts", "deprecated": false, "trackAdoption": false } @@ -1962,7 +2081,7 @@ " extends ", "ReferenceBasedIndexPatternColumn" ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula.tsx", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/formula.tsx", "deprecated": false, "trackAdoption": false, "children": [ @@ -1976,7 +2095,7 @@ "signature": [ "\"formula\"" ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula.tsx", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/formula.tsx", "deprecated": false, "trackAdoption": false }, @@ -1990,7 +2109,7 @@ "signature": [ "{ formula?: string | undefined; isFormulaBroken?: boolean | undefined; format?: { id: string; params?: { decimals: number; } | undefined; } | undefined; }" ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula.tsx", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/formula.tsx", "deprecated": false, "trackAdoption": false } @@ -2004,7 +2123,7 @@ "tags": [], "label": "FormulaPublicApi", "description": [], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula_public_api.ts", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/formula_public_api.ts", "deprecated": false, "trackAdoption": false, "children": [ @@ -2044,7 +2163,7 @@ }, " | undefined" ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula_public_api.ts", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/formula_public_api.ts", "deprecated": false, "trackAdoption": false, "children": [ @@ -2060,7 +2179,7 @@ "signature": [ "string" ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula_public_api.ts", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/formula_public_api.ts", "deprecated": false, "trackAdoption": false, "isRequired": true @@ -2072,7 +2191,7 @@ "tags": [], "label": "column", "description": [], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula_public_api.ts", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/formula_public_api.ts", "deprecated": false, "trackAdoption": false, "children": [ @@ -2083,7 +2202,7 @@ "tags": [], "label": "formula", "description": [], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula_public_api.ts", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/formula_public_api.ts", "deprecated": false, "trackAdoption": false }, @@ -2097,7 +2216,7 @@ "signature": [ "string | undefined" ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula_public_api.ts", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/formula_public_api.ts", "deprecated": false, "trackAdoption": false }, @@ -2111,7 +2230,7 @@ "signature": [ "{ id: string; params?: { decimals: number; } | undefined; } | undefined" ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula_public_api.ts", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/formula_public_api.ts", "deprecated": false, "trackAdoption": false } @@ -2135,7 +2254,7 @@ "text": "PersistedIndexPatternLayer" } ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula_public_api.ts", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/formula_public_api.ts", "deprecated": false, "trackAdoption": false, "isRequired": true @@ -2158,7 +2277,7 @@ "text": "DataView" } ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula_public_api.ts", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/formula_public_api.ts", "deprecated": false, "trackAdoption": false, "isRequired": true @@ -2176,7 +2295,7 @@ "tags": [], "label": "IncompleteColumn", "description": [], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/column_types.ts", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/column_types.ts", "deprecated": false, "trackAdoption": false, "children": [ @@ -2190,7 +2309,7 @@ "signature": [ "string | undefined" ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/column_types.ts", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/column_types.ts", "deprecated": false, "trackAdoption": false }, @@ -2204,126 +2323,7 @@ "signature": [ "string | undefined" ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/column_types.ts", - "deprecated": false, - "trackAdoption": false - } - ], - "initialIsOpen": false - }, - { - "parentPluginId": "lens", - "id": "def-public.IndexPatternLayer", - "type": "Interface", - "tags": [], - "label": "IndexPatternLayer", - "description": [], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/types.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "lens", - "id": "def-public.IndexPatternLayer.columnOrder", - "type": "Array", - "tags": [], - "label": "columnOrder", - "description": [], - "signature": [ - "string[]" - ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "lens", - "id": "def-public.IndexPatternLayer.columns", - "type": "Object", - "tags": [], - "label": "columns", - "description": [], - "signature": [ - "{ [x: string]: ", - { - "pluginId": "lens", - "scope": "public", - "docId": "kibLensPluginApi", - "section": "def-public.GenericIndexPatternColumn", - "text": "GenericIndexPatternColumn" - }, - "; }" - ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "lens", - "id": "def-public.IndexPatternLayer.indexPatternId", - "type": "string", - "tags": [], - "label": "indexPatternId", - "description": [], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "lens", - "id": "def-public.IndexPatternLayer.incompleteColumns", - "type": "Object", - "tags": [], - "label": "incompleteColumns", - "description": [], - "signature": [ - "Record | undefined" - ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/types.ts", - "deprecated": false, - "trackAdoption": false - } - ], - "initialIsOpen": false - }, - { - "parentPluginId": "lens", - "id": "def-public.IndexPatternPersistedState", - "type": "Interface", - "tags": [], - "label": "IndexPatternPersistedState", - "description": [], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/types.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "lens", - "id": "def-public.IndexPatternPersistedState.layers", - "type": "Object", - "tags": [], - "label": "layers", - "description": [], - "signature": [ - "{ [x: string]: Omit<", - { - "pluginId": "lens", - "scope": "public", - "docId": "kibLensPluginApi", - "section": "def-public.IndexPatternLayer", - "text": "IndexPatternLayer" - }, - ", \"indexPatternId\">; }" - ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/types.ts", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/column_types.ts", "deprecated": false, "trackAdoption": false } @@ -2354,7 +2354,7 @@ "text": "FieldBasedIndexPatternColumn" } ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/last_value.tsx", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/last_value.tsx", "deprecated": false, "trackAdoption": false, "children": [ @@ -2368,7 +2368,7 @@ "signature": [ "\"last_value\"" ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/last_value.tsx", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/last_value.tsx", "deprecated": false, "trackAdoption": false }, @@ -2384,7 +2384,7 @@ "ValueFormatConfig", " | undefined; }" ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/last_value.tsx", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/last_value.tsx", "deprecated": false, "trackAdoption": false } @@ -3093,7 +3093,7 @@ " extends ", "ReferenceBasedIndexPatternColumn" ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/math.tsx", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/math.tsx", "deprecated": false, "trackAdoption": false, "children": [ @@ -3107,7 +3107,7 @@ "signature": [ "\"math\"" ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/math.tsx", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/math.tsx", "deprecated": false, "trackAdoption": false }, @@ -3125,7 +3125,7 @@ "ValueFormatConfig", " | undefined; }" ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/math.tsx", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/math.tsx", "deprecated": false, "trackAdoption": false } @@ -3240,7 +3240,7 @@ "text": "FieldBasedIndexPatternColumn" } ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/percentile.tsx", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/percentile.tsx", "deprecated": false, "trackAdoption": false, "children": [ @@ -3254,7 +3254,7 @@ "signature": [ "\"percentile\"" ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/percentile.tsx", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/percentile.tsx", "deprecated": false, "trackAdoption": false }, @@ -3268,7 +3268,7 @@ "signature": [ "{ percentile: number; format?: { id: string; params?: { decimals: number; } | undefined; } | undefined; }" ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/percentile.tsx", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/percentile.tsx", "deprecated": false, "trackAdoption": false } @@ -3299,7 +3299,7 @@ "text": "FieldBasedIndexPatternColumn" } ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/percentile_ranks.tsx", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/percentile_ranks.tsx", "deprecated": false, "trackAdoption": false, "children": [ @@ -3313,7 +3313,7 @@ "signature": [ "\"percentile_rank\"" ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/percentile_ranks.tsx", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/percentile_ranks.tsx", "deprecated": false, "trackAdoption": false }, @@ -3327,7 +3327,7 @@ "signature": [ "{ value: number; }" ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/percentile_ranks.tsx", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/percentile_ranks.tsx", "deprecated": false, "trackAdoption": false } @@ -3422,7 +3422,7 @@ "text": "FieldBasedIndexPatternColumn" } ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/ranges/ranges.tsx", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/ranges/ranges.tsx", "deprecated": false, "trackAdoption": false, "children": [ @@ -3436,7 +3436,7 @@ "signature": [ "\"range\"" ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/ranges/ranges.tsx", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/ranges/ranges.tsx", "deprecated": false, "trackAdoption": false }, @@ -3454,7 +3454,7 @@ "RangeTypeLens", "[]; format?: { id: string; params?: { decimals: number; } | undefined; } | undefined; includeEmptyRows?: boolean | undefined; parentFormat?: { id: string; params?: { id?: string | undefined; template?: string | undefined; replaceInfinity?: boolean | undefined; } | undefined; } | undefined; }" ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/ranges/ranges.tsx", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/ranges/ranges.tsx", "deprecated": false, "trackAdoption": false } @@ -3809,7 +3809,7 @@ " extends ", "ReferenceBasedIndexPatternColumn" ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/static_value.tsx", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/static_value.tsx", "deprecated": false, "trackAdoption": false, "children": [ @@ -3823,7 +3823,7 @@ "signature": [ "\"static_value\"" ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/static_value.tsx", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/static_value.tsx", "deprecated": false, "trackAdoption": false }, @@ -3839,7 +3839,7 @@ "ValueFormatConfig", " | undefined; }" ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/static_value.tsx", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/static_value.tsx", "deprecated": false, "trackAdoption": false } @@ -4108,7 +4108,7 @@ "text": "FieldBasedIndexPatternColumn" } ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms/types.ts", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/terms/types.ts", "deprecated": false, "trackAdoption": false, "children": [ @@ -4122,7 +4122,7 @@ "signature": [ "\"terms\"" ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms/types.ts", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/terms/types.ts", "deprecated": false, "trackAdoption": false }, @@ -4146,7 +4146,7 @@ "ValueFormatConfig", " | undefined; parentFormat?: { id: string; } | undefined; }" ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms/types.ts", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/terms/types.ts", "deprecated": false, "trackAdoption": false } @@ -6586,7 +6586,7 @@ "signature": [ "((props: VisualizationStateFromContextChangeProps) => ", "Suggestion", - " | undefined) | undefined" + " | undefined) | undefined" ], "path": "x-pack/plugins/lens/public/types.ts", "deprecated": false, @@ -7207,6 +7207,42 @@ "path": "src/plugins/chart_expressions/expression_xy/common/types/expression_renderers.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "lens", + "id": "def-public.XYChartProps.syncTooltips", + "type": "boolean", + "tags": [], + "label": "syncTooltips", + "description": [], + "path": "src/plugins/chart_expressions/expression_xy/common/types/expression_renderers.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "lens", + "id": "def-public.XYChartProps.syncColors", + "type": "boolean", + "tags": [], + "label": "syncColors", + "description": [], + "path": "src/plugins/chart_expressions/expression_xy/common/types/expression_renderers.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "lens", + "id": "def-public.XYChartProps.canNavigateToLens", + "type": "CompoundType", + "tags": [], + "label": "canNavigateToLens", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "src/plugins/chart_expressions/expression_xy/common/types/expression_renderers.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false @@ -8183,7 +8219,7 @@ "ValueFormatConfig", " | undefined; } | undefined; }" ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/metrics.tsx", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/metrics.tsx", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -8238,7 +8274,7 @@ "ReferenceBasedIndexPatternColumn", " & { operationType: \"counter_rate\"; }" ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/counter_rate.tsx", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/calculations/counter_rate.tsx", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -8262,7 +8298,7 @@ "ValueFormatConfig", " | undefined; } | undefined; }" ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/count.tsx", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/count.tsx", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -8280,7 +8316,7 @@ "ReferenceBasedIndexPatternColumn", " & { operationType: \"cumulative_sum\"; }" ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/cumulative_sum.tsx", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/calculations/cumulative_sum.tsx", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -8348,7 +8384,7 @@ "ReferenceBasedIndexPatternColumn", " & { operationType: \"differences\"; }" ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/differences.tsx", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/calculations/differences.tsx", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -8467,7 +8503,7 @@ " | ", "ReferenceBasedIndexPatternColumn" ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/column_types.ts", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/column_types.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -8638,7 +8674,7 @@ "ValueFormatConfig", " | undefined; } | undefined; }" ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/metrics.tsx", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/metrics.tsx", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -8662,7 +8698,7 @@ "ValueFormatConfig", " | undefined; } | undefined; }" ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/metrics.tsx", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/metrics.tsx", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -8686,7 +8722,7 @@ "ValueFormatConfig", " | undefined; } | undefined; }" ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/metrics.tsx", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/metrics.tsx", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -8704,7 +8740,7 @@ "ReferenceBasedIndexPatternColumn", " & { operationType: \"moving_average\"; params: { window: number; }; }" ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/moving_average.tsx", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/calculations/moving_average.tsx", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -8721,7 +8757,7 @@ "signature": [ "string" ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/index.ts", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/index.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -8739,7 +8775,7 @@ "ReferenceBasedIndexPatternColumn", " & { operationType: \"overall_sum\"; }" ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/overall_metric.tsx", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/calculations/overall_metric.tsx", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -8770,7 +8806,7 @@ }, "> | undefined; }" ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/types.ts", + "path": "x-pack/plugins/lens/public/datasources/form_based/types.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -8870,7 +8906,7 @@ "ValueFormatConfig", " | undefined; } | undefined; }" ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/metrics.tsx", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/metrics.tsx", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -8894,7 +8930,7 @@ "ValueFormatConfig", " | undefined; } | undefined; }" ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/metrics.tsx", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/metrics.tsx", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -8912,7 +8948,7 @@ "ReferenceBasedIndexPatternColumn", " & { operationType: \"normalize_by_unit\"; params: { unit?: string | undefined; }; }" ], - "path": "x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/time_scale.tsx", + "path": "x-pack/plugins/lens/public/datasources/form_based/operations/definitions/calculations/time_scale.tsx", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -9142,15 +9178,75 @@ "parentPluginId": "lens", "id": "def-public.layerTypes", "type": "Object", - "tags": [], + "tags": [ + "deprecated" + ], "label": "layerTypes", "description": [], "signature": [ "{ readonly DATA: \"data\"; readonly REFERENCELINE: \"referenceLine\"; readonly ANNOTATIONS: \"annotations\"; }" ], - "path": "x-pack/plugins/lens/common/constants.ts", - "deprecated": false, + "path": "x-pack/plugins/lens/public/index.ts", + "deprecated": true, "trackAdoption": false, + "references": [ + { + "plugin": "maps", + "path": "x-pack/plugins/maps/public/lens/choropleth_chart/visualization.tsx" + }, + { + "plugin": "maps", + "path": "x-pack/plugins/maps/public/lens/choropleth_chart/visualization.tsx" + }, + { + "plugin": "maps", + "path": "x-pack/plugins/maps/public/lens/choropleth_chart/visualization.tsx" + }, + { + "plugin": "maps", + "path": "x-pack/plugins/maps/public/lens/choropleth_chart/visualization.tsx" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/utils.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/utils.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/utils.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/utils.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/utils.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/utils.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/visualization_extractor.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/visualization_extractor.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/visualization_extractor.ts" + }, + { + "plugin": "ml", + "path": "x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/visualization_extractor.ts" + } + ], "initialIsOpen": false } ] @@ -10407,6 +10503,47 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "lens", + "id": "def-server.LensDocShape860", + "type": "Type", + "tags": [], + "label": "LensDocShape860", + "description": [], + "signature": [ + "Omit<", + { + "pluginId": "lens", + "scope": "server", + "docId": "kibLensPluginApi", + "section": "def-server.LensDocShape850", + "text": "LensDocShape850" + }, + ", \"state\"> & { state: Omit>; }>; }; }; visualization: VisualizationState; query: ", + "Query", + "; filters: ", + { + "pluginId": "lens", + "scope": "common", + "docId": "kibLensPluginApi", + "section": "def-common.PersistableFilter", + "text": "PersistableFilter" + }, + "[]; }, \"datasourceStates\"> & { datasourceStates: { indexpattern: Omit<{ currentIndexPatternId: string; layers: Record>; }>; }, \"layers\"> & { layers: Record>; }, \"columns\"> & { columns: Record; }>; }>; }; }; }, \"datasourceStates\"> & { datasourceStates: { formBased: { currentIndexPatternId: string; layers: Record>; }>; }; }; }; }" + ], + "path": "x-pack/plugins/lens/server/migrations/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "lens", "id": "def-server.OperationTypePost712", @@ -11457,22 +11594,6 @@ "trackAdoption": false, "initialIsOpen": false }, - { - "parentPluginId": "lens", - "id": "def-common.CustomPaletteParamsConfig", - "type": "Type", - "tags": [], - "label": "CustomPaletteParamsConfig", - "description": [], - "signature": [ - "CustomPaletteParams", - " & { maxSteps?: number | undefined; }" - ], - "path": "x-pack/plugins/lens/common/types.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - }, { "parentPluginId": "lens", "id": "def-common.DOC_TYPE", @@ -11788,21 +11909,6 @@ "trackAdoption": false, "initialIsOpen": false }, - { - "parentPluginId": "lens", - "id": "def-common.layerTypes", - "type": "Object", - "tags": [], - "label": "layerTypes", - "description": [], - "signature": [ - "{ readonly DATA: \"data\"; readonly REFERENCELINE: \"referenceLine\"; readonly ANNOTATIONS: \"annotations\"; }" - ], - "path": "x-pack/plugins/lens/common/constants.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - }, { "parentPluginId": "lens", "id": "def-common.LegendDisplay", diff --git a/api_docs/lens.mdx b/api_docs/lens.mdx index 93d38cc9b09a5..ef92361d9431b 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-10 +date: 2022-10-16 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 | |-------------------|-----------|------------------------|-----------------| -| 656 | 0 | 565 | 45 | +| 658 | 0 | 567 | 45 | ## Client diff --git a/api_docs/license_api_guard.mdx b/api_docs/license_api_guard.mdx index 44640af1df067..5038a63c6f753 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-10 +date: 2022-10-16 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 c3a53ddfcb762..a086e067dd423 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-10 +date: 2022-10-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licenseManagement'] --- import licenseManagementObj from './license_management.devdocs.json'; diff --git a/api_docs/licensing.mdx b/api_docs/licensing.mdx index 05f7e0d8fd343..1115133cd162d 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-10 +date: 2022-10-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licensing'] --- import licensingObj from './licensing.devdocs.json'; diff --git a/api_docs/lists.devdocs.json b/api_docs/lists.devdocs.json index 83be2ee9706c9..5270d0f1418e9 100644 --- a/api_docs/lists.devdocs.json +++ b/api_docs/lists.devdocs.json @@ -4063,7 +4063,9 @@ "TransportRequestOptions", " | undefined): Promise<", "UpdateResponse", - ">; }; [kInternal]: symbol | null; [kAsyncSearch]: symbol | null; [kAutoscaling]: symbol | null; [kCat]: symbol | null; [kCcr]: symbol | null; [kCluster]: symbol | null; [kDanglingIndices]: symbol | null; [kEnrich]: symbol | null; [kEql]: symbol | null; [kFeatures]: symbol | null; [kFleet]: symbol | null; [kGraph]: symbol | null; [kIlm]: symbol | null; [kIndices]: symbol | null; [kIngest]: symbol | null; [kLicense]: symbol | null; [kLogstash]: symbol | null; [kMigration]: symbol | null; [kMl]: symbol | null; [kMonitoring]: symbol | null; [kNodes]: symbol | null; [kRollup]: symbol | null; [kSearchableSnapshots]: symbol | null; [kSecurity]: symbol | null; [kShutdown]: symbol | null; [kSlm]: symbol | null; [kSnapshot]: symbol | null; [kSql]: symbol | null; [kSsl]: symbol | null; [kTasks]: symbol | null; [kTextStructure]: symbol | null; [kTransform]: symbol | null; [kWatcher]: symbol | null; [kXpack]: symbol | null; transport: ", + ">; }; asyncSearch: ", + "default", + "; [kInternal]: symbol | null; [kAsyncSearch]: symbol | null; [kAutoscaling]: symbol | null; [kCat]: symbol | null; [kCcr]: symbol | null; [kCluster]: symbol | null; [kDanglingIndices]: symbol | null; [kEnrich]: symbol | null; [kEql]: symbol | null; [kFeatures]: symbol | null; [kFleet]: symbol | null; [kGraph]: symbol | null; [kIlm]: symbol | null; [kIndices]: symbol | null; [kIngest]: symbol | null; [kLicense]: symbol | null; [kLogstash]: symbol | null; [kMigration]: symbol | null; [kMl]: symbol | null; [kMonitoring]: symbol | null; [kNodes]: symbol | null; [kRollup]: symbol | null; [kSearchableSnapshots]: symbol | null; [kSecurity]: symbol | null; [kShutdown]: symbol | null; [kSlm]: symbol | null; [kSnapshot]: symbol | null; [kSql]: symbol | null; [kSsl]: symbol | null; [kTasks]: symbol | null; [kTextStructure]: symbol | null; [kTransform]: symbol | null; [kWatcher]: symbol | null; [kXpack]: symbol | null; transport: ", "default", "; helpers: ", "default", @@ -4073,8 +4075,6 @@ "default", "; Internal: ", "default", - "; asyncSearch: ", - "default", "; autoscaling: ", "default", "; bulk: { (this: That, params: ", diff --git a/api_docs/lists.mdx b/api_docs/lists.mdx index fb83ae6f81a32..f66c8ea5cd6dc 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-10 +date: 2022-10-16 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 0393eb71f3632..73031132a0456 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-10 +date: 2022-10-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'management'] --- import managementObj from './management.devdocs.json'; diff --git a/api_docs/maps.devdocs.json b/api_docs/maps.devdocs.json index d40b99e5b5795..752becaa2ceb6 100644 --- a/api_docs/maps.devdocs.json +++ b/api_docs/maps.devdocs.json @@ -4470,7 +4470,7 @@ "StyleDescriptor", " | null | undefined; query?: ", "Query", - " | undefined; includeInFitToBounds?: boolean | undefined; }" + " | undefined; includeInFitToBounds?: boolean | undefined; parent?: string | undefined; }" ], "path": "x-pack/plugins/maps/common/descriptor_types/layer_descriptor_types.ts", "deprecated": false, diff --git a/api_docs/maps.mdx b/api_docs/maps.mdx index 9816101695ae5..74dee2dcf565e 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-10 +date: 2022-10-16 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 fe95c1e9304be..cb2fe700df5d2 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-10 +date: 2022-10-16 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 55d7ef71b1a20..2e99ae688ddd6 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-10 +date: 2022-10-16 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 da7874274db48..c95c7accae141 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-10 +date: 2022-10-16 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 2f60b591347cc..320b243a5d881 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-10 +date: 2022-10-16 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 28aac147b57ed..f284917c8e07c 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-10 +date: 2022-10-16 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 fecad3b643019..cfcf89d4219db 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-10 +date: 2022-10-16 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 2c08034995076..4a4216ec894ca 100644 --- a/api_docs/observability.devdocs.json +++ b/api_docs/observability.devdocs.json @@ -6050,7 +6050,9 @@ "TransportRequestOptions", " | undefined): Promise<", "UpdateResponse", - ">; }; [kInternal]: symbol | null; [kAsyncSearch]: symbol | null; [kAutoscaling]: symbol | null; [kCat]: symbol | null; [kCcr]: symbol | null; [kCluster]: symbol | null; [kDanglingIndices]: symbol | null; [kEnrich]: symbol | null; [kEql]: symbol | null; [kFeatures]: symbol | null; [kFleet]: symbol | null; [kGraph]: symbol | null; [kIlm]: symbol | null; [kIndices]: symbol | null; [kIngest]: symbol | null; [kLicense]: symbol | null; [kLogstash]: symbol | null; [kMigration]: symbol | null; [kMl]: symbol | null; [kMonitoring]: symbol | null; [kNodes]: symbol | null; [kRollup]: symbol | null; [kSearchableSnapshots]: symbol | null; [kSecurity]: symbol | null; [kShutdown]: symbol | null; [kSlm]: symbol | null; [kSnapshot]: symbol | null; [kSql]: symbol | null; [kSsl]: symbol | null; [kTasks]: symbol | null; [kTextStructure]: symbol | null; [kTransform]: symbol | null; [kWatcher]: symbol | null; [kXpack]: symbol | null; transport: ", + ">; }; asyncSearch: ", + "default", + "; [kInternal]: symbol | null; [kAsyncSearch]: symbol | null; [kAutoscaling]: symbol | null; [kCat]: symbol | null; [kCcr]: symbol | null; [kCluster]: symbol | null; [kDanglingIndices]: symbol | null; [kEnrich]: symbol | null; [kEql]: symbol | null; [kFeatures]: symbol | null; [kFleet]: symbol | null; [kGraph]: symbol | null; [kIlm]: symbol | null; [kIndices]: symbol | null; [kIngest]: symbol | null; [kLicense]: symbol | null; [kLogstash]: symbol | null; [kMigration]: symbol | null; [kMl]: symbol | null; [kMonitoring]: symbol | null; [kNodes]: symbol | null; [kRollup]: symbol | null; [kSearchableSnapshots]: symbol | null; [kSecurity]: symbol | null; [kShutdown]: symbol | null; [kSlm]: symbol | null; [kSnapshot]: symbol | null; [kSql]: symbol | null; [kSsl]: symbol | null; [kTasks]: symbol | null; [kTextStructure]: symbol | null; [kTransform]: symbol | null; [kWatcher]: symbol | null; [kXpack]: symbol | null; transport: ", "default", "; helpers: ", "default", @@ -6060,8 +6062,6 @@ "default", "; Internal: ", "default", - "; asyncSearch: ", - "default", "; autoscaling: ", "default", "; bulk: { (this: That, params: ", @@ -7759,7 +7759,7 @@ "section": "def-server.ObservabilityRouteHandlerResources", "text": "ObservabilityRouteHandlerResources" }, - ", { id: string; name: string; description: string; indicator: { type: string; params: { environment: string; service: string; transaction_type: string; transaction_name: string; 'threshold.us': number; }; } | { type: string; params: { environment: string; service: string; transaction_type: string; transaction_name: string; } & { good_status_codes?: (\"2xx\" | \"3xx\" | \"4xx\" | \"5xx\")[] | undefined; }; }; time_window: { duration: string; is_rolling: boolean; }; budgeting_method: \"occurrences\"; objective: { target: number; }; revision: number; created_at: Date; updated_at: Date; }, ", + ", { id: string; name: string; description: string; indicator: { type: string; params: { environment: string; service: string; transaction_type: string; transaction_name: string; 'threshold.us': number; }; } | { type: string; params: { environment: string; service: string; transaction_type: string; transaction_name: string; } & { good_status_codes?: (\"2xx\" | \"3xx\" | \"4xx\" | \"5xx\")[] | undefined; }; }; time_window: { duration: string; is_rolling: boolean; }; budgeting_method: \"occurrences\"; objective: { target: number; }; summary: { sli_value: number; error_budget: { initial: number; consumed: number; remaining: number; }; }; revision: number; created_at: Date; updated_at: Date; }, ", { "pluginId": "observability", "scope": "server", @@ -8109,7 +8109,7 @@ "section": "def-server.ObservabilityRouteHandlerResources", "text": "ObservabilityRouteHandlerResources" }, - ", { id: string; name: string; description: string; indicator: { type: string; params: { environment: string; service: string; transaction_type: string; transaction_name: string; 'threshold.us': number; }; } | { type: string; params: { environment: string; service: string; transaction_type: string; transaction_name: string; } & { good_status_codes?: (\"2xx\" | \"3xx\" | \"4xx\" | \"5xx\")[] | undefined; }; }; time_window: { duration: string; is_rolling: boolean; }; budgeting_method: \"occurrences\"; objective: { target: number; }; revision: number; created_at: Date; updated_at: Date; }, ", + ", { id: string; name: string; description: string; indicator: { type: string; params: { environment: string; service: string; transaction_type: string; transaction_name: string; 'threshold.us': number; }; } | { type: string; params: { environment: string; service: string; transaction_type: string; transaction_name: string; } & { good_status_codes?: (\"2xx\" | \"3xx\" | \"4xx\" | \"5xx\")[] | undefined; }; }; time_window: { duration: string; is_rolling: boolean; }; budgeting_method: \"occurrences\"; objective: { target: number; }; summary: { sli_value: number; error_budget: { initial: number; consumed: number; remaining: number; }; }; revision: number; created_at: Date; updated_at: Date; }, ", { "pluginId": "observability", "scope": "server", diff --git a/api_docs/observability.mdx b/api_docs/observability.mdx index a3c878a3cf2bf..6f94652267234 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-10 +date: 2022-10-16 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 e6cbfa7500c92..90e0ae08fb61a 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-10 +date: 2022-10-16 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 020ecc70d4218..925769d49337e 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-10 +date: 2022-10-16 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -15,13 +15,13 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | Count | Plugins or Packages with a
public API | Number of teams | |--------------|----------|------------------------| -| 487 | 404 | 38 | +| 488 | 405 | 38 | ### Public API health stats | API Count | Any Count | Missing comments | Missing exports | |--------------|----------|-----------------|--------| -| 32173 | 179 | 21657 | 1023 | +| 32298 | 179 | 21765 | 1023 | ## Plugin Directory @@ -30,12 +30,12 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [Response Ops](https://github.com/orgs/elastic/teams/response-ops) | - | 213 | 0 | 208 | 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) | - | 379 | 0 | 370 | 24 | +| | [Response Ops](https://github.com/orgs/elastic/teams/response-ops) | - | 381 | 0 | 372 | 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 | 71 | 28 | +| | [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) | Chat available on Elastic Cloud deployments for quicker assistance. | 1 | 0 | 0 | 0 | @@ -44,17 +44,17 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | cloudLinks | [Kibana Core](https://github.com/orgs/elastic/teams/@kibana-core) | Adds the links to the Elastic Cloud console | 0 | 0 | 0 | 0 | | | [Cloud Security Posture](https://github.com/orgs/elastic/teams/cloud-posture-security) | The cloud security posture plugin | 18 | 0 | 2 | 3 | | | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 13 | 0 | 13 | 1 | -| | [Kibana Presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | The Controls Plugin contains embeddable components intended to create a simple query interface for end users, and a powerful editing suite that allows dashboard authors to build controls | 212 | 0 | 204 | 7 | -| | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 2689 | 0 | 23 | 0 | +| | [Kibana Presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | The Controls Plugin contains embeddable components intended to create a simple query interface for end users, and a powerful editing suite that allows dashboard authors to build controls | 213 | 0 | 205 | 7 | +| | [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 | 104 | 0 | 85 | 1 | +| | [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 | | | [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. | 3221 | 33 | 2513 | 24 | +| | [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 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Reusable data view field editor across Kibana | 60 | 0 | 30 | 0 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Data view management app | 2 | 0 | 2 | 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. | 983 | 0 | 225 | 2 | +| | [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. | 992 | 0 | 228 | 2 | | | [Machine Learning UI](https://github.com/orgs/elastic/teams/ml-ui) | The Data Visualizer tools help you understand your data, by analyzing the metrics and fields in a log file or an existing Elasticsearch index. | 28 | 3 | 24 | 1 | | | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 10 | 0 | 8 | 2 | | | [Data Discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | This plugin contains the Discover application and the saved search embeddable. | 97 | 0 | 80 | 4 | @@ -67,8 +67,8 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | The Event Annotation service contains expressions for event annotations | 174 | 0 | 174 | 3 | | | [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. | 57 | 0 | 57 | 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. | 105 | 0 | 101 | 3 | +| | [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 | | | [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,12 +78,12 @@ 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. | 153 | 0 | 143 | 9 | +| | [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 | | | [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 | -| | [@elastic/kibana-app-services](https://github.com/orgs/elastic/teams/team:AppServicesUx) | File upload, download, sharing, and serving over HTTP implementation in Kibana. | 270 | 0 | 15 | 2 | +| | [@elastic/kibana-app-services](https://github.com/orgs/elastic/teams/team:AppServicesUx) | File upload, download, sharing, and serving over HTTP implementation in Kibana. | 260 | 0 | 14 | 2 | | | [Fleet](https://github.com/orgs/elastic/teams/fleet) | - | 996 | 3 | 893 | 17 | | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 68 | 0 | 14 | 5 | | globalSearchBar | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 0 | 0 | 0 | 0 | @@ -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. | 656 | 0 | 565 | 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. | 658 | 0 | 567 | 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 | @@ -139,7 +139,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | searchprofiler | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 0 | 0 | 0 | 0 | | | [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) | - | 3 | 0 | 3 | 1 | +| | [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 | | | [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 | @@ -155,10 +155,10 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [Security solution](https://github.com/orgs/elastic/teams/security-solution) | - | 452 | 1 | 346 | 33 | | | [Machine Learning UI](https://github.com/orgs/elastic/teams/ml-ui) | This plugin provides access to the transforms features provided by Elastic. Transforms enable you to convert existing Elasticsearch indices into summarized indices, which provide opportunities for new insights and analytics. | 4 | 0 | 4 | 1 | | translations | [Kibana Localization](https://github.com/orgs/elastic/teams/kibana-localization) | - | 0 | 0 | 0 | 0 | -| | [Response Ops](https://github.com/orgs/elastic/teams/response-ops) | - | 517 | 1 | 489 | 49 | +| | [Response Ops](https://github.com/orgs/elastic/teams/response-ops) | - | 518 | 1 | 489 | 49 | | | [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 | 61 | 0 | 59 | 2 | +| | [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 | | | [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 | @@ -178,7 +178,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Registers the vega visualization. Is the elastic version of vega and vega-lite libraries. | 2 | 0 | 2 | 0 | | | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Contains the vislib visualizations. These are the classical area/line/bar, pie, gauge/goal and heatmap charts. We want to replace them with elastic-charts. | 26 | 0 | 25 | 1 | | | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Contains the new xy-axis chart using the elastic-charts library, which will eventually replace the vislib xy-axis charts including bar, area, and line. | 53 | 0 | 50 | 5 | -| | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Contains the shared architecture among all the legacy visualizations, e.g. the visualization type registry or the visualization embeddable. | 729 | 12 | 699 | 18 | +| | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Contains the shared architecture among all the legacy visualizations, e.g. the visualization type registry or the visualization embeddable. | 755 | 12 | 725 | 18 | | watcher | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 0 | 0 | 0 | 0 | ## Package Directory @@ -187,7 +187,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] |--------------|----------------|-----------|--------------|----------|---------------|--------| | | [Owner missing] | - | 11 | 5 | 11 | 0 | | | Machine Learning UI | React components for AIOps related efforts. | 6 | 0 | 6 | 0 | -| | Machine Learning UI | Static utilities for AIOps related efforts. | 51 | 0 | 26 | 0 | +| | Machine Learning UI | Static utilities for AIOps related efforts. | 53 | 0 | 22 | 0 | | | [Owner missing] | Alerts components and hooks | 9 | 1 | 9 | 0 | | | Kibana Core | Kibana Analytics tool | 73 | 0 | 73 | 2 | | | Kibana Core | - | 96 | 0 | 0 | 0 | @@ -199,6 +199,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [Owner missing] | Elastic APM trace data generator | 74 | 0 | 74 | 13 | | | [Owner missing] | - | 11 | 0 | 11 | 0 | | | [Owner missing] | - | 10 | 0 | 10 | 0 | +| | [Owner missing] | - | 4 | 0 | 3 | 0 | | | [Owner missing] | - | 76 | 0 | 76 | 0 | | | [Owner missing] | - | 7 | 0 | 2 | 0 | | | [Owner missing] | - | 3 | 0 | 3 | 0 | @@ -245,7 +246,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | Kibana Core | - | 4 | 0 | 4 | 0 | | | Kibana Core | - | 15 | 0 | 13 | 2 | | | Kibana Core | - | 38 | 1 | 34 | 0 | -| | Kibana Core | - | 99 | 0 | 51 | 0 | +| | Kibana Core | - | 103 | 0 | 53 | 0 | | | Kibana Core | - | 33 | 0 | 29 | 0 | | | Kibana Core | - | 15 | 1 | 15 | 0 | | | Kibana Core | - | 4 | 0 | 4 | 0 | diff --git a/api_docs/presentation_util.mdx b/api_docs/presentation_util.mdx index 72ab2b6b9b0c1..f2a2b287d0e87 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-10 +date: 2022-10-16 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 c374d8ff9bb23..9f5d92d5055a2 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-10 +date: 2022-10-16 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 2cd2b8b545029..8938c2852372f 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-10 +date: 2022-10-16 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 25fde92c9c027..1242ea92225f6 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-10 +date: 2022-10-16 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 a7ce02fa445ae..9232214542bfd 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-10 +date: 2022-10-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'rollup'] --- import rollupObj from './rollup.devdocs.json'; diff --git a/api_docs/rule_registry.devdocs.json b/api_docs/rule_registry.devdocs.json index 37e78ced1236a..942341236243f 100644 --- a/api_docs/rule_registry.devdocs.json +++ b/api_docs/rule_registry.devdocs.json @@ -1917,7 +1917,7 @@ "\nID of the Kibana feature associated with the index.\nUsed by alerts-as-data RBAC.\n\nNote from @dhurley14\nThe purpose of the `feature` param is to force the user to update\nthe data structure which contains the mapping of consumers to alerts\nas data indices. The idea is it is typed such that it forces the\nuser to go to the code and modify it. At least until a better system\nis put in place or we move the alerts as data client out of rule registry.\n" ], "signature": [ - "\"infrastructure\" | \"observability\" | \"logs\" | \"apm\" | \"uptime\" | \"siem\"" + "\"infrastructure\" | \"apm\" | \"observability\" | \"logs\" | \"uptime\" | \"siem\"" ], "path": "x-pack/plugins/rule_registry/server/rule_data_plugin_service/index_options.ts", "deprecated": false, diff --git a/api_docs/rule_registry.mdx b/api_docs/rule_registry.mdx index 36968e9f6d84c..5374acb8bb636 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-10 +date: 2022-10-16 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 cfd864e5e1e7c..9fafb186331b7 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-10 +date: 2022-10-16 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 3ddfe47eb5d24..a3e7550be2a15 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-10 +date: 2022-10-16 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 f947e389666e7..1bb02ccfed6b3 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-10 +date: 2022-10-16 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 092940749757f..16953be499b6d 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-10 +date: 2022-10-16 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 6e3788871ed75..1d5257ea32f55 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-10 +date: 2022-10-16 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 b0006411b10ce..0ca9d586cbd0f 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-10 +date: 2022-10-16 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 4694eea70cade..cfbedf67c9ee3 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-10 +date: 2022-10-16 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 800a8386708e0..f40f427ef754e 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-10 +date: 2022-10-16 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 e3e29cd303353..f1a146fea85ec 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-10 +date: 2022-10-16 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 5fe2fe5894253..0a2ed70f75647 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-10 +date: 2022-10-16 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 33d50cb8babe2..f2ea5debb134b 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-10 +date: 2022-10-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'securitySolution'] --- import securitySolutionObj from './security_solution.devdocs.json'; diff --git a/api_docs/session_view.devdocs.json b/api_docs/session_view.devdocs.json index d8641dfbf034f..4d71f22e2cadb 100644 --- a/api_docs/session_view.devdocs.json +++ b/api_docs/session_view.devdocs.json @@ -53,8 +53,37 @@ "initialIsOpen": false } ], - "enums": [], - "misc": [], + "enums": [ + { + "parentPluginId": "sessionView", + "id": "def-public.EventAction", + "type": "Enum", + "tags": [], + "label": "EventAction", + "description": [], + "path": "x-pack/plugins/session_view/common/types/process_tree/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + } + ], + "misc": [ + { + "parentPluginId": "sessionView", + "id": "def-public.ENTRY_SESSION_ENTITY_ID_PROPERTY", + "type": "string", + "tags": [], + "label": "ENTRY_SESSION_ENTITY_ID_PROPERTY", + "description": [], + "signature": [ + "\"process.entry_leader.entity_id\"" + ], + "path": "x-pack/plugins/session_view/common/constants.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + } + ], "objects": [] }, "server": { @@ -69,8 +98,37 @@ "classes": [], "functions": [], "interfaces": [], - "enums": [], - "misc": [], + "enums": [ + { + "parentPluginId": "sessionView", + "id": "def-common.EventAction", + "type": "Enum", + "tags": [], + "label": "EventAction", + "description": [], + "path": "x-pack/plugins/session_view/common/types/process_tree/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + } + ], + "misc": [ + { + "parentPluginId": "sessionView", + "id": "def-common.ENTRY_SESSION_ENTITY_ID_PROPERTY", + "type": "string", + "tags": [], + "label": "ENTRY_SESSION_ENTITY_ID_PROPERTY", + "description": [], + "signature": [ + "\"process.entry_leader.entity_id\"" + ], + "path": "x-pack/plugins/session_view/common/constants.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + } + ], "objects": [] } } \ No newline at end of file diff --git a/api_docs/session_view.mdx b/api_docs/session_view.mdx index 77ba39d41f48e..d25ebf839c915 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-10 +date: 2022-10-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'sessionView'] --- import sessionViewObj from './session_view.devdocs.json'; @@ -21,10 +21,24 @@ Contact [Security Team](https://github.com/orgs/elastic/teams/security-team) for | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 3 | 0 | 3 | 1 | +| 7 | 0 | 7 | 1 | ## Client ### Interfaces +### Enums + + +### Consts, variables and types + + +## Common + +### Enums + + +### Consts, variables and types + + diff --git a/api_docs/share.mdx b/api_docs/share.mdx index df0619d9b5290..8b46a76f72371 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-10 +date: 2022-10-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'share'] --- import shareObj from './share.devdocs.json'; diff --git a/api_docs/snapshot_restore.mdx b/api_docs/snapshot_restore.mdx index 1c86c9c84811f..5374f865f469d 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-10 +date: 2022-10-16 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 04356137a0932..3fef0542977b2 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-10 +date: 2022-10-16 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 909167b8d55ce..29f005eb91ed2 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-10 +date: 2022-10-16 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 6c49650732577..f4e98e66821cd 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-10 +date: 2022-10-16 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 1217311901de7..22bafa3fb4532 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-10 +date: 2022-10-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'taskManager'] --- import taskManagerObj from './task_manager.devdocs.json'; diff --git a/api_docs/telemetry.devdocs.json b/api_docs/telemetry.devdocs.json index 27c6790692801..5749144af5150 100644 --- a/api_docs/telemetry.devdocs.json +++ b/api_docs/telemetry.devdocs.json @@ -617,7 +617,7 @@ "When the data comes from a matching index-pattern, the name of the pattern" ], "signature": [ - "\"search\" | \"logstash\" | \"enterprise-search\" | \"app-search\" | \"magento2\" | \"magento\" | \"shopify\" | \"wordpress\" | \"drupal\" | \"joomla\" | \"sharepoint\" | \"squarespace\" | \"sitecore\" | \"weebly\" | \"acquia\" | \"filebeat\" | \"metricbeat\" | \"apm\" | \"functionbeat\" | \"heartbeat\" | \"fluentd\" | \"telegraf\" | \"prometheusbeat\" | \"fluentbit\" | \"nginx\" | \"apache\" | \"endgame\" | \"logs-endpoint\" | \"metrics-endpoint\" | \"siem-signals\" | \"auditbeat\" | \"winlogbeat\" | \"packetbeat\" | \"tomcat\" | \"artifactory\" | \"aruba\" | \"barracuda\" | \"bluecoat\" | \"arcsight\" | \"checkpoint\" | \"cisco\" | \"citrix\" | \"cyberark\" | \"cylance\" | \"fireeye\" | \"fortinet\" | \"infoblox\" | \"kaspersky\" | \"mcafee\" | \"paloaltonetworks\" | \"rsa\" | \"snort\" | \"sonicwall\" | \"sophos\" | \"squid\" | \"symantec\" | \"tippingpoint\" | \"trendmicro\" | \"tripwire\" | \"zscaler\" | \"zeek\" | \"sigma_doc\" | \"ecs-corelight\" | \"suricata\" | \"wazuh\" | \"meow\" | \"host_risk_score\" | \"user_risk_score\" | undefined" + "\"search\" | \"apm\" | \"logstash\" | \"enterprise-search\" | \"app-search\" | \"magento2\" | \"magento\" | \"shopify\" | \"wordpress\" | \"drupal\" | \"joomla\" | \"sharepoint\" | \"squarespace\" | \"sitecore\" | \"weebly\" | \"acquia\" | \"filebeat\" | \"metricbeat\" | \"functionbeat\" | \"heartbeat\" | \"fluentd\" | \"telegraf\" | \"prometheusbeat\" | \"fluentbit\" | \"nginx\" | \"apache\" | \"endgame\" | \"logs-endpoint\" | \"metrics-endpoint\" | \"siem-signals\" | \"auditbeat\" | \"winlogbeat\" | \"packetbeat\" | \"tomcat\" | \"artifactory\" | \"aruba\" | \"barracuda\" | \"bluecoat\" | \"arcsight\" | \"checkpoint\" | \"cisco\" | \"citrix\" | \"cyberark\" | \"cylance\" | \"fireeye\" | \"fortinet\" | \"infoblox\" | \"kaspersky\" | \"mcafee\" | \"paloaltonetworks\" | \"rsa\" | \"snort\" | \"sonicwall\" | \"sophos\" | \"squid\" | \"symantec\" | \"tippingpoint\" | \"trendmicro\" | \"tripwire\" | \"zscaler\" | \"zeek\" | \"sigma_doc\" | \"ecs-corelight\" | \"suricata\" | \"wazuh\" | \"meow\" | \"host_risk_score\" | \"user_risk_score\" | undefined" ], "path": "src/plugins/telemetry/server/telemetry_collection/get_data_telemetry/get_data_telemetry.ts", "deprecated": false, diff --git a/api_docs/telemetry.mdx b/api_docs/telemetry.mdx index bcedaaf0d81ff..2d9a6aa72b2b8 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-10 +date: 2022-10-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetry'] --- import telemetryObj from './telemetry.devdocs.json'; diff --git a/api_docs/telemetry_collection_manager.devdocs.json b/api_docs/telemetry_collection_manager.devdocs.json index f5e1d86713cd2..efd0378614ce7 100644 --- a/api_docs/telemetry_collection_manager.devdocs.json +++ b/api_docs/telemetry_collection_manager.devdocs.json @@ -246,7 +246,9 @@ "TransportRequestOptions", " | undefined): Promise<", "UpdateResponse", - ">; }; [kInternal]: symbol | null; [kAsyncSearch]: symbol | null; [kAutoscaling]: symbol | null; [kCat]: symbol | null; [kCcr]: symbol | null; [kCluster]: symbol | null; [kDanglingIndices]: symbol | null; [kEnrich]: symbol | null; [kEql]: symbol | null; [kFeatures]: symbol | null; [kFleet]: symbol | null; [kGraph]: symbol | null; [kIlm]: symbol | null; [kIndices]: symbol | null; [kIngest]: symbol | null; [kLicense]: symbol | null; [kLogstash]: symbol | null; [kMigration]: symbol | null; [kMl]: symbol | null; [kMonitoring]: symbol | null; [kNodes]: symbol | null; [kRollup]: symbol | null; [kSearchableSnapshots]: symbol | null; [kSecurity]: symbol | null; [kShutdown]: symbol | null; [kSlm]: symbol | null; [kSnapshot]: symbol | null; [kSql]: symbol | null; [kSsl]: symbol | null; [kTasks]: symbol | null; [kTextStructure]: symbol | null; [kTransform]: symbol | null; [kWatcher]: symbol | null; [kXpack]: symbol | null; transport: ", + ">; }; asyncSearch: ", + "default", + "; [kInternal]: symbol | null; [kAsyncSearch]: symbol | null; [kAutoscaling]: symbol | null; [kCat]: symbol | null; [kCcr]: symbol | null; [kCluster]: symbol | null; [kDanglingIndices]: symbol | null; [kEnrich]: symbol | null; [kEql]: symbol | null; [kFeatures]: symbol | null; [kFleet]: symbol | null; [kGraph]: symbol | null; [kIlm]: symbol | null; [kIndices]: symbol | null; [kIngest]: symbol | null; [kLicense]: symbol | null; [kLogstash]: symbol | null; [kMigration]: symbol | null; [kMl]: symbol | null; [kMonitoring]: symbol | null; [kNodes]: symbol | null; [kRollup]: symbol | null; [kSearchableSnapshots]: symbol | null; [kSecurity]: symbol | null; [kShutdown]: symbol | null; [kSlm]: symbol | null; [kSnapshot]: symbol | null; [kSql]: symbol | null; [kSsl]: symbol | null; [kTasks]: symbol | null; [kTextStructure]: symbol | null; [kTransform]: symbol | null; [kWatcher]: symbol | null; [kXpack]: symbol | null; transport: ", "default", "; helpers: ", "default", @@ -256,8 +258,6 @@ "default", "; Internal: ", "default", - "; asyncSearch: ", - "default", "; autoscaling: ", "default", "; bulk: { (this: That, params: ", diff --git a/api_docs/telemetry_collection_manager.mdx b/api_docs/telemetry_collection_manager.mdx index 5d0c3054de25a..f938b64bdf41f 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-10 +date: 2022-10-16 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 e0bc1e797caaa..637896a586e1b 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-10 +date: 2022-10-16 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 b352bd4e0dca3..44d39840370a7 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-10 +date: 2022-10-16 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 77d1f454f2f5a..42a2933fdd542 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-10 +date: 2022-10-16 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 a010695c5c771..e1e52fa109b88 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-10 +date: 2022-10-16 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 4d851dc086fe4..bc8562980b05e 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-10 +date: 2022-10-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'transform'] --- import transformObj from './transform.devdocs.json'; diff --git a/api_docs/triggers_actions_ui.devdocs.json b/api_docs/triggers_actions_ui.devdocs.json index e9e5908c5ee26..1b74e68bed0b8 100644 --- a/api_docs/triggers_actions_ui.devdocs.json +++ b/api_docs/triggers_actions_ui.devdocs.json @@ -8164,7 +8164,7 @@ "label": "CoreQueryParams", "description": [], "signature": [ - "{ readonly aggField?: string | undefined; readonly termSize?: number | undefined; readonly termField?: string | undefined; readonly index: string | string[]; readonly timeField: string; readonly aggType: string; readonly timeWindowSize: number; readonly timeWindowUnit: string; readonly groupBy: string; }" + "{ readonly aggField?: string | undefined; readonly termSize?: number | undefined; readonly termField?: string | undefined; readonly filterKuery?: string | undefined; readonly index: string | string[]; readonly timeField: string; readonly aggType: string; readonly timeWindowSize: number; readonly timeWindowUnit: string; readonly groupBy: string; }" ], "path": "x-pack/plugins/triggers_actions_ui/server/data/lib/core_query_types.ts", "deprecated": false, @@ -8236,7 +8236,7 @@ "label": "TimeSeriesQuery", "description": [], "signature": [ - "{ readonly interval?: string | undefined; readonly aggField?: string | undefined; readonly termSize?: number | undefined; readonly termField?: string | undefined; readonly dateStart?: string | undefined; readonly dateEnd?: string | undefined; readonly index: string | string[]; readonly timeField: string; readonly aggType: string; readonly timeWindowSize: number; readonly timeWindowUnit: string; readonly groupBy: string; }" + "{ readonly interval?: string | undefined; readonly aggField?: string | undefined; readonly termSize?: number | undefined; readonly termField?: string | undefined; readonly dateStart?: string | undefined; readonly dateEnd?: string | undefined; readonly filterKuery?: string | undefined; readonly index: string | string[]; readonly timeField: string; readonly aggType: string; readonly timeWindowSize: number; readonly timeWindowUnit: string; readonly groupBy: string; }" ], "path": "x-pack/plugins/triggers_actions_ui/server/data/lib/time_series_types.ts", "deprecated": false, @@ -8358,6 +8358,23 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "triggersActionsUi", + "id": "def-server.CoreQueryParamsSchemaProperties.filterKuery", + "type": "Object", + "tags": [], + "label": "filterKuery", + "description": [ + "// filter field" + ], + "signature": [ + "Type", + "" + ], + "path": "x-pack/plugins/triggers_actions_ui/server/data/lib/core_query_types.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "triggersActionsUi", "id": "def-server.CoreQueryParamsSchemaProperties.termSize", diff --git a/api_docs/triggers_actions_ui.mdx b/api_docs/triggers_actions_ui.mdx index a4ab7aaa8680e..e427614eec60d 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-10 +date: 2022-10-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'triggersActionsUi'] --- import triggersActionsUiObj from './triggers_actions_ui.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 | |-------------------|-----------|------------------------|-----------------| -| 517 | 1 | 489 | 49 | +| 518 | 1 | 489 | 49 | ## Client diff --git a/api_docs/ui_actions.mdx b/api_docs/ui_actions.mdx index ba35eb86cbf0e..38fe2317df512 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-10 +date: 2022-10-16 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 45bddb4318d64..214a75140f6c3 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-10 +date: 2022-10-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'uiActionsEnhanced'] --- import uiActionsEnhancedObj from './ui_actions_enhanced.devdocs.json'; diff --git a/api_docs/unified_field_list.devdocs.json b/api_docs/unified_field_list.devdocs.json index 9ade69bc0eab0..ac91e0235c30c 100644 --- a/api_docs/unified_field_list.devdocs.json +++ b/api_docs/unified_field_list.devdocs.json @@ -3,6 +3,153 @@ "client": { "classes": [], "functions": [ + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.FieldPopover", + "type": "Function", + "tags": [], + "label": "FieldPopover", + "description": [], + "signature": [ + "({ isOpen, closePopover, renderHeader, renderContent, ...otherPopoverProps }: React.PropsWithChildren<", + { + "pluginId": "unifiedFieldList", + "scope": "public", + "docId": "kibUnifiedFieldListPluginApi", + "section": "def-public.FieldPopoverProps", + "text": "FieldPopoverProps" + }, + ">) => JSX.Element" + ], + "path": "src/plugins/unified_field_list/public/components/field_popover/field_popover.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.FieldPopover.$1", + "type": "CompoundType", + "tags": [], + "label": "{\n isOpen,\n closePopover,\n renderHeader,\n renderContent,\n ...otherPopoverProps\n}", + "description": [], + "signature": [ + "React.PropsWithChildren<", + { + "pluginId": "unifiedFieldList", + "scope": "public", + "docId": "kibUnifiedFieldListPluginApi", + "section": "def-public.FieldPopoverProps", + "text": "FieldPopoverProps" + }, + ">" + ], + "path": "src/plugins/unified_field_list/public/components/field_popover/field_popover.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.FieldPopoverHeader", + "type": "Function", + "tags": [], + "label": "FieldPopoverHeader", + "description": [], + "signature": [ + "({ field, closePopover, buttonAddFieldToWorkspaceProps, buttonAddFilterProps, buttonEditFieldProps, buttonDeleteFieldProps, onAddFieldToWorkspace, onAddFilter, onEditField, onDeleteField, }: React.PropsWithChildren<", + { + "pluginId": "unifiedFieldList", + "scope": "public", + "docId": "kibUnifiedFieldListPluginApi", + "section": "def-public.FieldPopoverHeaderProps", + "text": "FieldPopoverHeaderProps" + }, + ">) => JSX.Element | null" + ], + "path": "src/plugins/unified_field_list/public/components/field_popover/field_popover_header.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.FieldPopoverHeader.$1", + "type": "CompoundType", + "tags": [], + "label": "{\n field,\n closePopover,\n buttonAddFieldToWorkspaceProps,\n buttonAddFilterProps,\n buttonEditFieldProps,\n buttonDeleteFieldProps,\n onAddFieldToWorkspace,\n onAddFilter,\n onEditField,\n onDeleteField,\n}", + "description": [], + "signature": [ + "React.PropsWithChildren<", + { + "pluginId": "unifiedFieldList", + "scope": "public", + "docId": "kibUnifiedFieldListPluginApi", + "section": "def-public.FieldPopoverHeaderProps", + "text": "FieldPopoverHeaderProps" + }, + ">" + ], + "path": "src/plugins/unified_field_list/public/components/field_popover/field_popover_header.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.FieldPopoverVisualize", + "type": "Function", + "tags": [], + "label": "FieldPopoverVisualize", + "description": [], + "signature": [ + "(props: React.PropsWithChildren<", + { + "pluginId": "unifiedFieldList", + "scope": "public", + "docId": "kibUnifiedFieldListPluginApi", + "section": "def-public.FieldPopoverVisualizeProps", + "text": "FieldPopoverVisualizeProps" + }, + ">) => JSX.Element" + ], + "path": "src/plugins/unified_field_list/public/components/field_popover/field_popover_visualize.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.FieldPopoverVisualize.$1", + "type": "CompoundType", + "tags": [], + "label": "props", + "description": [], + "signature": [ + "React.PropsWithChildren<", + { + "pluginId": "unifiedFieldList", + "scope": "public", + "docId": "kibUnifiedFieldListPluginApi", + "section": "def-public.FieldPopoverVisualizeProps", + "text": "FieldPopoverVisualizeProps" + }, + ">" + ], + "path": "src/plugins/unified_field_list/public/components/field_popover/field_popover_visualize.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, { "parentPluginId": "unifiedFieldList", "id": "def-public.FieldStats", @@ -59,102 +206,880 @@ }, { "parentPluginId": "unifiedFieldList", - "id": "def-public.loadFieldExisting", + "id": "def-public.FieldVisualizeButton", "type": "Function", "tags": [], - "label": "loadFieldExisting", + "label": "FieldVisualizeButton", "description": [], "signature": [ - "({\n data,\n dslQuery,\n fromDate,\n toDate,\n timeFieldName,\n dataViewsService,\n uiSettingsClient,\n dataView,\n}: FetchFieldExistenceParams) => Promise<{ indexPatternTitle: string; existingFieldNames: string[]; }>" + "React.FunctionComponent<", + { + "pluginId": "unifiedFieldList", + "scope": "public", + "docId": "kibUnifiedFieldListPluginApi", + "section": "def-public.FieldVisualizeButtonProps", + "text": "FieldVisualizeButtonProps" + }, + ">" ], - "path": "src/plugins/unified_field_list/public/services/field_existing/load_field_existing.ts", + "path": "src/plugins/unified_field_list/public/components/field_visualize_button/field_visualize_button.tsx", "deprecated": false, "trackAdoption": false, + "returnComment": [], "children": [ { "parentPluginId": "unifiedFieldList", - "id": "def-public.loadFieldExisting.$1", - "type": "Object", + "id": "def-public.FieldVisualizeButton.$1", + "type": "CompoundType", "tags": [], - "label": "{\n data,\n dslQuery,\n fromDate,\n toDate,\n timeFieldName,\n dataViewsService,\n uiSettingsClient,\n dataView,\n}", + "label": "props", "description": [], "signature": [ - "FetchFieldExistenceParams" + "P & { children?: React.ReactNode; }" ], - "path": "src/plugins/unified_field_list/public/services/field_existing/load_field_existing.ts", + "path": "node_modules/@types/react/index.d.ts", "deprecated": false, - "trackAdoption": false, - "isRequired": true + "trackAdoption": false + }, + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.FieldVisualizeButton.$2", + "type": "Any", + "tags": [], + "label": "context", + "description": [], + "signature": [ + "any" + ], + "path": "node_modules/@types/react/index.d.ts", + "deprecated": false, + "trackAdoption": false } ], - "returnComment": [], "initialIsOpen": false }, { "parentPluginId": "unifiedFieldList", - "id": "def-public.loadFieldStats", + "id": "def-public.getVisualizeInformation", "type": "Function", "tags": [], - "label": "loadFieldStats", - "description": [], + "label": "getVisualizeInformation", + "description": [ + "\nReturns the field name and potentially href of the field or the first multi-field\nthat has a compatible visualize uiAction." + ], "signature": [ - "(params: FetchFieldStatsParams) => Promise<", - "FieldStatsResponse", - ">" + "(uiActions: ", + { + "pluginId": "uiActions", + "scope": "public", + "docId": "kibUiActionsPluginApi", + "section": "def-public.UiActionsStart", + "text": "UiActionsStart" + }, + ", field: ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewField", + "text": "DataViewField" + }, + ", dataView: ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataView", + "text": "DataView" + }, + " | undefined, contextualFields: string[], multiFields: ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewField", + "text": "DataViewField" + }, + "[]) => Promise<", + { + "pluginId": "unifiedFieldList", + "scope": "public", + "docId": "kibUnifiedFieldListPluginApi", + "section": "def-public.VisualizeInformation", + "text": "VisualizeInformation" + }, + " | undefined>" ], - "path": "src/plugins/unified_field_list/public/services/field_stats/index.tsx", + "path": "src/plugins/unified_field_list/public/components/field_visualize_button/visualize_trigger_utils.ts", "deprecated": false, "trackAdoption": false, "children": [ { "parentPluginId": "unifiedFieldList", - "id": "def-public.loadFieldStats.$1", + "id": "def-public.getVisualizeInformation.$1", "type": "Object", "tags": [], - "label": "params", + "label": "uiActions", "description": [], "signature": [ - "FetchFieldStatsParams" + { + "pluginId": "uiActions", + "scope": "public", + "docId": "kibUiActionsPluginApi", + "section": "def-public.UiActionsStart", + "text": "UiActionsStart" + } ], - "path": "src/plugins/unified_field_list/public/services/field_stats/index.tsx", + "path": "src/plugins/unified_field_list/public/components/field_visualize_button/visualize_trigger_utils.ts", "deprecated": false, "trackAdoption": false, "isRequired": true - } - ], - "returnComment": [], - "initialIsOpen": false - } - ], - "interfaces": [ - { - "parentPluginId": "unifiedFieldList", - "id": "def-public.BucketedAggregation", - "type": "Interface", - "tags": [], - "label": "BucketedAggregation", - "description": [], - "signature": [ - "BucketedAggregation", - "" - ], - "path": "src/plugins/unified_field_list/common/types/stats.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ + }, { "parentPluginId": "unifiedFieldList", - "id": "def-public.BucketedAggregation.buckets", + "id": "def-public.getVisualizeInformation.$2", + "type": "Object", + "tags": [], + "label": "field", + "description": [], + "signature": [ + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewField", + "text": "DataViewField" + } + ], + "path": "src/plugins/unified_field_list/public/components/field_visualize_button/visualize_trigger_utils.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.getVisualizeInformation.$3", + "type": "Object", + "tags": [], + "label": "dataView", + "description": [], + "signature": [ + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataView", + "text": "DataView" + }, + " | undefined" + ], + "path": "src/plugins/unified_field_list/public/components/field_visualize_button/visualize_trigger_utils.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + }, + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.getVisualizeInformation.$4", "type": "Array", "tags": [], - "label": "buckets", + "label": "contextualFields", "description": [], "signature": [ - "{ key: KeyType; count: number; }[]" + "string[]" ], - "path": "src/plugins/unified_field_list/common/types/stats.ts", + "path": "src/plugins/unified_field_list/public/components/field_visualize_button/visualize_trigger_utils.ts", "deprecated": false, - "trackAdoption": false + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.getVisualizeInformation.$5", + "type": "Array", + "tags": [], + "label": "multiFields", + "description": [], + "signature": [ + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewField", + "text": "DataViewField" + }, + "[]" + ], + "path": "src/plugins/unified_field_list/public/components/field_visualize_button/visualize_trigger_utils.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.loadFieldExisting", + "type": "Function", + "tags": [], + "label": "loadFieldExisting", + "description": [], + "signature": [ + "({\n data,\n dslQuery,\n fromDate,\n toDate,\n timeFieldName,\n dataViewsService,\n uiSettingsClient,\n dataView,\n}: FetchFieldExistenceParams) => Promise<{ indexPatternTitle: string; existingFieldNames: string[]; }>" + ], + "path": "src/plugins/unified_field_list/public/services/field_existing/load_field_existing.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.loadFieldExisting.$1", + "type": "Object", + "tags": [], + "label": "{\n data,\n dslQuery,\n fromDate,\n toDate,\n timeFieldName,\n dataViewsService,\n uiSettingsClient,\n dataView,\n}", + "description": [], + "signature": [ + "FetchFieldExistenceParams" + ], + "path": "src/plugins/unified_field_list/public/services/field_existing/load_field_existing.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.loadFieldStats", + "type": "Function", + "tags": [], + "label": "loadFieldStats", + "description": [], + "signature": [ + "(params: FetchFieldStatsParams) => Promise<", + "FieldStatsResponse", + ">" + ], + "path": "src/plugins/unified_field_list/public/services/field_stats/index.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.loadFieldStats.$1", + "type": "Object", + "tags": [], + "label": "params", + "description": [], + "signature": [ + "FetchFieldStatsParams" + ], + "path": "src/plugins/unified_field_list/public/services/field_stats/index.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.triggerVisualizeActions", + "type": "Function", + "tags": [], + "label": "triggerVisualizeActions", + "description": [], + "signature": [ + "(uiActions: ", + { + "pluginId": "uiActions", + "scope": "public", + "docId": "kibUiActionsPluginApi", + "section": "def-public.UiActionsStart", + "text": "UiActionsStart" + }, + ", field: ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewField", + "text": "DataViewField" + }, + ", contextualFields: string[], originatingApp: string, dataView: ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataView", + "text": "DataView" + }, + " | undefined) => void" + ], + "path": "src/plugins/unified_field_list/public/components/field_visualize_button/visualize_trigger_utils.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.triggerVisualizeActions.$1", + "type": "Object", + "tags": [], + "label": "uiActions", + "description": [], + "signature": [ + { + "pluginId": "uiActions", + "scope": "public", + "docId": "kibUiActionsPluginApi", + "section": "def-public.UiActionsStart", + "text": "UiActionsStart" + } + ], + "path": "src/plugins/unified_field_list/public/components/field_visualize_button/visualize_trigger_utils.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.triggerVisualizeActions.$2", + "type": "Object", + "tags": [], + "label": "field", + "description": [], + "signature": [ + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewField", + "text": "DataViewField" + } + ], + "path": "src/plugins/unified_field_list/public/components/field_visualize_button/visualize_trigger_utils.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.triggerVisualizeActions.$3", + "type": "Array", + "tags": [], + "label": "contextualFields", + "description": [], + "signature": [ + "string[]" + ], + "path": "src/plugins/unified_field_list/public/components/field_visualize_button/visualize_trigger_utils.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.triggerVisualizeActions.$4", + "type": "string", + "tags": [], + "label": "originatingApp", + "description": [], + "signature": [ + "string" + ], + "path": "src/plugins/unified_field_list/public/components/field_visualize_button/visualize_trigger_utils.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.triggerVisualizeActions.$5", + "type": "Object", + "tags": [], + "label": "dataView", + "description": [], + "signature": [ + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataView", + "text": "DataView" + }, + " | undefined" + ], + "path": "src/plugins/unified_field_list/public/components/field_visualize_button/visualize_trigger_utils.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.triggerVisualizeActionsTextBasedLanguages", + "type": "Function", + "tags": [], + "label": "triggerVisualizeActionsTextBasedLanguages", + "description": [], + "signature": [ + "(uiActions: ", + { + "pluginId": "uiActions", + "scope": "public", + "docId": "kibUiActionsPluginApi", + "section": "def-public.UiActionsStart", + "text": "UiActionsStart" + }, + ", contextualFields: string[], originatingApp: string, dataView: ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataView", + "text": "DataView" + }, + " | undefined, query: ", + "AggregateQuery", + " | undefined) => void" + ], + "path": "src/plugins/unified_field_list/public/components/field_visualize_button/visualize_trigger_utils.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.triggerVisualizeActionsTextBasedLanguages.$1", + "type": "Object", + "tags": [], + "label": "uiActions", + "description": [], + "signature": [ + { + "pluginId": "uiActions", + "scope": "public", + "docId": "kibUiActionsPluginApi", + "section": "def-public.UiActionsStart", + "text": "UiActionsStart" + } + ], + "path": "src/plugins/unified_field_list/public/components/field_visualize_button/visualize_trigger_utils.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.triggerVisualizeActionsTextBasedLanguages.$2", + "type": "Array", + "tags": [], + "label": "contextualFields", + "description": [], + "signature": [ + "string[]" + ], + "path": "src/plugins/unified_field_list/public/components/field_visualize_button/visualize_trigger_utils.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.triggerVisualizeActionsTextBasedLanguages.$3", + "type": "string", + "tags": [], + "label": "originatingApp", + "description": [], + "signature": [ + "string" + ], + "path": "src/plugins/unified_field_list/public/components/field_visualize_button/visualize_trigger_utils.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.triggerVisualizeActionsTextBasedLanguages.$4", + "type": "Object", + "tags": [], + "label": "dataView", + "description": [], + "signature": [ + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataView", + "text": "DataView" + }, + " | undefined" + ], + "path": "src/plugins/unified_field_list/public/components/field_visualize_button/visualize_trigger_utils.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + }, + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.triggerVisualizeActionsTextBasedLanguages.$5", + "type": "CompoundType", + "tags": [], + "label": "query", + "description": [], + "signature": [ + "AggregateQuery", + " | undefined" + ], + "path": "src/plugins/unified_field_list/public/components/field_visualize_button/visualize_trigger_utils.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [], + "initialIsOpen": false + } + ], + "interfaces": [ + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.BucketedAggregation", + "type": "Interface", + "tags": [], + "label": "BucketedAggregation", + "description": [], + "signature": [ + "BucketedAggregation", + "" + ], + "path": "src/plugins/unified_field_list/common/types/stats.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.BucketedAggregation.buckets", + "type": "Array", + "tags": [], + "label": "buckets", + "description": [], + "signature": [ + "{ key: KeyType; count: number; }[]" + ], + "path": "src/plugins/unified_field_list/common/types/stats.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.FieldPopoverHeaderProps", + "type": "Interface", + "tags": [], + "label": "FieldPopoverHeaderProps", + "description": [], + "path": "src/plugins/unified_field_list/public/components/field_popover/field_popover_header.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.FieldPopoverHeaderProps.field", + "type": "Object", + "tags": [], + "label": "field", + "description": [], + "signature": [ + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewField", + "text": "DataViewField" + } + ], + "path": "src/plugins/unified_field_list/public/components/field_popover/field_popover_header.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.FieldPopoverHeaderProps.closePopover", + "type": "Function", + "tags": [], + "label": "closePopover", + "description": [], + "signature": [ + "() => void" + ], + "path": "src/plugins/unified_field_list/public/components/field_popover/field_popover_header.tsx", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [] + }, + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.FieldPopoverHeaderProps.buttonAddFieldToWorkspaceProps", + "type": "Object", + "tags": [], + "label": "buttonAddFieldToWorkspaceProps", + "description": [], + "signature": [ + "Partial<", + "EuiButtonIconProps", + "> | undefined" + ], + "path": "src/plugins/unified_field_list/public/components/field_popover/field_popover_header.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.FieldPopoverHeaderProps.buttonAddFilterProps", + "type": "Object", + "tags": [], + "label": "buttonAddFilterProps", + "description": [], + "signature": [ + "Partial<", + "EuiButtonIconProps", + "> | undefined" + ], + "path": "src/plugins/unified_field_list/public/components/field_popover/field_popover_header.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.FieldPopoverHeaderProps.buttonEditFieldProps", + "type": "Object", + "tags": [], + "label": "buttonEditFieldProps", + "description": [], + "signature": [ + "Partial<", + "EuiButtonIconProps", + "> | undefined" + ], + "path": "src/plugins/unified_field_list/public/components/field_popover/field_popover_header.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.FieldPopoverHeaderProps.buttonDeleteFieldProps", + "type": "Object", + "tags": [], + "label": "buttonDeleteFieldProps", + "description": [], + "signature": [ + "Partial<", + "EuiButtonIconProps", + "> | undefined" + ], + "path": "src/plugins/unified_field_list/public/components/field_popover/field_popover_header.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.FieldPopoverHeaderProps.onAddFieldToWorkspace", + "type": "Function", + "tags": [], + "label": "onAddFieldToWorkspace", + "description": [], + "signature": [ + "((field: ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewField", + "text": "DataViewField" + }, + ") => unknown) | undefined" + ], + "path": "src/plugins/unified_field_list/public/components/field_popover/field_popover_header.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.FieldPopoverHeaderProps.onAddFieldToWorkspace.$1", + "type": "Object", + "tags": [], + "label": "field", + "description": [], + "signature": [ + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewField", + "text": "DataViewField" + } + ], + "path": "src/plugins/unified_field_list/public/components/field_popover/field_popover_header.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.FieldPopoverHeaderProps.onAddFilter", + "type": "Function", + "tags": [], + "label": "onAddFilter", + "description": [], + "signature": [ + { + "pluginId": "unifiedFieldList", + "scope": "public", + "docId": "kibUnifiedFieldListPluginApi", + "section": "def-public.AddFieldFilterHandler", + "text": "AddFieldFilterHandler" + }, + " | undefined" + ], + "path": "src/plugins/unified_field_list/public/components/field_popover/field_popover_header.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.FieldPopoverHeaderProps.onEditField", + "type": "Function", + "tags": [], + "label": "onEditField", + "description": [], + "signature": [ + "((fieldName: string) => unknown) | undefined" + ], + "path": "src/plugins/unified_field_list/public/components/field_popover/field_popover_header.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.FieldPopoverHeaderProps.onEditField.$1", + "type": "string", + "tags": [], + "label": "fieldName", + "description": [], + "signature": [ + "string" + ], + "path": "src/plugins/unified_field_list/public/components/field_popover/field_popover_header.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.FieldPopoverHeaderProps.onDeleteField", + "type": "Function", + "tags": [], + "label": "onDeleteField", + "description": [], + "signature": [ + "((fieldName: string) => unknown) | undefined" + ], + "path": "src/plugins/unified_field_list/public/components/field_popover/field_popover_header.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.FieldPopoverHeaderProps.onDeleteField.$1", + "type": "string", + "tags": [], + "label": "fieldName", + "description": [], + "signature": [ + "string" + ], + "path": "src/plugins/unified_field_list/public/components/field_popover/field_popover_header.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.FieldPopoverProps", + "type": "Interface", + "tags": [], + "label": "FieldPopoverProps", + "description": [], + "signature": [ + { + "pluginId": "unifiedFieldList", + "scope": "public", + "docId": "kibUnifiedFieldListPluginApi", + "section": "def-public.FieldPopoverProps", + "text": "FieldPopoverProps" + }, + " extends ", + "EuiPopoverProps" + ], + "path": "src/plugins/unified_field_list/public/components/field_popover/field_popover.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.FieldPopoverProps.renderHeader", + "type": "Function", + "tags": [], + "label": "renderHeader", + "description": [], + "signature": [ + "(() => React.ReactNode) | undefined" + ], + "path": "src/plugins/unified_field_list/public/components/field_popover/field_popover.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.FieldPopoverProps.renderContent", + "type": "Function", + "tags": [], + "label": "renderContent", + "description": [], + "signature": [ + "(() => React.ReactNode) | undefined" + ], + "path": "src/plugins/unified_field_list/public/components/field_popover/field_popover.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] } ], "initialIsOpen": false @@ -674,6 +1599,293 @@ ], "initialIsOpen": false }, + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.FieldVisualizeButtonProps", + "type": "Interface", + "tags": [], + "label": "FieldVisualizeButtonProps", + "description": [], + "path": "src/plugins/unified_field_list/public/components/field_visualize_button/field_visualize_button.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.FieldVisualizeButtonProps.field", + "type": "Object", + "tags": [], + "label": "field", + "description": [], + "signature": [ + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewField", + "text": "DataViewField" + } + ], + "path": "src/plugins/unified_field_list/public/components/field_visualize_button/field_visualize_button.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.FieldVisualizeButtonProps.dataView", + "type": "Object", + "tags": [], + "label": "dataView", + "description": [], + "signature": [ + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataView", + "text": "DataView" + } + ], + "path": "src/plugins/unified_field_list/public/components/field_visualize_button/field_visualize_button.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.FieldVisualizeButtonProps.originatingApp", + "type": "string", + "tags": [], + "label": "originatingApp", + "description": [], + "path": "src/plugins/unified_field_list/public/components/field_visualize_button/field_visualize_button.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.FieldVisualizeButtonProps.uiActions", + "type": "Object", + "tags": [], + "label": "uiActions", + "description": [], + "signature": [ + "{ readonly clear: () => void; readonly addTriggerAction: (triggerId: string, action: ", + { + "pluginId": "uiActions", + "scope": "public", + "docId": "kibUiActionsPluginApi", + "section": "def-public.ActionDefinition", + "text": "ActionDefinition" + }, + ") => void; readonly attachAction: (triggerId: string, actionId: string) => void; readonly detachAction: (triggerId: string, actionId: string) => void; readonly registerAction: >(definition: A) => ", + { + "pluginId": "uiActions", + "scope": "public", + "docId": "kibUiActionsPluginApi", + "section": "def-public.Action", + "text": "Action" + }, + "<", + "ActionContext", + ">; readonly registerTrigger: (trigger: ", + { + "pluginId": "uiActions", + "scope": "public", + "docId": "kibUiActionsPluginApi", + "section": "def-public.Trigger", + "text": "Trigger" + }, + ") => void; readonly unregisterAction: (actionId: string) => void; readonly getTrigger: (triggerId: string) => ", + "TriggerContract", + "; readonly hasAction: (actionId: string) => boolean; readonly getAction: >(id: string) => ", + { + "pluginId": "uiActions", + "scope": "public", + "docId": "kibUiActionsPluginApi", + "section": "def-public.Action", + "text": "Action" + }, + "<", + "ActionContext", + ">; readonly getTriggerActions: (triggerId: string) => ", + { + "pluginId": "uiActions", + "scope": "public", + "docId": "kibUiActionsPluginApi", + "section": "def-public.Action", + "text": "Action" + }, + "[]; readonly getTriggerCompatibleActions: (triggerId: string, context: object) => Promise<", + { + "pluginId": "uiActions", + "scope": "public", + "docId": "kibUiActionsPluginApi", + "section": "def-public.Action", + "text": "Action" + }, + "[]>; readonly executeTriggerActions: (triggerId: string, context: object) => Promise; readonly fork: () => ", + { + "pluginId": "uiActions", + "scope": "public", + "docId": "kibUiActionsPluginApi", + "section": "def-public.UiActionsService", + "text": "UiActionsService" + }, + "; }" + ], + "path": "src/plugins/unified_field_list/public/components/field_visualize_button/field_visualize_button.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.FieldVisualizeButtonProps.multiFields", + "type": "Array", + "tags": [], + "label": "multiFields", + "description": [], + "signature": [ + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewField", + "text": "DataViewField" + }, + "[] | undefined" + ], + "path": "src/plugins/unified_field_list/public/components/field_visualize_button/field_visualize_button.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.FieldVisualizeButtonProps.contextualFields", + "type": "Array", + "tags": [], + "label": "contextualFields", + "description": [], + "signature": [ + "string[] | undefined" + ], + "path": "src/plugins/unified_field_list/public/components/field_visualize_button/field_visualize_button.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.FieldVisualizeButtonProps.trackUiMetric", + "type": "Function", + "tags": [], + "label": "trackUiMetric", + "description": [], + "signature": [ + "((metricType: string, eventName: string | string[]) => void) | undefined" + ], + "path": "src/plugins/unified_field_list/public/components/field_visualize_button/field_visualize_button.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.FieldVisualizeButtonProps.trackUiMetric.$1", + "type": "string", + "tags": [], + "label": "metricType", + "description": [], + "signature": [ + "string" + ], + "path": "src/plugins/unified_field_list/public/components/field_visualize_button/field_visualize_button.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.FieldVisualizeButtonProps.trackUiMetric.$2", + "type": "CompoundType", + "tags": [], + "label": "eventName", + "description": [], + "signature": [ + "string | string[]" + ], + "path": "src/plugins/unified_field_list/public/components/field_visualize_button/field_visualize_button.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.FieldVisualizeButtonProps.buttonProps", + "type": "Object", + "tags": [], + "label": "buttonProps", + "description": [], + "signature": [ + "Partial<", + "EuiButtonProps", + "> | undefined" + ], + "path": "src/plugins/unified_field_list/public/components/field_visualize_button/field_visualize_button.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.FieldVisualizeButtonProps.wrapInContainer", + "type": "Function", + "tags": [], + "label": "wrapInContainer", + "description": [], + "signature": [ + "((element: React.ReactElement>) => React.ReactElement>) | undefined" + ], + "path": "src/plugins/unified_field_list/public/components/field_visualize_button/field_visualize_button.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.FieldVisualizeButtonProps.wrapInContainer.$1", + "type": "Object", + "tags": [], + "label": "element", + "description": [], + "signature": [ + "React.ReactElement>" + ], + "path": "src/plugins/unified_field_list/public/components/field_visualize_button/field_visualize_button.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + } + ], + "initialIsOpen": false + }, { "parentPluginId": "unifiedFieldList", "id": "def-public.NumberStatsResult", @@ -768,6 +1980,54 @@ } ], "initialIsOpen": false + }, + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.VisualizeInformation", + "type": "Interface", + "tags": [], + "label": "VisualizeInformation", + "description": [], + "path": "src/plugins/unified_field_list/public/components/field_visualize_button/visualize_trigger_utils.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.VisualizeInformation.field", + "type": "Object", + "tags": [], + "label": "field", + "description": [], + "signature": [ + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewField", + "text": "DataViewField" + } + ], + "path": "src/plugins/unified_field_list/public/components/field_visualize_button/visualize_trigger_utils.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.VisualizeInformation.href", + "type": "string", + "tags": [], + "label": "href", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "src/plugins/unified_field_list/public/components/field_visualize_button/visualize_trigger_utils.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false } ], "enums": [], @@ -788,7 +2048,7 @@ "section": "def-common.DataViewField", "text": "DataViewField" }, - ", value: unknown, type: \"+\" | \"-\") => void" + " | \"_exists_\", value: unknown, type: \"+\" | \"-\") => void" ], "path": "src/plugins/unified_field_list/public/types.ts", "deprecated": false, @@ -798,7 +2058,7 @@ { "parentPluginId": "unifiedFieldList", "id": "def-public.AddFieldFilterHandler.$1", - "type": "Object", + "type": "CompoundType", "tags": [], "label": "field", "description": [], @@ -809,7 +2069,8 @@ "docId": "kibDataViewsPluginApi", "section": "def-common.DataViewField", "text": "DataViewField" - } + }, + " | \"_exists_\"" ], "path": "src/plugins/unified_field_list/public/types.ts", "deprecated": false, @@ -845,6 +2106,55 @@ } ], "initialIsOpen": false + }, + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.FieldPopoverVisualizeProps", + "type": "Type", + "tags": [], + "label": "FieldPopoverVisualizeProps", + "description": [], + "signature": [ + "{ field: ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewField", + "text": "DataViewField" + }, + "; dataView: ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataView", + "text": "DataView" + }, + "; originatingApp: string; uiActions: ", + { + "pluginId": "uiActions", + "scope": "public", + "docId": "kibUiActionsPluginApi", + "section": "def-public.UiActionsStart", + "text": "UiActionsStart" + }, + "; multiFields?: ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewField", + "text": "DataViewField" + }, + "[] | undefined; contextualFields?: string[] | undefined; trackUiMetric?: ((metricType: string, eventName: string | string[]) => void) | undefined; buttonProps?: Partial<", + "EuiButtonProps", + "> | undefined; }" + ], + "path": "src/plugins/unified_field_list/public/components/field_popover/field_popover_visualize.tsx", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false } ], "objects": [], diff --git a/api_docs/unified_field_list.mdx b/api_docs/unified_field_list.mdx index 3b29a19fa6be6..603077abe6d69 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-10 +date: 2022-10-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedFieldList'] --- import unifiedFieldListObj from './unified_field_list.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Data Discovery](https://github.com/orgs/elastic/teams/kibana-data-disco | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 61 | 0 | 59 | 2 | +| 122 | 0 | 117 | 2 | ## Client diff --git a/api_docs/unified_search.mdx b/api_docs/unified_search.mdx index bdeec48aa8ea9..a5d3ee6962962 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-10 +date: 2022-10-16 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 191e2461415cf..85deb1e54a3fa 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-10 +date: 2022-10-16 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 47c97e65e6724..8093c7cc2e847 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-10 +date: 2022-10-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'urlForwarding'] --- import urlForwardingObj from './url_forwarding.devdocs.json'; diff --git a/api_docs/usage_collection.devdocs.json b/api_docs/usage_collection.devdocs.json index c90dbcddab203..046c83b0d64c7 100644 --- a/api_docs/usage_collection.devdocs.json +++ b/api_docs/usage_collection.devdocs.json @@ -515,7 +515,9 @@ "TransportRequestOptions", " | undefined): Promise<", "UpdateResponse", - ">; }; [kInternal]: symbol | null; [kAsyncSearch]: symbol | null; [kAutoscaling]: symbol | null; [kCat]: symbol | null; [kCcr]: symbol | null; [kCluster]: symbol | null; [kDanglingIndices]: symbol | null; [kEnrich]: symbol | null; [kEql]: symbol | null; [kFeatures]: symbol | null; [kFleet]: symbol | null; [kGraph]: symbol | null; [kIlm]: symbol | null; [kIndices]: symbol | null; [kIngest]: symbol | null; [kLicense]: symbol | null; [kLogstash]: symbol | null; [kMigration]: symbol | null; [kMl]: symbol | null; [kMonitoring]: symbol | null; [kNodes]: symbol | null; [kRollup]: symbol | null; [kSearchableSnapshots]: symbol | null; [kSecurity]: symbol | null; [kShutdown]: symbol | null; [kSlm]: symbol | null; [kSnapshot]: symbol | null; [kSql]: symbol | null; [kSsl]: symbol | null; [kTasks]: symbol | null; [kTextStructure]: symbol | null; [kTransform]: symbol | null; [kWatcher]: symbol | null; [kXpack]: symbol | null; transport: ", + ">; }; asyncSearch: ", + "default", + "; [kInternal]: symbol | null; [kAsyncSearch]: symbol | null; [kAutoscaling]: symbol | null; [kCat]: symbol | null; [kCcr]: symbol | null; [kCluster]: symbol | null; [kDanglingIndices]: symbol | null; [kEnrich]: symbol | null; [kEql]: symbol | null; [kFeatures]: symbol | null; [kFleet]: symbol | null; [kGraph]: symbol | null; [kIlm]: symbol | null; [kIndices]: symbol | null; [kIngest]: symbol | null; [kLicense]: symbol | null; [kLogstash]: symbol | null; [kMigration]: symbol | null; [kMl]: symbol | null; [kMonitoring]: symbol | null; [kNodes]: symbol | null; [kRollup]: symbol | null; [kSearchableSnapshots]: symbol | null; [kSecurity]: symbol | null; [kShutdown]: symbol | null; [kSlm]: symbol | null; [kSnapshot]: symbol | null; [kSql]: symbol | null; [kSsl]: symbol | null; [kTasks]: symbol | null; [kTextStructure]: symbol | null; [kTransform]: symbol | null; [kWatcher]: symbol | null; [kXpack]: symbol | null; transport: ", "default", "; helpers: ", "default", @@ -525,8 +527,6 @@ "default", "; Internal: ", "default", - "; asyncSearch: ", - "default", "; autoscaling: ", "default", "; bulk: { (this: That, params: ", diff --git a/api_docs/usage_collection.mdx b/api_docs/usage_collection.mdx index f8c3a14d66b2d..611d89bb84877 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-10 +date: 2022-10-16 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 f4689a3d2597d..907a3b68beb01 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-10 +date: 2022-10-16 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 b292069fca384..71add2be67897 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-10 +date: 2022-10-16 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 f36a18ef40bd0..d67ccb5ab6944 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-10 +date: 2022-10-16 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 89dfc16e9f523..6e6e36ef4d0f9 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-10 +date: 2022-10-16 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 1e7017d80aabf..394f3ea392d7a 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-10 +date: 2022-10-16 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 79dde1fcfab44..93c23d4ce2430 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-10 +date: 2022-10-16 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 21d856b2f4dd3..d17ed5a436fad 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-10 +date: 2022-10-16 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 2c7ec032c466e..c79b0ffd34842 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-10 +date: 2022-10-16 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 fba1745b81e6b..ce870cf90b43f 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-10 +date: 2022-10-16 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 e211f35e5c3c7..349dd2de0d631 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-10 +date: 2022-10-16 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 db8a77c924275..e1c6279e69794 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-10 +date: 2022-10-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeXy'] --- import visTypeXyObj from './vis_type_xy.devdocs.json'; diff --git a/api_docs/visualizations.devdocs.json b/api_docs/visualizations.devdocs.json index e283e14d8ba8f..26d7586a75922 100644 --- a/api_docs/visualizations.devdocs.json +++ b/api_docs/visualizations.devdocs.json @@ -7363,6 +7363,105 @@ "returnComment": [], "initialIsOpen": false }, + { + "parentPluginId": "visualizations", + "id": "def-common.getStopsWithColorsFromRanges", + "type": "Function", + "tags": [], + "label": "getStopsWithColorsFromRanges", + "description": [], + "signature": [ + "(ranges: ", + { + "pluginId": "expressions", + "scope": "common", + "docId": "kibExpressionsPluginApi", + "section": "def-common.Range", + "text": "Range" + }, + "[], colorSchema: ", + { + "pluginId": "charts", + "scope": "common", + "docId": "kibChartsPluginApi", + "section": "def-common.ColorSchemas", + "text": "ColorSchemas" + }, + ", invertColors?: boolean) => ", + { + "pluginId": "visualizations", + "scope": "common", + "docId": "kibVisualizationsPluginApi", + "section": "def-common.PaletteConfig", + "text": "PaletteConfig" + } + ], + "path": "src/plugins/visualizations/common/utils/palette.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "visualizations", + "id": "def-common.getStopsWithColorsFromRanges.$1", + "type": "Array", + "tags": [], + "label": "ranges", + "description": [], + "signature": [ + { + "pluginId": "expressions", + "scope": "common", + "docId": "kibExpressionsPluginApi", + "section": "def-common.Range", + "text": "Range" + }, + "[]" + ], + "path": "src/plugins/visualizations/common/utils/palette.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "visualizations", + "id": "def-common.getStopsWithColorsFromRanges.$2", + "type": "Enum", + "tags": [], + "label": "colorSchema", + "description": [], + "signature": [ + { + "pluginId": "charts", + "scope": "common", + "docId": "kibChartsPluginApi", + "section": "def-common.ColorSchemas", + "text": "ColorSchemas" + } + ], + "path": "src/plugins/visualizations/common/utils/palette.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "visualizations", + "id": "def-common.getStopsWithColorsFromRanges.$3", + "type": "boolean", + "tags": [], + "label": "invertColors", + "description": [], + "signature": [ + "boolean" + ], + "path": "src/plugins/visualizations/common/utils/palette.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, { "parentPluginId": "visualizations", "id": "def-common.isAnnotationsLayer", @@ -8239,6 +8338,59 @@ ], "initialIsOpen": false }, + { + "parentPluginId": "visualizations", + "id": "def-common.BasicFullPercentageModeConfig", + "type": "Interface", + "tags": [], + "label": "BasicFullPercentageModeConfig", + "description": [], + "path": "src/plugins/visualizations/common/convert_to_lens/types/common.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "visualizations", + "id": "def-common.BasicFullPercentageModeConfig.isPercentageMode", + "type": "boolean", + "tags": [], + "label": "isPercentageMode", + "description": [], + "path": "src/plugins/visualizations/common/convert_to_lens/types/common.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "visualizations", + "id": "def-common.BasicPercentageModeConfig", + "type": "Interface", + "tags": [], + "label": "BasicPercentageModeConfig", + "description": [], + "path": "src/plugins/visualizations/common/convert_to_lens/types/common.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "visualizations", + "id": "def-common.BasicPercentageModeConfig.isPercentageMode", + "type": "boolean", + "tags": [], + "label": "isPercentageMode", + "description": [], + "signature": [ + "false" + ], + "path": "src/plugins/visualizations/common/convert_to_lens/types/common.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, { "parentPluginId": "visualizations", "id": "def-common.ColumnState", @@ -9701,6 +9853,48 @@ ], "initialIsOpen": false }, + { + "parentPluginId": "visualizations", + "id": "def-common.PaletteConfig", + "type": "Interface", + "tags": [], + "label": "PaletteConfig", + "description": [], + "path": "src/plugins/visualizations/common/utils/palette.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "visualizations", + "id": "def-common.PaletteConfig.color", + "type": "Array", + "tags": [], + "label": "color", + "description": [], + "signature": [ + "(string | undefined)[]" + ], + "path": "src/plugins/visualizations/common/utils/palette.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "visualizations", + "id": "def-common.PaletteConfig.stop", + "type": "Array", + "tags": [], + "label": "stop", + "description": [], + "signature": [ + "number[]" + ], + "path": "src/plugins/visualizations/common/utils/palette.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, { "parentPluginId": "visualizations", "id": "def-common.PartitionLayerState", @@ -11597,6 +11791,20 @@ "path": "src/plugins/visualizations/common/convert_to_lens/types/configurations.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "visualizations", + "id": "def-common.XYConfiguration.showCurrentTimeMarker", + "type": "CompoundType", + "tags": [], + "label": "showCurrentTimeMarker", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "src/plugins/visualizations/common/convert_to_lens/types/configurations.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false @@ -11948,7 +12156,7 @@ "label": "lineStyle", "description": [], "signature": [ - "\"solid\" | \"dashed\" | \"dotted\" | \"dot-dashed\" | undefined" + "\"solid\" | \"dashed\" | \"dotted\" | undefined" ], "path": "src/plugins/visualizations/common/convert_to_lens/types/configurations.ts", "deprecated": false, @@ -12476,6 +12684,14 @@ "docId": "kibVisualizationsPluginApi", "section": "def-common.MetricVisConfiguration", "text": "MetricVisConfiguration" + }, + " | ", + { + "pluginId": "visualizations", + "scope": "common", + "docId": "kibVisualizationsPluginApi", + "section": "def-common.GaugeVisConfiguration", + "text": "GaugeVisConfiguration" } ], "path": "src/plugins/visualizations/common/convert_to_lens/types/configurations.ts", @@ -12867,6 +13083,96 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "visualizations", + "id": "def-common.GaugeCentralMajorMode", + "type": "Type", + "tags": [], + "label": "GaugeCentralMajorMode", + "description": [], + "signature": [ + "\"none\" | \"auto\" | \"custom\"" + ], + "path": "src/plugins/visualizations/common/convert_to_lens/types/configurations.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "visualizations", + "id": "def-common.GaugeColorMode", + "type": "Type", + "tags": [], + "label": "GaugeColorMode", + "description": [], + "signature": [ + "\"none\" | \"palette\"" + ], + "path": "src/plugins/visualizations/common/convert_to_lens/types/configurations.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "visualizations", + "id": "def-common.GaugeLabelMajorMode", + "type": "Type", + "tags": [], + "label": "GaugeLabelMajorMode", + "description": [], + "signature": [ + "\"none\" | \"auto\" | \"custom\"" + ], + "path": "src/plugins/visualizations/common/convert_to_lens/types/configurations.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "visualizations", + "id": "def-common.GaugeShape", + "type": "Type", + "tags": [], + "label": "GaugeShape", + "description": [], + "signature": [ + "\"horizontalBullet\" | \"verticalBullet\" | \"arc\" | \"circle\"" + ], + "path": "src/plugins/visualizations/common/convert_to_lens/types/configurations.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "visualizations", + "id": "def-common.GaugeTicksPosition", + "type": "Type", + "tags": [], + "label": "GaugeTicksPosition", + "description": [], + "signature": [ + "\"auto\" | \"hidden\" | \"bands\"" + ], + "path": "src/plugins/visualizations/common/convert_to_lens/types/configurations.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "visualizations", + "id": "def-common.GaugeVisConfiguration", + "type": "Type", + "tags": [], + "label": "GaugeVisConfiguration", + "description": [], + "signature": [ + "GaugeState & { layerId: string; layerType: \"data\"; }" + ], + "path": "src/plugins/visualizations/common/convert_to_lens/types/configurations.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "visualizations", "id": "def-common.GenericColumnWithMeta", @@ -12942,6 +13248,21 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "visualizations", + "id": "def-common.LENS_GAUGE_ID", + "type": "string", + "tags": [], + "label": "LENS_GAUGE_ID", + "description": [], + "signature": [ + "\"lnsGauge\"" + ], + "path": "src/plugins/visualizations/common/convert_to_lens/types/configurations.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "visualizations", "id": "def-common.MaxColumn", @@ -13208,15 +13529,50 @@ "label": "PercentageModeConfig", "description": [], "signature": [ - "({ isPercentageMode: true; } & ", + { + "pluginId": "visualizations", + "scope": "common", + "docId": "kibVisualizationsPluginApi", + "section": "def-common.BasicPercentageModeConfig", + "text": "BasicPercentageModeConfig" + }, + " | ", + { + "pluginId": "visualizations", + "scope": "common", + "docId": "kibVisualizationsPluginApi", + "section": "def-common.PercentageModeConfigWithMinMax", + "text": "PercentageModeConfigWithMinMax" + } + ], + "path": "src/plugins/visualizations/common/convert_to_lens/types/common.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "visualizations", + "id": "def-common.PercentageModeConfigWithMinMax", + "type": "Type", + "tags": [], + "label": "PercentageModeConfigWithMinMax", + "description": [], + "signature": [ + { + "pluginId": "visualizations", + "scope": "common", + "docId": "kibVisualizationsPluginApi", + "section": "def-common.BasicFullPercentageModeConfig", + "text": "BasicFullPercentageModeConfig" + }, + " & ", { "pluginId": "visualizations", "scope": "common", "docId": "kibVisualizationsPluginApi", "section": "def-common.MinMax", "text": "MinMax" - }, - ") | { isPercentageMode: boolean; }" + } ], "path": "src/plugins/visualizations/common/convert_to_lens/types/common.ts", "deprecated": false, @@ -13703,6 +14059,96 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "visualizations", + "id": "def-common.GaugeCentralMajorModes", + "type": "Object", + "tags": [], + "label": "GaugeCentralMajorModes", + "description": [], + "signature": [ + "{ readonly AUTO: \"auto\"; readonly CUSTOM: \"custom\"; readonly NONE: \"none\"; }" + ], + "path": "src/plugins/visualizations/common/convert_to_lens/constants.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "visualizations", + "id": "def-common.GaugeColorModes", + "type": "Object", + "tags": [], + "label": "GaugeColorModes", + "description": [], + "signature": [ + "{ readonly PALETTE: \"palette\"; readonly NONE: \"none\"; }" + ], + "path": "src/plugins/visualizations/common/convert_to_lens/constants.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "visualizations", + "id": "def-common.GaugeLabelMajorModes", + "type": "Object", + "tags": [], + "label": "GaugeLabelMajorModes", + "description": [], + "signature": [ + "{ readonly AUTO: \"auto\"; readonly CUSTOM: \"custom\"; readonly NONE: \"none\"; }" + ], + "path": "src/plugins/visualizations/common/convert_to_lens/constants.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "visualizations", + "id": "def-common.GaugeShapes", + "type": "Object", + "tags": [], + "label": "GaugeShapes", + "description": [], + "signature": [ + "{ readonly HORIZONTAL_BULLET: \"horizontalBullet\"; readonly VERTICAL_BULLET: \"verticalBullet\"; readonly ARC: \"arc\"; readonly CIRCLE: \"circle\"; }" + ], + "path": "src/plugins/visualizations/common/convert_to_lens/constants.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "visualizations", + "id": "def-common.GaugeTicksPositions", + "type": "Object", + "tags": [], + "label": "GaugeTicksPositions", + "description": [], + "signature": [ + "{ readonly HIDDEN: \"hidden\"; readonly AUTO: \"auto\"; readonly BANDS: \"bands\"; }" + ], + "path": "src/plugins/visualizations/common/convert_to_lens/constants.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "visualizations", + "id": "def-common.GROUP_ID", + "type": "Object", + "tags": [], + "label": "GROUP_ID", + "description": [], + "signature": [ + "{ readonly METRIC: \"metric\"; readonly MIN: \"min\"; readonly MAX: \"max\"; readonly GOAL: \"goal\"; }" + ], + "path": "src/plugins/visualizations/common/convert_to_lens/types/configurations.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "visualizations", "id": "def-common.LayerTypes", diff --git a/api_docs/visualizations.mdx b/api_docs/visualizations.mdx index e09c5b43fe526..d2d58d46dc15a 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-10 +date: 2022-10-16 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visualizations'] --- import visualizationsObj from './visualizations.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 | |-------------------|-----------|------------------------|-----------------| -| 729 | 12 | 699 | 18 | +| 755 | 12 | 725 | 18 | ## Client diff --git a/docs/api/alerting/create_rule.asciidoc b/docs/api/alerting/create_rule.asciidoc index 9394265f506b1..24abf15d02dea 100644 --- a/docs/api/alerting/create_rule.asciidoc +++ b/docs/api/alerting/create_rule.asciidoc @@ -62,7 +62,8 @@ the URL, the default space is used. types of alerts. If you don't need this, set this value to `default`. `id`::: -(Required, string) The ID of the connector saved object. +(Required, string) The ID of the connector saved object, which you can obtain by +using <>. `params`::: (Required, object) The map to the `params` that the @@ -131,7 +132,8 @@ is `onThrottleInterval`. [[create-rule-api-example]] === {api-examples-title} -Create a rule that has actions associated with a server log connector: +Create an <> that has actions +associated with a server log connector: [source,sh] -------------------------------------------------- diff --git a/docs/apm/apm-app-users.asciidoc b/docs/apm/apm-app-users.asciidoc index f5a74eb369dd1..01ecdafce4457 100644 --- a/docs/apm/apm-app-users.asciidoc +++ b/docs/apm/apm-app-users.asciidoc @@ -28,6 +28,7 @@ Select your use-case to get started: * <> * <> * <> +* <> * <> //// @@ -53,11 +54,12 @@ To create an APM reader user: . Create a new role, named something like `read-apm`, and assign the following privileges: + -- +:apm-read-view: +:apm-monitor: include::./tab-widgets/apm-app-reader/widget.asciidoc[] +:!apm-read-view: +:!apm-monitor: -- -+ -TIP: Using the deprecated APM Server binaries? -Add the privileges under the **Classic APM indices** tab above. . Assign the `read-apm` role created in the previous step, and the following built-in roles to any APM reader users: @@ -83,9 +85,6 @@ In some instances, you may wish to restrict certain Kibana apps that a user has -- include::./tab-widgets/apm-app-reader/widget.asciidoc[] -- -+ -TIP: Using the deprecated APM Server binaries? -Add the privileges under the **Classic APM indices** tab above. . Assign feature privileges to any Kibana feature that the user needs access to. Here are two examples: @@ -235,6 +234,33 @@ See <>. *********************************** *********************************** //// +[role="xpack"] +[[apm-app-storage-explorer-user-create]] +=== APM app storage explorer user + +++++ +Create a storage explorer user +++++ + +[[apm-app-storage-explorer-user]] +==== Storage explorer user + +View the **Storage explorer** in the APM app. + +. Create a new role, named something like `storage-explorer_user`, +and assign the following privileges: ++ +-- +include::./tab-widgets/storage-explorer-user/widget.asciidoc[] +-- + +. Assign the `storage-explorer_user` created previously, and the roles and privileges necessary to create +a <> or <> APM reader to any users that need to view **Storage explorer** in the APM app. + +//// +*********************************** *********************************** +//// + [role="xpack"] [[apm-app-api-user]] === APM app API user diff --git a/docs/apm/how-to-guides.asciidoc b/docs/apm/how-to-guides.asciidoc index 88b331de2acf2..4f702adf01a22 100644 --- a/docs/apm/how-to-guides.asciidoc +++ b/docs/apm/how-to-guides.asciidoc @@ -14,6 +14,7 @@ Learn how to perform common APM app tasks. * <> * <> * <> +* <> * <> @@ -35,4 +36,6 @@ include::lambda.asciidoc[] include::advanced-queries.asciidoc[] +include::storage-explorer.asciidoc[] + include::deployment-annotations.asciidoc[] \ No newline at end of file diff --git a/docs/apm/images/storage-explorer-expanded.png b/docs/apm/images/storage-explorer-expanded.png new file mode 100644 index 0000000000000..242dfb97ac325 Binary files /dev/null and b/docs/apm/images/storage-explorer-expanded.png differ diff --git a/docs/apm/images/storage-explorer-overview.png b/docs/apm/images/storage-explorer-overview.png new file mode 100644 index 0000000000000..c9c02b4bbdb7a Binary files /dev/null and b/docs/apm/images/storage-explorer-overview.png differ diff --git a/docs/apm/storage-explorer.asciidoc b/docs/apm/storage-explorer.asciidoc new file mode 100644 index 0000000000000..545e9e35f0e0f --- /dev/null +++ b/docs/apm/storage-explorer.asciidoc @@ -0,0 +1,93 @@ +[[storage-explorer]] +=== Storage explorer + +beta::[] + +Analyze your APM data and manage costs with **storage explorer**. +For example, analyze the storage footprint of each of your services to see which are producing +large amounts of data--then change the sample rate of a service to lower the amount of data ingested. +Or, expand the time filter to visualize data trends over time so that you can better forecast +and prepare for future storage needs. + +[role="screenshot"] +image::apm/images/storage-explorer-overview.png[APM Storage explorer] + +[float] +==== Index lifecycle phases + +A default {apm-guide-ref}/ilm-how-to.html[index lifecycle policy] is applied to each APM data stream, +but can be customized depending on your business needs. +Use the **Index lifecycle phase** dropdown to visualize and analyze your storage by phase. + +Customizing the default APM index lifecycle policies can save money by specifying things like: + +* The point at which an index can be moved to less performant hardware. +* The point at which availability is not as critical and the number of replicas can be reduced. +* When the index can be safely deleted. + +See {apm-guide-ref}/ilm-how-to.html[Index lifecycle management] to learn more about customizing +the default APM index lifecycle policies. + +[float] +==== Service size chart + +The service size chart displays the estimated size of each service over time. +Expand the time filter to visualize data trends and estimate daily data generation. + +[float] +==== Service statistics table + +The service statistics table provides detailed information on each service: + +* A list of **service environments**. +* The **sampling rate**. This value is calculated by dividing the number of sampled transactions by total throughput. +It might differ from the configured sampling rate for two reasons: with head-based sampling, +the initial service makes the sampling decision, and with tail-based sampling, +granular policies allow you to set multiple sample rates. +* The estimated **size on disk**. This storage size includes both primary and replica shards and is +calculated by prorating the total size of your indices by the service's document count divided by +the total number of documents. +* Number of **transactions**, **spans**, **errors**, and **metrics** — doc count and size on disk. + +[role="screenshot"] +image::apm/images/storage-explorer-expanded.png[APM Storage explorer service breakdown] + +As you explore your service statistics, you might want to take action to reduce the number of +documents and therefore storage size of a particular service. + +[float] +===== Reduce the number of transactions +To reduce the number of transactions a service generates, configure a more aggressive +{apm-guide-ref}/sampling.html[transaction sampling policy]. Transaction sampling lowers +the amount of data ingested without negatively impacting the usefulness of your data. + +[float] +===== Reduce the number of spans +To reduce the number of spans a service generates, enable +{apm-guide-ref}/span-compression.html[span compression]. Span compression saves on data +and transfer costs by compressing multiple, similar spans into a single span. + +[float] +===== Reduce the number of metrics +To reduce the number of system, runtime, and application metrics, +tune the APM agent or agents that are collecting the data. +You can disable the collection of specific metrics with the **disable metrics** configuration. +Or, you can set the **metrics interval** to zero seconds to deactivate metrics entirely. +Most APM agents support both options. +See the relevant {apm-agents-ref}[agent configuration options] for more details. + +[float] +===== Reduce the number of errors +To reduce the number of errors a service generate, +work with your developers to change how exceptions are handled in your code. + +[float] +==== Privileges + +Storage explorer requires expanded privileges to view. +See <> for more information. + +[float] +==== Limitations + +Multi-cluster deployments are not supported. diff --git a/docs/apm/tab-widgets/storage-explorer-user/content.asciidoc b/docs/apm/tab-widgets/storage-explorer-user/content.asciidoc new file mode 100644 index 0000000000000..0a6e620edbe95 --- /dev/null +++ b/docs/apm/tab-widgets/storage-explorer-user/content.asciidoc @@ -0,0 +1,29 @@ +// tag::classic-indices[] +[options="header"] +|==== +|Type |Privilege |Purpose + +|Index +|`monitor` on `apm-*` +|Monitor access to `apm-*` for storage explorer +|==== +// end::classic-indices[] + +// tag::data-streams[] +[options="header"] +|==== +|Type |Privilege |Purpose + +|Index +|`monitor` on `logs-apm*` +|Monitor access to `logs-apm*` for storage explorer + +|Index +|`monitor` on `metrics-apm*` +|Monitor access to `metrics-apm*` for storage explorer + +|Index +|`monitor` on `traces-apm*` +|Monitor access to `traces-apm*` for storage explorer +|==== +// end::data-streams[] diff --git a/docs/apm/tab-widgets/storage-explorer-user/widget.asciidoc b/docs/apm/tab-widgets/storage-explorer-user/widget.asciidoc new file mode 100644 index 0000000000000..a577f2e8b94ae --- /dev/null +++ b/docs/apm/tab-widgets/storage-explorer-user/widget.asciidoc @@ -0,0 +1,40 @@ +++++ +
+
+ + +
+
+++++ + +include::content.asciidoc[tag=data-streams] + +++++ +
+ +
+++++ \ No newline at end of file diff --git a/docs/concepts/data-views.asciidoc b/docs/concepts/data-views.asciidoc index 8726b3a55cbd0..2ce89474a003a 100644 --- a/docs/concepts/data-views.asciidoc +++ b/docs/concepts/data-views.asciidoc @@ -65,14 +65,14 @@ based on different timestamps. . To specify your own {data-source} name, click *Show advanced settings*, then enter the name in the *Custom {data-source} ID* field. For example, enter your {es} index alias name. -. Click *Save {data-source} to {kib}*. +. [[reload-fields]] To use this data in searches and visualizations that you intend to save, click *Save {data-source} to {kib}*. + +. To explore your data without creating a {data-source}, click *Use without saving*. + -[[reload-fields]] {kib} is now configured to use your {es} data. When a new field is added to an index, -the {data-source} field list is updated -the next time the {data-source} is loaded, for example, when you load the page or -move between {kib} apps. +This allows you to explore your data in *Discover*, *Lens*, and *Maps* +without making it visible to others in your space. You can save the {data-source} later +if you create a search or visualization that you want to share. -. Select this {data-source} when you search and visualize your data. [float] [[rollup-data-view]] diff --git a/docs/developer/contributing/development-functional-tests.asciidoc b/docs/developer/contributing/development-functional-tests.asciidoc index cf854c6d53cfa..95c6171aaecf5 100644 --- a/docs/developer/contributing/development-functional-tests.asciidoc +++ b/docs/developer/contributing/development-functional-tests.asciidoc @@ -67,14 +67,6 @@ export TEST_ES_PASS= node scripts/functional_test_runner ---------- -** If you are running x-pack functional tests, start server and runner from {blob}xpack[x-pack] folder: -+ -["source", "shell"] ----------- -node scripts/functional_tests_server.js -node ../scripts/functional_test_runner.js ----------- - ** Selenium tests are run in headless mode on CI. Locally the same tests will be executed in a real browser. You can activate headless mode by setting the environment variable: + ["source", "shell"] diff --git a/docs/discover/document-explorer.asciidoc b/docs/discover/document-explorer.asciidoc index 9547dbaf4477f..79bf640707ebf 100644 --- a/docs/discover/document-explorer.asciidoc +++ b/docs/discover/document-explorer.asciidoc @@ -1,19 +1,40 @@ [[document-explorer]] == Explore your documents - -*Discover* displays your documents in table format, so you can -best explore your data. Resize columns, set row height, -perform multi-column sorting, compare data, and more. +Fine tune your explorations by customizing *Discover* to bring out the the best view of your documents. +Adjust the chart height, modify the document table, and look inside a document. [role="screenshot"] -image:images/customer.png[Customer last name, first initial in the document table] +image:images/discover.png[A view of the Discover app] + [float] -[[document-explorer-columns]] -=== Reorder and resize columns +[[document-explorer-c]] +=== Hide or resize the chart + +Hide or resize the chart for a better fit. + +* To turn off the display of the chart, click +image:images/chart-icon.png[icon button for opening Show/Hide chart menu, width=24px] +to open the *Chart options* menu, and then click *Hide*. + +* To change the chart height, drag the resize handle +image:images/resize-icon.png[two-line icon for increasing or decreasing the height of the chart, width=24px] +to the size you want. +The chart size is saved in your browser. -Use drag and drop to organize the columns and improve the view of the data. +* To reset the height, open the *Chart options* menu, and then select *Reset to default height*. + +[float] +[[document-explorer-customize]] +=== Modify the document table + +Customize the appearance of the document table and its contents by resizing the columns and rows, +sorting and modifying the fields, and filtering the documents. + +[float] +[[document-explorer-columns]] +==== Reorder and resize the columns * To move a single column, click its header. In the dropdown menu, click *Move left* or *Move right*. @@ -22,26 +43,26 @@ click *Move left* or *Move right*. In the pop-up, drag the column names to their new order. * To resize a column, drag the right edge of the column header until the column is the width that you want. - ++ Column widths are stored with a saved search. When you visualize saved searches on dashboards, the saved search appears the same as in **Discover**. + [float] [[document-explorer-row-height]] -=== Adjust row height +==== Adjust the row height -To set the row height to 1 or more lines, or automatically +To set the row height to one or more lines, or automatically adjust the height to fit the contents, click the row height icon image:images/row-height-icon.png[icon to open the Row height pop-up]. [role="screenshot"] -image::images/document-explorer-row-height.png[Row height settings for the document table, width="75%"] - +image::images/document-explorer-row-height.png[Row height settings for the document table, width="50%"] [float] [[document-explorer-sort-data]] -=== Sort data +==== Sort the fields -Sort your data by one or more fields, in ascending or descending order. +Sort the data by one or more fields, in ascending or descending order. The default sort is based on the time field, from new to old. To add or remove a sort on a single field, click the @@ -49,38 +70,69 @@ column header, and then select the sort order. To sort by multiple fields: -. In the document table, click the *field sorted* option. +. Click the *field sorted* option. + [role="screenshot"] -image::images/document-explorer-sort-data.png[Pop-up in document table for sorting columns, width="75%"] +image::images/document-explorer-sort-data.png[Pop-up in document table for sorting columns, width="50%"] -. To add more fields to the sort, select from the dropdown menu. +. To add fields to the sort, select their names from the dropdown menu. + By default, columns are sorted in the order they are added. + [role="screenshot"] -image::images/document-explorer-multi-field.png[Multi field sort in the document table, width="75%"] +image::images/document-explorer-multi-field.png[Multi field sort in the document table, width="50%"] . To change the sort order, select a field in the pop-up, and then drag it to the new location. +[float] +[[document-explorer-edit-field]] +==== Edit a field + +Change how {kib} displays a field. + +. Click the column header for the field, and then select *Edit data view field.* + +. In the *Edit field* form, change the field name and format. ++ +For detailed information on formatting options, refer to <>. + [float] [[document-explorer-compare-data]] -=== Compare data +==== Filter the documents -Narrow your results to a subset of documents to easily -compare the data of interest. +Narrow your results to a subset of documents so you're comparing just the data of interest. . Select the documents you want to compare. . Click the *documents selected* option, and then select *Show selected documents only*. + [role="screenshot"] -image::images/document-explorer-compare-data.png[Compare data in the document table, width="75%"] +image::images/document-explorer-compare-data.png[Compare data in the document table, width="50%"] + +[float] +[[document-explorer-configure-table]] +==== Set the number of rows per page + +To change the numbers of rows you want to display on each page, use the *Rows per page* menu. By default, the document table displays 100 rows per page. + +[role="screenshot"] +image::images/document-table-rows-per-page.png["Menu with options for setting the number of rows in the document table"] + +To customize the default number of rows per page, go to *Stack Managaement > Advanced Settings* +and search for *rows per page*. + +[float] +[[document-explorer-full-screen]] +==== View in fullscreen + +To toggle the table in and out of fullscreen mode, click the fullscreen icon +image:images/fullscreen-icon.png[icon to display the document table in fullscreen mode]. [float] [[document-explorer-expand-documents]] -=== Expand documents + +=== Go inside a document Dive into an individual document to inspect its fields, set filters, and view the documents that occurred before and after it. @@ -97,8 +149,7 @@ image::images/document-table-expanded.png[Expanded view of the document table] . In the *Table* view, scan through the fields and their values, or search for a field by name. . When you find a field of interest, -click -image:images/actions-icon.png[three dots icon in table column] in the *Actions* column +hover your mouse over the *Actions* column to: .. Filter the results to include or exclude specific fields or values. .. Toggle the field in or out the document table. @@ -122,22 +173,3 @@ filters remain active, while other filters are copied in a disabled state. + [role="screenshot"] image::images/discover-context.png[Image showing context view feature, with anchor documents highlighted in blue] - - -[float] -[[document-explorer-full-screen]] -=== View documents in fullscreen - -To view as much data as possible and eliminate distractions, click the fullscreen icon -image:images/fullscreen-icon.png[icon to display the document table in fullscreen mode] -in the document table. - -[float] -[[document-explorer-configure-table]] -=== Configure the number of documents displayed - -By default, the document table displays 100 rows per page. To change this number, -click *Rows per page*. - -[role="screenshot"] -image::images/document-table-rows-per-page.png["Menu with options for setting the number of rows in the document table"] diff --git a/docs/discover/images/customer.png b/docs/discover/images/customer.png index c60c98b25e54d..11504bf10ac20 100644 Binary files a/docs/discover/images/customer.png and b/docs/discover/images/customer.png differ diff --git a/docs/discover/images/discover-add-filter.png b/docs/discover/images/discover-add-filter.png index 5a5a1a173b547..b022090afcb1f 100644 Binary files a/docs/discover/images/discover-add-filter.png and b/docs/discover/images/discover-add-filter.png differ diff --git a/docs/discover/images/discover-add-icon.png b/docs/discover/images/discover-add-icon.png new file mode 100644 index 0000000000000..c8330ef07b07c Binary files /dev/null and b/docs/discover/images/discover-add-icon.png differ diff --git a/docs/discover/images/discover-context.png b/docs/discover/images/discover-context.png index 35954fa7a2b51..e02171e3f8572 100644 Binary files a/docs/discover/images/discover-context.png and b/docs/discover/images/discover-context.png differ diff --git a/docs/discover/images/discover-data-view.png b/docs/discover/images/discover-data-view.png index 50b1866ab7a68..869fc9b928811 100644 Binary files a/docs/discover/images/discover-data-view.png and b/docs/discover/images/discover-data-view.png differ diff --git a/docs/discover/images/discover-search-for-relevance.png b/docs/discover/images/discover-search-for-relevance.png index e710cab0ddf2f..ea7c1a8d93436 100644 Binary files a/docs/discover/images/discover-search-for-relevance.png and b/docs/discover/images/discover-search-for-relevance.png differ diff --git a/docs/discover/images/discover-sidebar-available-fields.png b/docs/discover/images/discover-sidebar-available-fields.png index 363f3f7141086..37ae6858337b6 100644 Binary files a/docs/discover/images/discover-sidebar-available-fields.png and b/docs/discover/images/discover-sidebar-available-fields.png differ diff --git a/docs/discover/images/discover-visualize.png b/docs/discover/images/discover-visualize.png index 15f2eb4a7f60b..f88bbb7d51a62 100644 Binary files a/docs/discover/images/discover-visualize.png and b/docs/discover/images/discover-visualize.png differ diff --git a/docs/discover/images/discover.png b/docs/discover/images/discover.png index 1a2d839717f76..8b45b90225a50 100644 Binary files a/docs/discover/images/discover.png and b/docs/discover/images/discover.png differ diff --git a/docs/discover/images/document-explorer-compare-data.png b/docs/discover/images/document-explorer-compare-data.png index d5cb84af5bb37..aa14375a4f1ff 100644 Binary files a/docs/discover/images/document-explorer-compare-data.png and b/docs/discover/images/document-explorer-compare-data.png differ diff --git a/docs/discover/images/document-table-expanded.png b/docs/discover/images/document-table-expanded.png index 06b244268c1d7..d92bf70821126 100644 Binary files a/docs/discover/images/document-table-expanded.png and b/docs/discover/images/document-table-expanded.png differ diff --git a/docs/discover/images/document-table.png b/docs/discover/images/document-table.png index 6cb47390fd584..6a27d972655aa 100644 Binary files a/docs/discover/images/document-table.png and b/docs/discover/images/document-table.png differ diff --git a/docs/discover/images/field-statistics-geo.png b/docs/discover/images/field-statistics-geo.png index 35c727cb1fe76..da720e7429eb6 100644 Binary files a/docs/discover/images/field-statistics-geo.png and b/docs/discover/images/field-statistics-geo.png differ diff --git a/docs/discover/images/field-statistics-numeric.png b/docs/discover/images/field-statistics-numeric.png index cd587532c9cc4..cc298e75dcb65 100644 Binary files a/docs/discover/images/field-statistics-numeric.png and b/docs/discover/images/field-statistics-numeric.png differ diff --git a/docs/discover/images/field-statistics-view.png b/docs/discover/images/field-statistics-view.png index 836d0b5173005..bf610add8a790 100644 Binary files a/docs/discover/images/field-statistics-view.png and b/docs/discover/images/field-statistics-view.png differ diff --git a/docs/discover/images/find-manufacturer-field.png b/docs/discover/images/find-manufacturer-field.png index ce78aab933362..32cf7ee0c0ec4 100644 Binary files a/docs/discover/images/find-manufacturer-field.png and b/docs/discover/images/find-manufacturer-field.png differ diff --git a/docs/discover/images/hello-field.png b/docs/discover/images/hello-field.png index 40527e90fbb64..2471ee494f29d 100644 Binary files a/docs/discover/images/hello-field.png and b/docs/discover/images/hello-field.png differ diff --git a/docs/discover/images/resize-icon.png b/docs/discover/images/resize-icon.png new file mode 100644 index 0000000000000..a0725824510da Binary files /dev/null and b/docs/discover/images/resize-icon.png differ diff --git a/docs/discover/save-search.asciidoc b/docs/discover/save-search.asciidoc index 89adf4eac0ba1..deede3cf2b922 100644 --- a/docs/discover/save-search.asciidoc +++ b/docs/discover/save-search.asciidoc @@ -6,12 +6,6 @@ that you've created in *Discover*. Saved searches are good for adding search results to a dashboard, and can also serve as a foundation for building visualizations. -A saved search stores the query text, filters, and -current view of *Discover*, including the columns selected in the document table, -the sort order, and the {data-source}. -Saved searches are different from <>, which -are for storing query text and are available in any app with a query bar. - [role="xpack"] [[discover-read-only-access]] [float] @@ -24,8 +18,13 @@ image::discover/images/read-only-badge.png[Example of Discover's read only acces [float] === Save a search -. Once you've created a search worth saving in *Discover*, click *Save* in the toolbar. -. Enter a name for the search and click *Save*. +By default, a saved search stores the query text, filters, and +current view of *Discover*, including the columns and sort order in the document table, and the {data-source}. + +. Once you've created a search worth saving, click *Save* in the toolbar. +. Enter a name for the search. +. Optionally store <> and the time range with the search. +. Click *Save*. . To reload your search results in *Discover*, click *Open* in the toolbar, and select the saved search. + If the saved search is associated with a different {data-source} than is currently diff --git a/docs/discover/search-for-relevance.asciidoc b/docs/discover/search-for-relevance.asciidoc index c6f092edd0015..b2c69a3cc5479 100644 --- a/docs/discover/search-for-relevance.asciidoc +++ b/docs/discover/search-for-relevance.asciidoc @@ -26,7 +26,7 @@ At this point, you're sorting by the`timestamp` field. . Select *High-Low*. + [role="screenshot"] -image::images/field-sorting-popover.png["Field sorting popover", width=60%] +image::images/field-sorting-popover.png["Field sorting popover", width="60%"] + Your table now sorts documents from most to least relevant. diff --git a/docs/management/cases/cases.asciidoc b/docs/management/cases/cases.asciidoc index c08b99894eea0..de2f2196ee63f 100644 --- a/docs/management/cases/cases.asciidoc +++ b/docs/management/cases/cases.asciidoc @@ -3,10 +3,10 @@ preview::[] -Cases are used to open and track issues directly in {kib}. All cases list -the original reporter and all the users who contribute to a case (_participants_). -You can also send cases to external incident management systems by configuring -connectors. +Cases are used to open and track issues directly in {kib}. You can add +assignees and tags to your cases, set their severity and status, and add alerts, +comments, and visualizations. You can also send cases to external incident +management systems by configuring connectors. [role="screenshot"] image::images/cases.png[Cases page] diff --git a/docs/management/cases/images/cases-visualization.png b/docs/management/cases/images/cases-visualization.png index 53c4893bcc598..e5287ca45d3d4 100644 Binary files a/docs/management/cases/images/cases-visualization.png and b/docs/management/cases/images/cases-visualization.png differ diff --git a/docs/management/cases/images/cases.png b/docs/management/cases/images/cases.png index a69f21c2ec9f8..b313decf7b6b5 100644 Binary files a/docs/management/cases/images/cases.png and b/docs/management/cases/images/cases.png differ diff --git a/docs/management/cases/manage-cases.asciidoc b/docs/management/cases/manage-cases.asciidoc index f4693ef25950f..fd26221ba3432 100644 --- a/docs/management/cases/manage-cases.asciidoc +++ b/docs/management/cases/manage-cases.asciidoc @@ -10,12 +10,15 @@ Open a new case to keep track of issues and share their details with colleagues. . Go to *Management > {stack-manage-app} > Cases*, then click *Create case*. -. Give the case a name, add any relevant tags and a description. +. Give the case a name, severity, and description. + TIP: In the `Description` area, you can use https://www.markdownguide.org/cheat-sheet[Markdown] syntax to create formatted text. +. Optionally, add assignees and tags. You can add users only if they meet +the necessary <>. + . For *External incident management system*, select a connector. For more information, refer to <>. @@ -61,10 +64,12 @@ To view a case, click on its name. You can then: * Add a new comment. * Edit existing comments and the description. +* Add or remove assignees. * Add a connector. * Send updates to external systems (if external connections are configured). * Edit tags. * Refresh the case to retrieve the latest updates. * Change the status. +* Change the severity. * Close or delete the case. * Reopen a closed case. \ No newline at end of file diff --git a/docs/management/cases/setup-cases.asciidoc b/docs/management/cases/setup-cases.asciidoc index ee3a3cdaefc1b..bd99d499c81d1 100644 --- a/docs/management/cases/setup-cases.asciidoc +++ b/docs/management/cases/setup-cases.asciidoc @@ -18,6 +18,12 @@ a| NOTE: The *Actions and Connectors* feature privilege is required to create, add, delete, and modify case connectors and to send updates to external systems. +| Give assignee access to cases +a| `All` for the *Cases* feature under *Management*. + +NOTE: Before a user can be assigned to a case, they must log into {kib} at +least once, which creates a user profile. + | Give view-only access for cases | `Read` for the *Cases* feature under *Management*. | Give access to view and delete cases | `Read` for the *Cases* feature under diff --git a/docs/management/index-patterns/images/create-data-view.png b/docs/management/index-patterns/images/create-data-view.png index 229ed0f490b41..af5b01111cd2e 100644 Binary files a/docs/management/index-patterns/images/create-data-view.png and b/docs/management/index-patterns/images/create-data-view.png differ diff --git a/docs/settings/search-sessions-settings.asciidoc b/docs/settings/search-sessions-settings.asciidoc index 7a51c23c9a1cc..2862dec25b881 100644 --- a/docs/settings/search-sessions-settings.asciidoc +++ b/docs/settings/search-sessions-settings.asciidoc @@ -19,7 +19,7 @@ How long {kib} stores search results from unsaved sessions, after the last search in the session completes. The default is `5m`. `data.search.sessions.maxUpdateRetries` {ess-icon}:: -How many retries {kib} can perform while attempting to save a search session. The default is `3`. +How many retries {kib} can perform while attempting to save a search session. The default is `10`. `data.search.sessions.defaultExpiration` {ess-icon}:: How long search session results are stored before they are deleted. diff --git a/docs/user/discover.asciidoc b/docs/user/discover.asciidoc index fab5dc372feac..823d9dcf1fe53 100644 --- a/docs/user/discover.asciidoc +++ b/docs/user/discover.asciidoc @@ -57,7 +57,8 @@ your {es} data. To view the ecommerce sample data, open the {data-source} menu, and then select **Kibana Sample Data Ecommerce**. + [role="screenshot"] -image::images/discover-data-view.png[How to set the {data-source} in Discover, width=50%] +image::images/discover-data-view.png[How to set the {data-source} in Discover, width="40%"] + + To create a data view for your own data, click *Create a data view*. @@ -87,12 +88,15 @@ You can also search for the field by name. [role="screenshot"] image:images/discover-sidebar-available-fields.png[Fields list that displays the top five search results, width=50%] -. Click the `manufacturer` field to view its five most popular values. +. Click `manufacturer` to view its most popular values. + -[role="screenshot"] -image:images/find-manufacturer-field.png[Fields list that displays the top five search results, width=75%] +**Discover** shows the top 10 values and the number of records used to calculate those values. . Click image:images/add-icon.png[Add icon] to toggle the field into the document table. ++ +[role="screenshot"] +image::images/discover-add-icon.png[How to add a field as a column in the table, width="50%"] + . Find the `customer_first_name` and `customer_last_name` fields and add them to the document table. Your table should look similar to this: @@ -103,7 +107,8 @@ image:images/document-table.png[Document table with fields for manufacturer, cus . To rearrange the table columns, click a column header, and then select *Move left* or *Move right*. -. To view more of the document table, click +. To view more of the document table, +click image:images/chart-icon.png[icon button for opening Show/Hide chart menu, width=24px] to open the *Chart options* menu, and then select *Hide chart*. @@ -217,8 +222,7 @@ to show document details. image:images/document-table-expanded.png[Table view with document expanded] . Scan through the fields and their values. If you find a field of interest, -click -image:images/actions-icon.png[three dots icon next to data view dropdown] in the *Actions* column for filters and other controls. +hover your mouse over the *Actions* column for filters and other options. . To create a view of the document that you can bookmark and share, click **Single document**. @@ -238,6 +242,8 @@ the document table, the sort order, and the {data-source}. . In the toolbar, click **Save**. +. Optionally store <> and the time range with the search. + . Give your search a title, and then click **Save**. [float] @@ -299,9 +305,8 @@ For more about this and other rules provided in {alert-features}, go to <>. -* <> to better meet your needs. -Go to **Advanced Settings** to configure the number of documents to show, -the table columns that display by default, and more. +* <> to better meet your needs. + -- include::{kib-repo-dir}/discover/document-explorer.asciidoc[] diff --git a/examples/response_stream/common/api/reducer_stream/request_body_schema.ts b/examples/response_stream/common/api/reducer_stream/request_body_schema.ts index 58ea487a8a539..8318a411ab86a 100644 --- a/examples/response_stream/common/api/reducer_stream/request_body_schema.ts +++ b/examples/response_stream/common/api/reducer_stream/request_body_schema.ts @@ -13,5 +13,7 @@ export const reducerStreamRequestBodySchema = schema.object({ simulateErrors: schema.maybe(schema.boolean()), /** Maximum timeout between streaming messages. */ timeout: schema.maybe(schema.number()), + /** Setting to override headers derived compression */ + compressResponse: schema.maybe(schema.boolean()), }); export type ReducerStreamRequestBodySchema = TypeOf; diff --git a/examples/response_stream/common/api/simple_string_stream/request_body_schema.ts b/examples/response_stream/common/api/simple_string_stream/request_body_schema.ts index 8e891395e5dc8..3a9d0f4d7e225 100644 --- a/examples/response_stream/common/api/simple_string_stream/request_body_schema.ts +++ b/examples/response_stream/common/api/simple_string_stream/request_body_schema.ts @@ -11,6 +11,8 @@ import { schema, TypeOf } from '@kbn/config-schema'; export const simpleStringStreamRequestBodySchema = schema.object({ /** Maximum timeout between streaming messages. */ timeout: schema.number(), + /** Setting to override headers derived compression */ + compressResponse: schema.maybe(schema.boolean()), }); export type SimpleStringStreamRequestBodySchema = TypeOf< typeof simpleStringStreamRequestBodySchema diff --git a/examples/response_stream/public/containers/app/pages/page_reducer_stream/index.tsx b/examples/response_stream/public/containers/app/pages/page_reducer_stream/index.tsx index 0755765374330..913f8b4064440 100644 --- a/examples/response_stream/public/containers/app/pages/page_reducer_stream/index.tsx +++ b/examples/response_stream/public/containers/app/pages/page_reducer_stream/index.tsx @@ -44,13 +44,14 @@ export const PageReducerStream: FC = () => { const basePath = http?.basePath.get() ?? ''; const [simulateErrors, setSimulateErrors] = useState(false); + const [compressResponse, setCompressResponse] = useState(true); const { dispatch, start, cancel, data, errors, isCancelled, isRunning } = useFetchStream< ApiReducerStream, typeof basePath >( `${basePath}/internal/response_stream/reducer_stream`, - { simulateErrors }, + { compressResponse, simulateErrors }, { reducer: reducerStreamReducer, initialState } ); @@ -144,6 +145,13 @@ export const PageReducerStream: FC = () => { onChange={(e) => setSimulateErrors(!simulateErrors)} compressed /> + setCompressResponse(!compressResponse)} + compressed + /> ); diff --git a/examples/response_stream/public/containers/app/pages/page_simple_string_stream/index.tsx b/examples/response_stream/public/containers/app/pages/page_simple_string_stream/index.tsx index cfa76688d9701..a305e907cfb45 100644 --- a/examples/response_stream/public/containers/app/pages/page_simple_string_stream/index.tsx +++ b/examples/response_stream/public/containers/app/pages/page_simple_string_stream/index.tsx @@ -6,9 +6,17 @@ * Side Public License, v 1. */ -import React, { FC } from 'react'; +import React, { useState, FC } from 'react'; -import { EuiButton, EuiCallOut, EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiText } from '@elastic/eui'; +import { + EuiButton, + EuiCallOut, + EuiCheckbox, + EuiFlexGroup, + EuiFlexItem, + EuiSpacer, + EuiText, +} from '@elastic/eui'; import { useFetchStream } from '@kbn/aiops-utils'; @@ -21,10 +29,15 @@ export const PageSimpleStringStream: FC = () => { const { core } = useDeps(); const basePath = core.http?.basePath.get() ?? ''; + const [compressResponse, setCompressResponse] = useState(true); + const { dispatch, errors, start, cancel, data, isRunning } = useFetchStream< ApiSimpleStringStream, typeof basePath - >(`${basePath}/internal/response_stream/simple_string_stream`, { timeout: 500 }); + >(`${basePath}/internal/response_stream/simple_string_stream`, { + compressResponse, + timeout: 500, + }); const onClickHandler = async () => { if (isRunning) { @@ -58,6 +71,14 @@ export const PageSimpleStringStream: FC = () => { + setCompressResponse(!compressResponse)} + compressed + /> +

{data}

diff --git a/examples/response_stream/server/routes/reducer_stream.ts b/examples/response_stream/server/routes/reducer_stream.ts index 7cc02d9b1a80f..e9fe6d02b68f6 100644 --- a/examples/response_stream/server/routes/reducer_stream.ts +++ b/examples/response_stream/server/routes/reducer_stream.ts @@ -31,17 +31,29 @@ export const defineReducerStreamRoute = (router: IRouter, logger: Logger) => { const maxTimeoutMs = request.body.timeout ?? 250; const simulateError = request.body.simulateErrors ?? false; + let logMessageCounter = 1; + + function logDebugMessage(msg: string) { + logger.debug(`Response Stream Example #${logMessageCounter}: ${msg}`); + logMessageCounter++; + } + + logDebugMessage('Starting stream.'); + let shouldStop = false; request.events.aborted$.subscribe(() => { + logDebugMessage('aborted$ subscription trigger.'); shouldStop = true; }); request.events.completed$.subscribe(() => { + logDebugMessage('completed$ subscription trigger.'); shouldStop = true; }); const { end, push, responseWithHeaders } = streamFactory( request.headers, - logger + logger, + request.body.compressResponse ); const entities = [ diff --git a/examples/response_stream/server/routes/single_string_stream.ts b/examples/response_stream/server/routes/single_string_stream.ts index dd3a784314c96..fde4947746dbf 100644 --- a/examples/response_stream/server/routes/single_string_stream.ts +++ b/examples/response_stream/server/routes/single_string_stream.ts @@ -35,7 +35,11 @@ export const defineSimpleStringStreamRoute = (router: IRouter, logger: Logger) = shouldStop = true; }); - const { end, push, responseWithHeaders } = streamFactory(request.headers, logger); + const { end, push, responseWithHeaders } = streamFactory( + request.headers, + logger, + request.body.compressResponse + ); const text = 'Elasticsearch is a search engine based on the Lucene library. It provides a distributed, multitenant-capable full-text search engine with an HTTP web interface and schema-free JSON documents. Elasticsearch is developed in Java and is dual-licensed under the source-available Server Side Public License and the Elastic license, while other parts fall under the proprietary (source-available) Elastic License. Official clients are available in Java, .NET (C#), PHP, Python, Apache Groovy, Ruby and many other languages. According to the DB-Engines ranking, Elasticsearch is the most popular enterprise search engine.'; diff --git a/package.json b/package.json index bd550a1ea2c48..140727a894ca5 100644 --- a/package.json +++ b/package.json @@ -105,7 +105,7 @@ "@dnd-kit/utilities": "^2.0.0", "@elastic/apm-rum": "^5.12.0", "@elastic/apm-rum-react": "^1.4.2", - "@elastic/charts": "50.0.1", + "@elastic/charts": "50.0.2", "@elastic/datemath": "5.0.3", "@elastic/elasticsearch": "npm:@elastic/elasticsearch-canary@8.3.0-canary.1", "@elastic/ems-client": "8.3.3", @@ -142,6 +142,7 @@ "@kbn/analytics-shippers-fullstory": "link:bazel-bin/packages/analytics/shippers/fullstory", "@kbn/apm-config-loader": "link:bazel-bin/packages/kbn-apm-config-loader", "@kbn/apm-utils": "link:bazel-bin/packages/kbn-apm-utils", + "@kbn/cases-components": "link:bazel-bin/packages/kbn-cases-components", "@kbn/chart-icons": "link:bazel-bin/packages/kbn-chart-icons", "@kbn/coloring": "link:bazel-bin/packages/kbn-coloring", "@kbn/config": "link:bazel-bin/packages/kbn-config", @@ -460,7 +461,7 @@ "constate": "^3.3.2", "content-disposition": "^0.5.4", "copy-to-clipboard": "^3.0.8", - "core-js": "^3.25.1", + "core-js": "^3.25.5", "cronstrue": "^1.51.0", "cuid": "^2.1.8", "cytoscape": "^3.10.0", @@ -584,7 +585,7 @@ "react-fast-compare": "^2.0.4", "react-focus-on": "^3.6.0", "react-grid-layout": "^1.3.4", - "react-hook-form": "^7.36.1", + "react-hook-form": "^7.37.0", "react-intl": "^2.8.0", "react-is": "^17.0.2", "react-markdown": "^6.0.3", @@ -865,6 +866,7 @@ "@types/kbn__axe-config": "link:bazel-bin/packages/kbn-axe-config/npm_module_types", "@types/kbn__bazel-packages": "link:bazel-bin/packages/kbn-bazel-packages/npm_module_types", "@types/kbn__bazel-runner": "link:bazel-bin/packages/kbn-bazel-runner/npm_module_types", + "@types/kbn__cases-components": "link:bazel-bin/packages/kbn-cases-components/npm_module_types", "@types/kbn__chart-icons": "link:bazel-bin/packages/kbn-chart-icons/npm_module_types", "@types/kbn__ci-stats-core": "link:bazel-bin/packages/kbn-ci-stats-core/npm_module_types", "@types/kbn__ci-stats-performance-metrics": "link:bazel-bin/packages/kbn-ci-stats-performance-metrics/npm_module_types", @@ -1448,7 +1450,7 @@ "webpack-dev-server": "^4.9.3", "webpack-merge": "^4.2.2", "webpack-sources": "^1.4.1", - "xml-crypto": "^2.1.4", + "xml-crypto": "^3.0.0", "xmlbuilder": "13.0.2", "yargs": "^15.4.1" } diff --git a/packages/BUILD.bazel b/packages/BUILD.bazel index aae46a111c053..265e5fe75591d 100644 --- a/packages/BUILD.bazel +++ b/packages/BUILD.bazel @@ -191,6 +191,7 @@ filegroup( "//packages/kbn-babel-preset:build", "//packages/kbn-bazel-packages:build", "//packages/kbn-bazel-runner:build", + "//packages/kbn-cases-components:build", "//packages/kbn-chart-icons:build", "//packages/kbn-ci-stats-core:build", "//packages/kbn-ci-stats-performance-metrics:build", @@ -527,6 +528,7 @@ filegroup( "//packages/kbn-axe-config:build_types", "//packages/kbn-bazel-packages:build_types", "//packages/kbn-bazel-runner:build_types", + "//packages/kbn-cases-components:build_types", "//packages/kbn-chart-icons:build_types", "//packages/kbn-ci-stats-core:build_types", "//packages/kbn-ci-stats-performance-metrics:build_types", diff --git a/packages/content-management/table_list/BUILD.bazel b/packages/content-management/table_list/BUILD.bazel index 36d84a426a017..170ce00558045 100644 --- a/packages/content-management/table_list/BUILD.bazel +++ b/packages/content-management/table_list/BUILD.bazel @@ -86,6 +86,8 @@ TYPES_DEPS = [ "@npm//@types/jest", "@npm//@types/lodash", "@npm//@types/react", + "@npm//@emotion/css", + "@npm//@emotion/react", "@npm//@elastic/eui", "@npm//react-use", "@npm//rxjs", @@ -101,7 +103,7 @@ jsts_transpiler( name = "target_web", srcs = SRCS, build_pkg_name = package_name(), - web = True, + web = True ) ts_config( diff --git a/packages/content-management/table_list/src/actions.ts b/packages/content-management/table_list/src/actions.ts index ad82aa7379812..9eff5f445079d 100644 --- a/packages/content-management/table_list/src/actions.ts +++ b/packages/content-management/table_list/src/actions.ts @@ -6,7 +6,9 @@ * Side Public License, v 1. */ import type { IHttpFetchError } from '@kbn/core-http-browser'; -import type { CriteriaWithPagination } from '@elastic/eui'; +import type { CriteriaWithPagination, Direction } from '@elastic/eui'; + +import type { SortColumnField } from './components'; /** Action to trigger a fetch of the table items */ export interface OnFetchItemsAction { @@ -52,6 +54,15 @@ export interface OnTableChangeAction { data: CriteriaWithPagination; } +/** Action to update the sort column of the table */ +export interface OnTableSortChangeAction { + type: 'onTableSortChange'; + data: { + field: SortColumnField; + direction: Direction; + }; +} + /** Action to display the delete confirmation modal */ export interface ShowConfirmDeleteItemsModalAction { type: 'showConfirmDeleteItemsModal'; @@ -70,5 +81,6 @@ export type Action = | DeleteItemsActions | OnSelectionChangeAction | OnTableChangeAction + | OnTableSortChangeAction | ShowConfirmDeleteItemsModalAction | OnSearchQueryChangeAction; diff --git a/packages/content-management/table_list/src/components/index.ts b/packages/content-management/table_list/src/components/index.ts index f2284a4cd67ab..004222d7729d0 100644 --- a/packages/content-management/table_list/src/components/index.ts +++ b/packages/content-management/table_list/src/components/index.ts @@ -11,3 +11,6 @@ export { UpdatedAtField } from './updated_at_field'; export { ConfirmDeleteModal } from './confirm_delete_modal'; export { ListingLimitWarning } from './listing_limit_warning'; export { ItemDetails } from './item_details'; +export { TableSortSelect } from './table_sort_select'; + +export type { SortColumnField } from './table_sort_select'; diff --git a/packages/content-management/table_list/src/components/table.tsx b/packages/content-management/table_list/src/components/table.tsx index feb83dbc30a40..846fa087a8db8 100644 --- a/packages/content-management/table_list/src/components/table.tsx +++ b/packages/content-management/table_list/src/components/table.tsx @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import React, { Dispatch, useCallback } from 'react'; +import React, { Dispatch, useCallback, useMemo } from 'react'; import { FormattedMessage } from '@kbn/i18n-react'; import { EuiBasicTableColumn, @@ -14,6 +14,8 @@ import { EuiInMemoryTable, CriteriaWithPagination, PropertySort, + SearchFilterConfig, + Direction, } from '@elastic/eui'; import { useServices } from '../services'; @@ -23,6 +25,8 @@ import type { Props as TableListViewProps, UserContentCommonSchema, } from '../table_list_view'; +import { TableSortSelect } from './table_sort_select'; +import type { SortColumnField } from './table_sort_select'; type State = Pick< TableListViewState, @@ -36,7 +40,10 @@ interface Props extends State { isFetchingItems: boolean; tableCaption: string; tableColumns: Array>; + hasUpdatedAtMetadata: boolean; deleteItems: TableListViewProps['deleteItems']; + onSortChange: (column: SortColumnField, direction: Direction) => void; + onTableChange: (criteria: CriteriaWithPagination) => void; } export function Table({ @@ -48,10 +55,13 @@ export function Table({ pagination, tableColumns, tableSort, + hasUpdatedAtMetadata, entityName, entityNamePlural, deleteItems, tableCaption, + onTableChange, + onSortChange, }: Props) { const { getSearchBarFilters } = useServices(); @@ -87,19 +97,38 @@ export function Table({ } : undefined; - const searchFilters = getSearchBarFilters ? getSearchBarFilters() : []; + const searchFilters = useMemo(() => { + const tableSortSelectFilter: SearchFilterConfig = { + type: 'custom_component', + component: () => { + return ( + + ); + }, + }; - const search = { - onChange: ({ queryText }: { queryText: string }) => - dispatch({ type: 'onSearchQueryChange', data: queryText }), - toolsLeft: renderToolsLeft(), - defaultQuery: searchQuery, - box: { - incremental: true, - 'data-test-subj': 'tableListSearchBox', - }, - filters: searchFilters, - }; + return getSearchBarFilters + ? [tableSortSelectFilter, ...getSearchBarFilters()] + : [tableSortSelectFilter]; + }, [onSortChange, hasUpdatedAtMetadata, tableSort, getSearchBarFilters]); + + const search = useMemo(() => { + return { + onChange: ({ queryText }: { queryText: string }) => + dispatch({ type: 'onSearchQueryChange', data: queryText }), + toolsLeft: renderToolsLeft(), + defaultQuery: searchQuery, + box: { + incremental: true, + 'data-test-subj': 'tableListSearchBox', + }, + filters: searchFilters, + }; + }, [dispatch, renderToolsLeft, searchFilters, searchQuery]); const noItemsMessage = ( ({ selection={selection} search={search} sorting={tableSort ? { sort: tableSort as PropertySort } : undefined} - onChange={(criteria: CriteriaWithPagination) => - dispatch({ type: 'onTableChange', data: criteria }) - } + onChange={onTableChange} data-test-subj="itemsInMemTable" rowHeader="attributes.title" tableCaption={tableCaption} diff --git a/packages/content-management/table_list/src/components/table_sort_select.tsx b/packages/content-management/table_list/src/components/table_sort_select.tsx new file mode 100644 index 0000000000000..ec2c5c5db1f6d --- /dev/null +++ b/packages/content-management/table_list/src/components/table_sort_select.tsx @@ -0,0 +1,179 @@ +/* + * 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, { useState, useEffect } from 'react'; +import { i18n } from '@kbn/i18n'; +import { + EuiSelectable, + EuiPopover, + EuiFilterButton, + EuiSelectableOption, + EuiIcon, + Direction, + EuiText, + useEuiTheme, +} from '@elastic/eui'; +import { css } from '@emotion/react'; + +import { State } from '../table_list_view'; + +type SortItem = EuiSelectableOption & { + column: SortColumnField; + direction: Direction; +}; + +export type SortColumnField = 'updatedAt' | 'attributes.title'; + +const i18nText = { + nameAscSort: i18n.translate('contentManagement.tableList.listing.tableSortSelect.nameAscLabel', { + defaultMessage: 'Name A-Z', + }), + nameDescSort: i18n.translate( + 'contentManagement.tableList.listing.tableSortSelect.nameDescLabel', + { + defaultMessage: 'Name Z-A', + } + ), + updatedAtAscSort: i18n.translate( + 'contentManagement.tableList.listing.tableSortSelect.updatedAtAscLabel', + { + defaultMessage: 'Least recently updated', + } + ), + updatedAtDescSort: i18n.translate( + 'contentManagement.tableList.listing.tableSortSelect.updatedAtDescLabel', + { + defaultMessage: 'Recently updated', + } + ), + headerSort: i18n.translate('contentManagement.tableList.listing.tableSortSelect.headerLabel', { + defaultMessage: 'Sort by', + }), +}; + +interface Props { + hasUpdatedAtMetadata: boolean; + tableSort: State['tableSort']; + onChange?: (column: SortColumnField, direction: Direction) => void; +} + +export function TableSortSelect({ tableSort, hasUpdatedAtMetadata, onChange }: Props) { + const { euiTheme } = useEuiTheme(); + + const [isPopoverOpen, setIsPopoverOpen] = useState(false); + const [options, setOptions] = useState(() => { + let opts: SortItem[] = [ + { + label: i18nText.nameAscSort, + column: 'attributes.title', + direction: 'asc', + append: , + }, + { + label: i18nText.nameDescSort, + column: 'attributes.title', + direction: 'desc', + append: , + }, + ]; + + if (hasUpdatedAtMetadata) { + opts = opts.concat([ + { + label: i18nText.updatedAtDescSort, + column: 'updatedAt', + direction: 'desc', + append: , + }, + { + label: i18nText.updatedAtAscSort, + column: 'updatedAt', + direction: 'asc', + append: , + }, + ]); + } + + return opts; + }); + const selectedOptionLabel = options.find(({ checked }) => checked === 'on')?.label ?? ''; + + const panelHeaderCSS = css` + border-bottom: ${euiTheme.border.thin}; + font-weight: ${600}; + padding: ${euiTheme.size.s}; + `; + + const togglePopOver = () => { + setIsPopoverOpen((prev) => !prev); + }; + + const closePopover = () => { + setIsPopoverOpen(false); + }; + + const button = ( + + {selectedOptionLabel} + + ); + + const onSelectChange = (updatedOptions: SortItem[]) => { + setOptions(updatedOptions); + + const selectedOption = updatedOptions.find(({ checked }) => checked === 'on'); + if (selectedOption && onChange) { + onChange(selectedOption.column, selectedOption.direction); + } + }; + + useEffect(() => { + setOptions((prev) => { + return prev.map((option) => { + const checked = + option.column === tableSort.field && option.direction === tableSort.direction + ? 'on' + : undefined; + + return { + ...option, + checked, + }; + }); + }); + }, [tableSort]); + + return ( + + <> + {i18nText.headerSort} + + singleSelection + aria-label="some aria label" + options={options} + onChange={onSelectChange} + data-test-subj="sortSelect" + > + {(list) => list} + + + + ); +} diff --git a/packages/content-management/table_list/src/mocks.tsx b/packages/content-management/table_list/src/mocks.tsx index 52f985edf7752..ed63e1c66d94b 100644 --- a/packages/content-management/table_list/src/mocks.tsx +++ b/packages/content-management/table_list/src/mocks.tsx @@ -30,10 +30,19 @@ const tags = [ }, ]; -export const TagList: Services['TagList'] = ({ onClick }) => { +interface Props { + onClick?: (tag: { name: string }) => void; + tags?: typeof tags | null; +} + +export const TagList = ({ onClick, tags: _tags = tags }: Props) => { + if (_tags === null) { + return null; + } + return ( - {tags.map((tag) => ( + {_tags.map((tag) => ( { @@ -54,6 +63,12 @@ export const TagList: Services['TagList'] = ({ onClick }) => { ); }; +export const getTagList = + ({ tags: _tags }: Props = {}) => + ({ onClick }: Props) => { + return ; + }; + /** * Returns Storybook-compatible service abstractions for the `NoDataCard` Provider. */ diff --git a/packages/content-management/table_list/src/reducer.tsx b/packages/content-management/table_list/src/reducer.tsx index 6ec7cbce37a49..c90cb4c883957 100644 --- a/packages/content-management/table_list/src/reducer.tsx +++ b/packages/content-management/table_list/src/reducer.tsx @@ -30,7 +30,7 @@ export function getReducer() { hasUpdatedAtMetadata = Boolean(items.find((item) => Boolean(item.updatedAt))); if (hasUpdatedAtMetadata) { tableSort = { - field: 'updatedAt' as keyof T, + field: 'updatedAt' as const, direction: 'desc' as const, }; } @@ -67,7 +67,7 @@ export function getReducer() { }; } case 'onTableChange': { - const tableSort = action.data.sort ?? state.tableSort; + const tableSort = (action.data.sort as State['tableSort']) ?? state.tableSort; return { ...state, pagination: { @@ -78,6 +78,12 @@ export function getReducer() { tableSort, }; } + case 'onTableSortChange': { + return { + ...state, + tableSort: action.data, + }; + } case 'showConfirmDeleteItemsModal': { return { ...state, diff --git a/packages/content-management/table_list/src/table_list_view.test.tsx b/packages/content-management/table_list/src/table_list_view.test.tsx index 755f1ebe10e59..8e5aff4ae0dbe 100644 --- a/packages/content-management/table_list/src/table_list_view.test.tsx +++ b/packages/content-management/table_list/src/table_list_view.test.tsx @@ -11,8 +11,10 @@ import { registerTestBed, TestBed } from '@kbn/test-jest-helpers'; import React, { useEffect } from 'react'; import moment, { Moment } from 'moment'; import { act } from 'react-dom/test-utils'; +import type { ReactWrapper } from 'enzyme'; import { WithServices } from './__jest__'; +import { getTagList } from './mocks'; import { TableListView, Props as TableListViewProps } from './table_list_view'; const mockUseEffect = useEffect; @@ -306,4 +308,202 @@ describe('TableListView', () => { expect(lastRowTitle).toBe('Item 29elasticcloud'); }); }); + + describe('column sorting', () => { + const setupColumnSorting = registerTestBed( + WithServices(TableListView, { TagList: getTagList({ tags: null }) }), + { + defaultProps: { ...requiredProps }, + memoryRouter: { wrapComponent: false }, + } + ); + + const twoDaysAgo = new Date(new Date().setDate(new Date().getDate() - 2)); + const twoDaysAgoToString = new Date(twoDaysAgo.getTime()).toDateString(); + const yesterday = new Date(new Date().setDate(new Date().getDate() - 1)); + const yesterdayToString = new Date(yesterday.getTime()).toDateString(); + const hits = [ + { + id: '123', + updatedAt: twoDaysAgo, // first asc, last desc + attributes: { + title: 'z-foo', // first desc, last asc + }, + }, + { + id: '456', + updatedAt: yesterday, // first desc, last asc + attributes: { + title: 'a-foo', // first asc, last desc + }, + }, + ]; + + test('should initially sort by "Last updated" column', async () => { + let testBed: TestBed; + + await act(async () => { + testBed = await setupColumnSorting({ + findItems: jest.fn().mockResolvedValue({ total: hits.length, hits }), + }); + }); + + const { component, table } = testBed!; + component.update(); + + const { tableCellsValues } = table.getMetaData('itemsInMemTable'); + + expect(tableCellsValues).toEqual([ + ['a-foo', yesterdayToString], + ['z-foo', twoDaysAgoToString], + ]); + }); + + test('filter select should have 4 options', async () => { + let testBed: TestBed; + + await act(async () => { + testBed = await setupColumnSorting({ + findItems: jest.fn().mockResolvedValue({ total: hits.length, hits }), + }); + }); + const { component, find } = testBed!; + component.update(); + + act(() => { + find('tableSortSelectBtn').simulate('click'); + }); + component.update(); + + const filterOptions = find('sortSelect').find('li'); + + expect(filterOptions.length).toBe(4); + expect(filterOptions.map((wrapper) => wrapper.text())).toEqual([ + 'Name A-Z ', + 'Name Z-A ', + 'Recently updated - Checked option. ', + 'Least recently updated ', + ]); + }); + + test('filter select should change the sort order', async () => { + let testBed: TestBed; + + await act(async () => { + testBed = await setupColumnSorting({ + findItems: jest.fn().mockResolvedValue({ total: hits.length, hits }), + }); + }); + + const { component, table, find } = testBed!; + component.update(); + + let { tableCellsValues } = table.getMetaData('itemsInMemTable'); + + expect(tableCellsValues).toEqual([ + ['a-foo', yesterdayToString], + ['z-foo', twoDaysAgoToString], + ]); + + act(() => { + find('tableSortSelectBtn').simulate('click'); + }); + component.update(); + const filterOptions = find('sortSelect').find('li'); + + // Click 'Name Z-A' + act(() => { + filterOptions.at(1).simulate('click'); + }); + component.update(); + + ({ tableCellsValues } = table.getMetaData('itemsInMemTable')); + + expect(tableCellsValues).toEqual([ + ['z-foo', twoDaysAgoToString], + ['a-foo', yesterdayToString], + ]); + }); + + test('should update the select option when toggling the column header', async () => { + const getTableColumnSortButton = (testBed: TestBed, text: string) => { + const buttons = testBed.find('tableHeaderSortButton'); + let wrapper: ReactWrapper | undefined; + + buttons.forEach((_wrapper) => { + if (wrapper) { + return; + } + + if (_wrapper.text().includes(text)) { + wrapper = _wrapper; + } + }); + return wrapper; + }; + + let testBed: TestBed; + + await act(async () => { + testBed = await setupColumnSorting({ + findItems: jest.fn().mockResolvedValue({ total: hits.length, hits }), + }); + }); + + const { component, table, find } = testBed!; + component.update(); + + act(() => { + find('tableSortSelectBtn').simulate('click'); + }); + component.update(); + let filterOptions = find('sortSelect').find('li'); + expect(filterOptions.map((wrapper) => wrapper.text())).toEqual([ + 'Name A-Z ', + 'Name Z-A ', + 'Recently updated - Checked option. ', // checked + 'Least recently updated ', + ]); + + const nameColumnHeaderButton = getTableColumnSortButton(testBed!, 'Name'); + if (!nameColumnHeaderButton) { + throw new Error('Could not find table header button containing "Name".'); + } + + act(() => { + nameColumnHeaderButton.simulate('click'); + }); + component.update(); + let { tableCellsValues } = table.getMetaData('itemsInMemTable'); + + expect(tableCellsValues).toEqual([ + ['a-foo', yesterdayToString], + ['z-foo', twoDaysAgoToString], + ]); + + act(() => { + nameColumnHeaderButton.simulate('click'); + }); + component.update(); + ({ tableCellsValues } = table.getMetaData('itemsInMemTable')); + + expect(tableCellsValues).toEqual([ + ['z-foo', twoDaysAgoToString], + ['a-foo', yesterdayToString], + ]); + + act(() => { + find('tableSortSelectBtn').simulate('click'); + }); + component.update(); + filterOptions = find('sortSelect').find('li'); + + expect(filterOptions.map((wrapper) => wrapper.text())).toEqual([ + 'Name A-Z ', + 'Name Z-A - Checked option. ', // now this option is checked + 'Recently updated ', + 'Least recently updated ', + ]); + }); + }); }); diff --git a/packages/content-management/table_list/src/table_list_view.tsx b/packages/content-management/table_list/src/table_list_view.tsx index f7386240826c7..80b814c4dcdb9 100644 --- a/packages/content-management/table_list/src/table_list_view.tsx +++ b/packages/content-management/table_list/src/table_list_view.tsx @@ -17,6 +17,7 @@ import { Direction, EuiSpacer, EuiTableActionsColumnType, + CriteriaWithPagination, } from '@elastic/eui'; import { keyBy, uniq, get } from 'lodash'; import { i18n } from '@kbn/i18n'; @@ -35,6 +36,7 @@ import { useServices } from './services'; import type { SavedObjectsReference, SavedObjectsFindOptionsReference } from './services'; import type { Action } from './actions'; import { getReducer } from './reducer'; +import type { SortColumnField } from './components'; export interface Props { entityName: string; @@ -79,8 +81,8 @@ export interface State({ pageSize: initialPageSize, pageSizeOptions: uniq([10, 20, 50, initialPageSize]).sort(), }, + tableSort: { + field: 'attributes.title' as const, + direction: 'asc', + }, }); const { @@ -308,6 +314,17 @@ function TableListViewComp({ } }, [searchQueryParser, searchQuery, findItems]); + const onSortChange = useCallback((field: SortColumnField, direction: Direction) => { + dispatch({ + type: 'onTableSortChange', + data: { field, direction }, + }); + }, []); + + const onTableChange = useCallback((criteria: CriteriaWithPagination) => { + dispatch({ type: 'onTableChange', data: criteria }); + }, []); + const deleteSelectedItems = useCallback(async () => { if (isDeletingItems) { return; @@ -468,6 +485,7 @@ function TableListViewComp({ isFetchingItems={isFetchingItems} searchQuery={searchQuery} tableColumns={tableColumns} + hasUpdatedAtMetadata={hasUpdatedAtMetadata} tableSort={tableSort} pagination={pagination} selectedIds={selectedIds} @@ -475,6 +493,8 @@ function TableListViewComp({ entityNamePlural={entityNamePlural} deleteItems={deleteItems} tableCaption={tableListTitle} + onTableChange={onTableChange} + onSortChange={onSortChange} /> {/* Delete modal */} diff --git a/packages/content-management/table_list/tsconfig.json b/packages/content-management/table_list/tsconfig.json index f9da39a3d7eb9..df09013c1e96f 100644 --- a/packages/content-management/table_list/tsconfig.json +++ b/packages/content-management/table_list/tsconfig.json @@ -11,7 +11,8 @@ "node", "react", "@kbn/ambient-ui-types", - "@kbn/ambient-storybook-types" + "@kbn/ambient-storybook-types", + "@emotion/react/types/css-prop" ] }, "include": [ diff --git a/packages/kbn-apm-synthtrace/src/lib/apm/apm_fields.ts b/packages/kbn-apm-synthtrace/src/lib/apm/apm_fields.ts index 7736aa8e8879b..07379b2a3002d 100644 --- a/packages/kbn-apm-synthtrace/src/lib/apm/apm_fields.ts +++ b/packages/kbn-apm-synthtrace/src/lib/apm/apm_fields.ts @@ -58,6 +58,8 @@ export type ApmFields = Fields & 'error.grouping_key': string; 'host.name': string; 'host.hostname': string; + 'http.request.method': string; + 'http.response.status_code': number; 'kubernetes.pod.uid': string; 'kubernetes.pod.name': string; 'metricset.name': string; @@ -84,14 +86,13 @@ export type ApmFields = Fields & 'service.framework.name': string; 'service.target.name': string; 'service.target.type': string; + 'span.action': string; 'span.id': string; 'span.name': string; 'span.type': string; 'span.subtype': string; 'span.duration.us': number; - 'span.destination.service.name': string; 'span.destination.service.resource': string; - 'span.destination.service.type': string; 'span.destination.service.response_time.sum.us': number; 'span.destination.service.response_time.count': number; 'span.self_time.count': number; diff --git a/packages/kbn-apm-synthtrace/src/lib/apm/base_span.ts b/packages/kbn-apm-synthtrace/src/lib/apm/base_span.ts index f8c058592a494..0cfe5940405a2 100644 --- a/packages/kbn-apm-synthtrace/src/lib/apm/base_span.ts +++ b/packages/kbn-apm-synthtrace/src/lib/apm/base_span.ts @@ -40,6 +40,10 @@ export class BaseSpan extends Serializable { return this; } + getChildren() { + return this._children; + } + children(...children: BaseSpan[]): this { children.forEach((child) => { child.parent(this); diff --git a/packages/kbn-apm-synthtrace/src/lib/apm/client/apm_synthtrace_apm_client.ts b/packages/kbn-apm-synthtrace/src/lib/apm/client/apm_synthtrace_apm_client.ts index da836cd8a2119..af200a103558e 100644 --- a/packages/kbn-apm-synthtrace/src/lib/apm/client/apm_synthtrace_apm_client.ts +++ b/packages/kbn-apm-synthtrace/src/lib/apm/client/apm_synthtrace_apm_client.ts @@ -148,9 +148,7 @@ export class ApmSynthtraceApmClient { const destination = (e.context.destination = e.context.destination ?? {}); const destinationService = (destination.service = destination.service ?? { resource: '' }); - set('span.destination.service.name', destinationService, (c, v) => (c.name = v)); set('span.destination.service.resource', destinationService, (c, v) => (c.resource = v)); - set('span.destination.service.type', destinationService, (c, v) => (c.type = v)); } if (e.kind === 'transaction') { set('transaction.name', e, (c, v) => (c.name = v)); diff --git a/packages/kbn-apm-synthtrace/src/lib/apm/instance.ts b/packages/kbn-apm-synthtrace/src/lib/apm/instance.ts index 32a81de9f307a..f69e54b3e300b 100644 --- a/packages/kbn-apm-synthtrace/src/lib/apm/instance.ts +++ b/packages/kbn-apm-synthtrace/src/lib/apm/instance.ts @@ -13,6 +13,12 @@ import { Span } from './span'; import { Transaction } from './transaction'; import { ApmApplicationMetricFields, ApmFields } from './apm_fields'; +export type SpanParams = { + spanName: string; + spanType: string; + spanSubtype?: string; +} & ApmFields; + export class Instance extends Entity { transaction({ transactionName, @@ -28,16 +34,7 @@ export class Instance extends Entity { }); } - span({ - spanName, - spanType, - spanSubtype, - ...apmFields - }: { - spanName: string; - spanType: string; - spanSubtype?: string; - } & ApmFields) { + span({ spanName, spanType, spanSubtype, ...apmFields }: SpanParams) { return new Span({ ...this.fields, ...apmFields, diff --git a/packages/kbn-apm-synthtrace/src/lib/apm/span.ts b/packages/kbn-apm-synthtrace/src/lib/apm/span.ts index a5795ae321478..99e0b1053014a 100644 --- a/packages/kbn-apm-synthtrace/src/lib/apm/span.ts +++ b/packages/kbn-apm-synthtrace/src/lib/apm/span.ts @@ -10,6 +10,7 @@ import url from 'url'; import { BaseSpan } from './base_span'; import { generateShortId } from '../utils/generate_id'; import { ApmFields } from './apm_fields'; +import { SpanParams } from './instance'; export class Span extends BaseSpan { constructor(fields: ApmFields) { @@ -25,29 +26,26 @@ export class Span extends BaseSpan { return this; } - destination(resource: string, type?: string, name?: string) { - if (!type) { - type = this.fields['span.type']; - } - - if (!name) { - name = resource; - } + destination(resource: string) { this.fields['span.destination.service.resource'] = resource; - this.fields['span.destination.service.name'] = name; - this.fields['span.destination.service.type'] = type; return this; } } +export type HttpMethod = 'GET' | 'POST' | 'DELETE' | 'PUT'; + export function httpExitSpan({ spanName, destinationUrl, + method = 'GET', + statusCode = 200, }: { spanName: string; destinationUrl: string; -}) { + method?: HttpMethod; + statusCode?: number; +}): SpanParams { // origin: 'http://opbeans-go:3000', // host: 'opbeans-go:3000', // hostname: 'opbeans-go', @@ -55,31 +53,98 @@ export function httpExitSpan({ const destination = new url.URL(destinationUrl); const spanType = 'external'; - const spanSubType = 'http'; + const spanSubtype = 'http'; return { spanName, spanType, - spanSubType, + spanSubtype, + + // http + 'span.action': method, + 'http.request.method': method, + 'http.response.status_code': statusCode, + + // destination 'destination.address': destination.hostname, 'destination.port': parseInt(destination.port, 10), 'service.target.name': destination.host, - 'span.destination.service.name': destination.origin, 'span.destination.service.resource': destination.host, - 'span.destination.service.type': 'external', }; } -export function dbExitSpan({ spanName, spanSubType }: { spanName: string; spanSubType?: string }) { +export function dbExitSpan({ spanName, spanSubtype }: { spanName: string; spanSubtype?: string }) { const spanType = 'db'; return { spanName, spanType, - spanSubType, - 'service.target.type': spanSubType, - 'span.destination.service.name': spanSubType, - 'span.destination.service.resource': spanSubType, - 'span.destination.service.type': spanType, + spanSubtype, + 'service.target.type': spanSubtype, + 'span.destination.service.resource': spanSubtype, + }; +} + +export function elasticsearchSpan(spanName: string, statement?: string): SpanParams { + const spanType = 'db'; + const spanSubtype = 'elasticsearch'; + + return { + spanName, + spanType, + spanSubtype, + + ...(statement + ? { + 'span.db.statement': statement, + 'span.db.type': 'elasticsearch', + } + : {}), + + 'service.target.type': spanSubtype, + 'destination.address': 'qwerty.us-west2.gcp.elastic-cloud.com', + 'destination.port': 443, + 'span.destination.service.resource': spanSubtype, + }; +} + +export function sqliteSpan(spanName: string, statement?: string): SpanParams { + const spanType = 'db'; + const spanSubtype = 'sqlite'; + + return { + spanName, + spanType, + spanSubtype, + + ...(statement + ? { + 'span.db.statement': statement, + 'span.db.type': 'sql', + } + : {}), + + // destination + 'service.target.type': spanSubtype, + 'destination.address': 'qwerty.us-west2.gcp.elastic-cloud.com', + 'destination.port': 443, + 'span.destination.service.resource': spanSubtype, + }; +} + +export function redisSpan(spanName: string): SpanParams { + const spanType = 'db'; + const spanSubtype = 'redis'; + + return { + spanName, + spanType, + spanSubtype, + + // destination + 'service.target.type': spanSubtype, + 'destination.address': 'qwerty.us-west2.gcp.elastic-cloud.com', + 'destination.port': 443, + 'span.destination.service.resource': spanSubtype, }; } diff --git a/packages/kbn-apm-synthtrace/src/lib/dsl/distributed_trace_client.test.ts b/packages/kbn-apm-synthtrace/src/lib/dsl/distributed_trace_client.test.ts new file mode 100644 index 0000000000000..87e508abe87db --- /dev/null +++ b/packages/kbn-apm-synthtrace/src/lib/dsl/distributed_trace_client.test.ts @@ -0,0 +1,221 @@ +/* + * 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 { apm } from '../apm'; +import { ApmFields } from '../apm/apm_fields'; +import { BaseSpan } from '../apm/base_span'; +import { DistributedTrace } from './distributed_trace_client'; + +const opbeansRum = apm + .service({ name: 'opbeans-rum', environment: 'prod', agentName: 'rum-js' }) + .instance('my-instance'); + +const opbeansNode = apm + .service({ name: 'opbeans-node', environment: 'prod', agentName: 'nodejs' }) + .instance('my-instance'); + +const opbeansGo = apm + .service({ name: 'opbeans-go', environment: 'prod', agentName: 'go' }) + .instance('my-instance'); + +describe('DistributedTrace', () => { + describe('basic scenario', () => { + it('should add latency', () => { + const dt = new DistributedTrace({ + serviceInstance: opbeansRum, + transactionName: 'Dashboard', + timestamp: 0, + children: (s) => { + s.service({ + serviceInstance: opbeansNode, + transactionName: 'GET /nodejs/products', + + children: (_) => { + _.service({ serviceInstance: opbeansGo, transactionName: 'GET /gogo' }); + _.db({ name: 'GET apm-*/_search', type: 'elasticsearch', duration: 400 }); + }, + }); + }, + }).getTransaction(); + + const traceDocs = getTraceDocs(dt); + const formattedDocs = traceDocs.map((f) => { + return { + processorEvent: f['processor.event'], + timestamp: f['@timestamp'], + duration: (f['transaction.duration.us'] ?? f['span.duration.us'])! / 1000, + name: f['transaction.name'] ?? f['span.name'], + }; + }); + + expect(formattedDocs).toMatchInlineSnapshot(` + Array [ + Object { + "duration": 400, + "name": "Dashboard", + "processorEvent": "transaction", + "timestamp": 0, + }, + Object { + "duration": 400, + "name": "GET /nodejs/products", + "processorEvent": "span", + "timestamp": 0, + }, + Object { + "duration": 400, + "name": "GET /nodejs/products", + "processorEvent": "transaction", + "timestamp": 0, + }, + Object { + "duration": 0, + "name": "GET /gogo", + "processorEvent": "span", + "timestamp": 0, + }, + Object { + "duration": 0, + "name": "GET /gogo", + "processorEvent": "transaction", + "timestamp": 0, + }, + Object { + "duration": 400, + "name": "GET apm-*/_search", + "processorEvent": "span", + "timestamp": 0, + }, + ] + `); + }); + }); + + describe('latency', () => { + it('should add latency', () => { + const traceDocs = getSimpleScenario({ latency: 500 }); + const timestamps = traceDocs.map((f) => f['@timestamp']); + expect(timestamps).toMatchInlineSnapshot(` + Array [ + 0, + 0, + 250, + 250, + 250, + 250, + ] + `); + }); + + it('should not add latency', () => { + const traceDocs = getSimpleScenario(); + const timestamps = traceDocs.map((f) => f['@timestamp']); + expect(timestamps).toMatchInlineSnapshot(` + Array [ + 0, + 0, + 0, + 0, + 0, + 0, + ] + `); + }); + }); + + describe('duration', () => { + it('should add duration', () => { + const traceDocs = getSimpleScenario({ duration: 3000 }); + const durations = traceDocs.map( + (f) => (f['transaction.duration.us'] ?? f['span.duration.us'])! / 1000 + ); + expect(durations).toMatchInlineSnapshot(` + Array [ + 3000, + 3000, + 3000, + 300, + 400, + 500, + ] + `); + }); + + it('should not add duration', () => { + const traceDocs = getSimpleScenario(); + const durations = traceDocs.map( + (f) => (f['transaction.duration.us'] ?? f['span.duration.us'])! / 1000 + ); + expect(durations).toMatchInlineSnapshot(` + Array [ + 500, + 500, + 500, + 300, + 400, + 500, + ] + `); + }); + }); + + describe('repeat', () => { + it('produces few trace documents when "repeat" is disabled', () => { + const traceDocs = getSimpleScenario({ repeat: undefined }); + expect(traceDocs.length).toBe(6); + }); + + it('produces more trace documents when "repeat" is enabled', () => { + const traceDocs = getSimpleScenario({ repeat: 20 }); + expect(traceDocs.length).toBe(101); + }); + }); +}); + +function getTraceDocs(transaction: BaseSpan): ApmFields[] { + const children = transaction.getChildren(); + if (children) { + const childFields = children.flatMap((child) => getTraceDocs(child)); + return [transaction.fields, ...childFields]; + } + + return [transaction.fields]; +} + +function getSimpleScenario({ + duration, + latency, + repeat, +}: { + duration?: number; + latency?: number; + repeat?: number; +} = {}) { + const dt = new DistributedTrace({ + serviceInstance: opbeansRum, + transactionName: 'Dashboard', + timestamp: 0, + children: (s) => { + s.service({ + serviceInstance: opbeansNode, + transactionName: 'GET /nodejs/products', + duration, + latency, + repeat, + + children: (_) => { + _.db({ name: 'GET apm-*/_search', type: 'elasticsearch', duration: 300 }); + _.db({ name: 'GET apm-*/_search', type: 'elasticsearch', duration: 400 }); + _.db({ name: 'GET apm-*/_search', type: 'elasticsearch', duration: 500 }); + }, + }); + }, + }).getTransaction(); + + return getTraceDocs(dt); +} diff --git a/packages/kbn-apm-synthtrace/src/lib/dsl/distributed_trace_client.ts b/packages/kbn-apm-synthtrace/src/lib/dsl/distributed_trace_client.ts new file mode 100644 index 0000000000000..ceeb94f871e3a --- /dev/null +++ b/packages/kbn-apm-synthtrace/src/lib/dsl/distributed_trace_client.ts @@ -0,0 +1,183 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 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 { times } from 'lodash'; +import { elasticsearchSpan, httpExitSpan, HttpMethod, redisSpan, sqliteSpan } from '../apm/span'; +import { BaseSpan } from '../apm/base_span'; +import { Instance, SpanParams } from '../apm/instance'; +import { Transaction } from '../apm/transaction'; + +export class DistributedTrace { + timestamp: number; + serviceInstance: Instance; + spanEndTimes: number[] = []; + childSpans: BaseSpan[] = []; + transaction: Transaction; + + constructor({ + serviceInstance, + transactionName, + timestamp, + children, + }: { + serviceInstance: Instance; + transactionName: string; + timestamp: number; + children?: (dt: DistributedTrace) => void; + }) { + this.timestamp = timestamp; + this.serviceInstance = serviceInstance; + + if (children) { + children(this); + } + + const maxEndTime = Math.max(...this.spanEndTimes); + const duration = maxEndTime - this.timestamp; + + this.transaction = serviceInstance + .transaction({ transactionName }) + .timestamp(timestamp) + .duration(duration) + .children(...this.childSpans); + + return this; + } + + getTransaction() { + return this.transaction; + } + + service({ + serviceInstance, + transactionName, + latency = 0, + repeat = 1, + timestamp = this.timestamp, + duration, + children, + }: { + serviceInstance: Instance; + transactionName: string; + repeat?: number; + timestamp?: number; + latency?: number; + duration?: number; + children?: (dt: DistributedTrace) => unknown; + }) { + const originServiceInstance = this.serviceInstance; + + times(repeat, () => { + const dt = new DistributedTrace({ + serviceInstance, + transactionName, + timestamp: timestamp + latency / 2, + children, + }); + + const maxSpanEndTime = Math.max(...dt.spanEndTimes, timestamp + (duration ?? 0)); + this.spanEndTimes.push(maxSpanEndTime + latency / 2); + + // origin service + const exitSpanStart = timestamp; + const exitSpanDuration = (duration ?? maxSpanEndTime - exitSpanStart) + latency / 2; + + // destination service + const transactionStart = timestamp + latency / 2; + const transactionDuration = duration ?? maxSpanEndTime - transactionStart; + + const span = originServiceInstance + .span( + httpExitSpan({ + spanName: transactionName, + destinationUrl: 'http://api-gateway:3000', // TODO: this should be derived from serviceInstance + }) + ) + .duration(exitSpanDuration) + .timestamp(exitSpanStart) + .children( + dt.serviceInstance + .transaction({ transactionName }) + .timestamp(transactionStart) + .duration(transactionDuration) + .children(...(dt.childSpans ?? [])) + ); + + this.childSpans.push(span); + }); + } + + external({ + name, + url, + method, + statusCode, + duration, + timestamp = this.timestamp, + }: { + name: string; + url: string; + method?: HttpMethod; + statusCode?: number; + duration: number; + timestamp?: number; + }) { + const startTime = timestamp; + const endTime = startTime + duration; + this.spanEndTimes.push(endTime); + + const span = this.serviceInstance + .span(httpExitSpan({ spanName: name, destinationUrl: url, method, statusCode })) + .timestamp(startTime) + .duration(duration) + .success(); + + this.childSpans.push(span); + } + + db({ + name, + duration, + type, + statement, + timestamp = this.timestamp, + }: { + name: string; + duration: number; + type: 'elasticsearch' | 'sqlite' | 'redis'; + statement?: string; + timestamp?: number; + }) { + const startTime = timestamp; + const endTime = startTime + duration; + this.spanEndTimes.push(endTime); + + let dbSpan: SpanParams; + switch (type) { + case 'elasticsearch': + dbSpan = elasticsearchSpan(name, statement); + break; + + case 'sqlite': + dbSpan = sqliteSpan(name, statement); + break; + + case 'redis': + dbSpan = redisSpan(name); + break; + } + + const span = this.serviceInstance + .span(dbSpan) + .timestamp(startTime) + .duration(duration) + .success(); + + this.childSpans.push(span); + } +} diff --git a/packages/kbn-apm-synthtrace/src/scenarios/distributed_trace_long.ts b/packages/kbn-apm-synthtrace/src/scenarios/distributed_trace_long.ts new file mode 100644 index 0000000000000..32542ee2c1d49 --- /dev/null +++ b/packages/kbn-apm-synthtrace/src/scenarios/distributed_trace_long.ts @@ -0,0 +1,134 @@ +/* + * 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. + */ + +/* eslint-disable @typescript-eslint/no-shadow */ + +import { apm, timerange } from '../..'; +import { ApmFields } from '../lib/apm/apm_fields'; +import { Scenario } from '../cli/scenario'; +import { RunOptions } from '../cli/utils/parse_run_cli_flags'; +import { getSynthtraceEnvironment } from '../lib/utils/get_synthtrace_environment'; +import { DistributedTrace } from '../lib/dsl/distributed_trace_client'; + +const ENVIRONMENT = getSynthtraceEnvironment(__filename); + +const scenario: Scenario = async (runOptions: RunOptions) => { + return { + generate: ({ from, to }) => { + const ratePerMinute = 1; + const traceDuration = 1100; + const rootTransactionName = `${ratePerMinute}rpm / ${traceDuration}ms`; + + const opbeansRum = apm + .service({ name: 'opbeans-rum', environment: ENVIRONMENT, agentName: 'rum-js' }) + .instance('my-instance'); + + const opbeansNode = apm + .service({ name: 'opbeans-node', environment: ENVIRONMENT, agentName: 'nodejs' }) + .instance('my-instance'); + + const opbeansGo = apm + .service({ name: 'opbeans-go', environment: ENVIRONMENT, agentName: 'go' }) + .instance('my-instance'); + + const opbeansDotnet = apm + .service({ name: 'opbeans-dotnet', environment: ENVIRONMENT, agentName: 'dotnet' }) + .instance('my-instance'); + + const opbeansJava = apm + .service({ name: 'opbeans-java', environment: ENVIRONMENT, agentName: 'java' }) + .instance('my-instance'); + + const traces = timerange(from, to) + .ratePerMinute(ratePerMinute) + .generator((timestamp) => { + return new DistributedTrace({ + serviceInstance: opbeansRum, + transactionName: rootTransactionName, + timestamp, + children: (_) => { + _.service({ + repeat: 10, + serviceInstance: opbeansNode, + transactionName: 'GET /nodejs/products', + latency: 100, + + children: (_) => { + _.service({ + serviceInstance: opbeansGo, + transactionName: 'GET /go', + children: (_) => { + _.service({ + repeat: 20, + serviceInstance: opbeansJava, + transactionName: 'GET /java', + children: (_) => { + _.external({ + name: 'GET telemetry.elastic.co', + url: 'https://telemetry.elastic.co/ping', + duration: 50, + }); + }, + }); + }, + }); + _.db({ name: 'GET apm-*/_search', type: 'elasticsearch', duration: 400 }); + _.db({ name: 'GET', type: 'redis', duration: 500 }); + _.db({ name: 'SELECT * FROM users', type: 'sqlite', duration: 600 }); + }, + }); + + _.service({ + serviceInstance: opbeansNode, + transactionName: 'GET /nodejs/users', + latency: 100, + repeat: 10, + children: (_) => { + _.service({ + serviceInstance: opbeansGo, + transactionName: 'GET /go/security', + latency: 50, + children: (_) => { + _.service({ + repeat: 10, + serviceInstance: opbeansDotnet, + transactionName: 'GET /dotnet/cases/4', + latency: 50, + children: (_) => + _.db({ + name: 'GET apm-*/_search', + type: 'elasticsearch', + duration: 600, + statement: JSON.stringify( + { + query: { + query_string: { + query: '(new york city) OR (big apple)', + default_field: 'content', + }, + }, + }, + null, + 2 + ), + }), + }); + }, + }); + }, + }); + }, + }).getTransaction(); + }); + + return traces; + }, + }; +}; + +export default scenario; diff --git a/packages/kbn-babel-preset/node_preset.js b/packages/kbn-babel-preset/node_preset.js index caf5f7dce419e..31cebf7e1715a 100644 --- a/packages/kbn-babel-preset/node_preset.js +++ b/packages/kbn-babel-preset/node_preset.js @@ -31,7 +31,7 @@ module.exports = (_, options = {}) => { // Because of that we should use for that value the same version we install // in the package.json in order to have the same polyfills between the environment // and the tests - corejs: '3.25.1', + corejs: '3.25.5', bugfixes: true, ...(options['@babel/preset-env'] || {}), diff --git a/packages/kbn-babel-preset/webpack_preset.js b/packages/kbn-babel-preset/webpack_preset.js index 5d2fa5a627fb6..171b00911db17 100644 --- a/packages/kbn-babel-preset/webpack_preset.js +++ b/packages/kbn-babel-preset/webpack_preset.js @@ -18,7 +18,7 @@ module.exports = (_, options = {}) => { modules: false, // Please read the explanation for this // in node_preset.js - corejs: '3.25.1', + corejs: '3.25.5', bugfixes: true, }, ], diff --git a/packages/kbn-cases-components/BUILD.bazel b/packages/kbn-cases-components/BUILD.bazel new file mode 100644 index 0000000000000..ef6db08ca7540 --- /dev/null +++ b/packages/kbn-cases-components/BUILD.bazel @@ -0,0 +1,125 @@ +load("@npm//@bazel/typescript:index.bzl", "ts_config") +load("@build_bazel_rules_nodejs//:index.bzl", "js_library") +load("//src/dev/bazel:index.bzl", "jsts_transpiler", "pkg_npm", "pkg_npm_types", "ts_project") + +PKG_DIRNAME = "kbn-cases-components" +PKG_REQUIRE_NAME = "@kbn/cases-components" + +SOURCE_FILES = glob( + [ + "**/*.ts", + "**/*.tsx", + ], + exclude = [ + "**/*.config.js", + "**/*.mock.*", + "**/*.test.*", + "**/*.stories.*", + "**/__snapshots__/**", + "**/integration_tests/**", + "**/mocks/**", + "**/scripts/**", + "**/storybook/**", + "**/test_fixtures/**", + "**/test_helpers/**", + ], +) + +SRCS = SOURCE_FILES + +filegroup( + name = "srcs", + srcs = SRCS, +) + +NPM_MODULE_EXTRA_FILES = [ + "package.json", +] + +RUNTIME_DEPS = [ + "//packages/kbn-i18n", + "//packages/kbn-i18n-react", + "@npm//@elastic/eui", + "@npm//@testing-library/react", + "@npm//react", +] + +TYPES_DEPS = [ + "//packages/kbn-i18n:npm_module_types", + "//packages/kbn-i18n-react:npm_module_types", + "@npm//@elastic/eui", + "@npm//@types/node", + "@npm//@types/jest", + "@npm//@testing-library/react", + "@npm//tslib", + "@npm//@types/react", + "@npm//@testing-library/jest-dom", +] + +jsts_transpiler( + name = "target_node", + srcs = SRCS, + build_pkg_name = package_name(), +) + +jsts_transpiler( + name = "target_web", + srcs = SRCS, + build_pkg_name = package_name(), + web = True, +) + +ts_config( + name = "tsconfig", + src = "tsconfig.json", + deps = [ + "//:tsconfig.base.json", + "//:tsconfig.bazel.json", + ], +) + +ts_project( + name = "tsc_types", + args = ['--pretty'], + srcs = SRCS, + deps = TYPES_DEPS, + declaration = True, + declaration_map = True, + emit_declaration_only = True, + out_dir = "target_types", + tsconfig = ":tsconfig", +) + +js_library( + name = PKG_DIRNAME, + srcs = NPM_MODULE_EXTRA_FILES, + deps = RUNTIME_DEPS + [":target_node", ":target_web"], + package_name = PKG_REQUIRE_NAME, + visibility = ["//visibility:public"], +) + +pkg_npm( + name = "npm_module", + deps = [":" + PKG_DIRNAME], +) + +filegroup( + name = "build", + srcs = [":npm_module"], + visibility = ["//visibility:public"], +) + +pkg_npm_types( + name = "npm_module_types", + srcs = SRCS, + deps = [":tsc_types"], + package_name = PKG_REQUIRE_NAME, + tsconfig = ":tsconfig", + visibility = ["//visibility:public"], +) + +filegroup( + name = "build_types", + srcs = [":npm_module_types"], + visibility = ["//visibility:public"], +) diff --git a/packages/kbn-cases-components/README.md b/packages/kbn-cases-components/README.md new file mode 100644 index 0000000000000..bc60e2fba7fe5 --- /dev/null +++ b/packages/kbn-cases-components/README.md @@ -0,0 +1,15 @@ +# @kbn/cases-components + +The package exports a collection of pure Cases components. + +## Components + +### Status + +The component renders the status of a case. Usage: + +``` +import { Status, CaseStatuses } from '@kbn/cases-components'; + + +``` diff --git a/packages/kbn-cases-components/index.ts b/packages/kbn-cases-components/index.ts new file mode 100644 index 0000000000000..47a7a298f0e1d --- /dev/null +++ b/packages/kbn-cases-components/index.ts @@ -0,0 +1,11 @@ +/* + * 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. + */ + +export { Status } from './src/status/status'; +export { CaseStatuses } from './src/status/types'; +export { getStatusConfiguration } from './src/status/config'; diff --git a/packages/kbn-cases-components/jest.config.js b/packages/kbn-cases-components/jest.config.js new file mode 100644 index 0000000000000..aae0428a0ee0d --- /dev/null +++ b/packages/kbn-cases-components/jest.config.js @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 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: ['/packages/kbn-cases-components'], + setupFilesAfterEnv: ['/packages/kbn-cases-components/setup_tests.ts'], +}; diff --git a/packages/kbn-cases-components/kibana.jsonc b/packages/kbn-cases-components/kibana.jsonc new file mode 100644 index 0000000000000..6893f2473ed17 --- /dev/null +++ b/packages/kbn-cases-components/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/cases-components", + "owner": "@elastic/response-ops", + "runtimeDeps": [], + "typeDeps": [], +} diff --git a/packages/kbn-cases-components/package.json b/packages/kbn-cases-components/package.json new file mode 100644 index 0000000000000..eeb816ca5538b --- /dev/null +++ b/packages/kbn-cases-components/package.json @@ -0,0 +1,8 @@ +{ + "name": "@kbn/cases-components", + "private": true, + "version": "1.0.0", + "main": "./target_node/index.js", + "browser": "./target_web/index.js", + "license": "SSPL-1.0 OR Elastic License 2.0" +} diff --git a/src/plugins/vis_types/gauge/public/utils/index.ts b/packages/kbn-cases-components/setup_tests.ts similarity index 78% rename from src/plugins/vis_types/gauge/public/utils/index.ts rename to packages/kbn-cases-components/setup_tests.ts index fb23c97d835fe..8d1acb9232934 100644 --- a/src/plugins/vis_types/gauge/public/utils/index.ts +++ b/packages/kbn-cases-components/setup_tests.ts @@ -6,4 +6,5 @@ * Side Public License, v 1. */ -export { getStopsWithColorsFromRanges } from './palette'; +// eslint-disable-next-line import/no-extraneous-dependencies +import '@testing-library/jest-dom'; diff --git a/packages/kbn-cases-components/src/status/config.ts b/packages/kbn-cases-components/src/status/config.ts new file mode 100644 index 0000000000000..b8d3a558fb406 --- /dev/null +++ b/packages/kbn-cases-components/src/status/config.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 * as i18n from './translations'; +import { CaseStatuses } from './types'; + +export const getStatusConfiguration = () => ({ + [CaseStatuses.open]: { + color: 'primary', + label: i18n.OPEN, + icon: 'folderOpen' as const, + }, + [CaseStatuses['in-progress']]: { + color: 'warning', + label: i18n.IN_PROGRESS, + icon: 'folderExclamation' as const, + }, + [CaseStatuses.closed]: { + color: 'default', + label: i18n.CLOSED, + icon: 'folderCheck' as const, + }, +}); diff --git a/packages/kbn-cases-components/src/status/status.test.tsx b/packages/kbn-cases-components/src/status/status.test.tsx new file mode 100644 index 0000000000000..3796fc3627e66 --- /dev/null +++ b/packages/kbn-cases-components/src/status/status.test.tsx @@ -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 React from 'react'; +import { render } from '@testing-library/react'; + +import { Status } from './status'; +import { CaseStatuses } from './types'; +import { getStatusConfiguration } from './config'; + +const statusConfiguration = getStatusConfiguration(); + +describe('Stats', () => { + it.each([[CaseStatuses.open], [CaseStatuses['in-progress']], [CaseStatuses.closed]])( + 'renders correctly with status: %s', + async (status) => { + const res = render(); + const label = statusConfiguration[status].label; + + expect(res.getByText(label)).toBeInTheDocument(); + } + ); +}); diff --git a/packages/kbn-cases-components/src/status/status.tsx b/packages/kbn-cases-components/src/status/status.tsx new file mode 100644 index 0000000000000..ec1bacafa0468 --- /dev/null +++ b/packages/kbn-cases-components/src/status/status.tsx @@ -0,0 +1,35 @@ +/* + * 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, { memo } from 'react'; +import { EuiBadge } from '@elastic/eui'; + +import { getStatusConfiguration } from './config'; +import { CaseStatuses } from './types'; + +interface Props { + status: CaseStatuses; + dataTestSubj?: string; +} + +const statuses = getStatusConfiguration(); + +const CaseStatusComponent: React.FC = ({ status, dataTestSubj }) => { + return ( + + {statuses[status]?.label} + + ); +}; + +CaseStatusComponent.displayName = 'Status'; + +export const Status = memo(CaseStatusComponent); diff --git a/packages/kbn-cases-components/src/status/translations.ts b/packages/kbn-cases-components/src/status/translations.ts new file mode 100644 index 0000000000000..6b73166ebf9c2 --- /dev/null +++ b/packages/kbn-cases-components/src/status/translations.ts @@ -0,0 +1,21 @@ +/* + * 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 { i18n } from '@kbn/i18n'; + +export const OPEN = i18n.translate('cases.components.status.open', { + defaultMessage: 'Open', +}); + +export const IN_PROGRESS = i18n.translate('cases.components.status.inProgress', { + defaultMessage: 'In progress', +}); + +export const CLOSED = i18n.translate('cases.components.status.closed', { + defaultMessage: 'Closed', +}); diff --git a/src/plugins/vis_types/metric/public/utils/index.ts b/packages/kbn-cases-components/src/status/types.ts similarity index 78% rename from src/plugins/vis_types/metric/public/utils/index.ts rename to packages/kbn-cases-components/src/status/types.ts index fb23c97d835fe..228867340d3c6 100644 --- a/src/plugins/vis_types/metric/public/utils/index.ts +++ b/packages/kbn-cases-components/src/status/types.ts @@ -6,4 +6,8 @@ * Side Public License, v 1. */ -export { getStopsWithColorsFromRanges } from './palette'; +export enum CaseStatuses { + open = 'open', + 'in-progress' = 'in-progress', + closed = 'closed', +} diff --git a/packages/kbn-cases-components/tsconfig.json b/packages/kbn-cases-components/tsconfig.json new file mode 100644 index 0000000000000..171db889bdd36 --- /dev/null +++ b/packages/kbn-cases-components/tsconfig.json @@ -0,0 +1,19 @@ +{ + "extends": "../../tsconfig.bazel.json", + "compilerOptions": { + "declaration": true, + "declarationMap": true, + "emitDeclarationOnly": true, + "outDir": "target_types", + "stripInternal": false, + "types": [ + "jest", + "node", + "react" + ] + }, + "include": [ + "**/*.ts", + "**/*.tsx", + ] +} diff --git a/packages/kbn-doc-links/src/get_doc_links.ts b/packages/kbn-doc-links/src/get_doc_links.ts index b7a3326942582..e848c29437351 100644 --- a/packages/kbn-doc-links/src/get_doc_links.ts +++ b/packages/kbn-doc-links/src/get_doc_links.ts @@ -126,7 +126,6 @@ export const getDocLinks = ({ kibanaBranch }: GetDocLinkOptions): DocLinks => { connectorsMongoDB: `${ENTERPRISE_SEARCH_DOCS}connectors-mongodb.html`, connectorsMySQL: `${ENTERPRISE_SEARCH_DOCS}connectors-mysql.html`, connectorsWorkplaceSearch: `${ENTERPRISE_SEARCH_DOCS}connectors.html#connectors-workplace-search`, - contentExtraction: `${ENTERPRISE_SEARCH_DOCS}content-extraction.html`, crawlerGettingStarted: `${ENTERPRISE_SEARCH_DOCS}crawler-getting-started.html`, crawlerManaging: `${ENTERPRISE_SEARCH_DOCS}crawler-managing.html`, crawlerOverview: `${ENTERPRISE_SEARCH_DOCS}crawler.html`, @@ -376,6 +375,9 @@ export const getDocLinks = ({ kibanaBranch }: GetDocLinkOptions): DocLinks => { }, responseActions: `${SECURITY_SOLUTION_DOCS}response-actions.html`, configureEndpointIntegrationPolicy: `${SECURITY_SOLUTION_DOCS}configure-endpoint-integration-policy.html`, + exceptions: { + value_lists: `${SECURITY_SOLUTION_DOCS}detections-ui-exceptions.html#manage-value-lists`, + }, }, query: { eql: `${ELASTICSEARCH_DOCS}eql.html`, diff --git a/packages/kbn-doc-links/src/types.ts b/packages/kbn-doc-links/src/types.ts index 16a80e7f7bf33..9e75b09cd946e 100644 --- a/packages/kbn-doc-links/src/types.ts +++ b/packages/kbn-doc-links/src/types.ts @@ -111,7 +111,6 @@ export interface DocLinks { readonly connectorsMongoDB: string; readonly connectorsMySQL: string; readonly connectorsWorkplaceSearch: string; - readonly contentExtraction: string; readonly crawlerGettingStarted: string; readonly crawlerManaging: string; readonly crawlerOverview: string; @@ -278,6 +277,9 @@ export interface DocLinks { readonly threatIntelInt: string; readonly responseActions: string; readonly configureEndpointIntegrationPolicy: string; + readonly exceptions: { + value_lists: string; + }; }; readonly query: { readonly eql: string; diff --git a/packages/kbn-optimizer/limits.yml b/packages/kbn-optimizer/limits.yml index 67064af8cddc5..07d813b5f6dc8 100644 --- a/packages/kbn-optimizer/limits.yml +++ b/packages/kbn-optimizer/limits.yml @@ -110,7 +110,7 @@ pageLoadAssetSize: share: 71239 snapshotRestore: 79032 spaces: 57868 - stackAlerts: 29684 + stackAlerts: 58316 stackConnectors: 36314 synthetics: 40958 telemetry: 51957 @@ -140,6 +140,6 @@ pageLoadAssetSize: visTypeTimeseries: 55203 visTypeVega: 153573 visTypeVislib: 242838 - visTypeXy: 30000 + visTypeXy: 31800 visualizations: 90000 watcher: 43598 diff --git a/packages/kbn-securitysolution-autocomplete/BUILD.bazel b/packages/kbn-securitysolution-autocomplete/BUILD.bazel index 8b076f2cf8152..d09b4cf04c70a 100644 --- a/packages/kbn-securitysolution-autocomplete/BUILD.bazel +++ b/packages/kbn-securitysolution-autocomplete/BUILD.bazel @@ -44,6 +44,7 @@ RUNTIME_DEPS = [ "//packages/kbn-securitysolution-io-ts-list-types", "//packages/kbn-securitysolution-list-hooks", "//packages/kbn-securitysolution-list-utils", + "//packages/kbn-doc-links", "@npm//@elastic/eui", "@npm//@testing-library/react", "@npm//@testing-library/react-hooks", @@ -60,6 +61,7 @@ TYPES_DEPS = [ "//packages/kbn-securitysolution-io-ts-list-types:npm_module_types", "//packages/kbn-securitysolution-list-hooks:npm_module_types", "//packages/kbn-securitysolution-list-utils:npm_module_types", + "//packages/kbn-doc-links:npm_module_types", "@npm//@elastic/eui", "@npm//@testing-library/react", "@npm//@testing-library/react-hooks", diff --git a/packages/kbn-securitysolution-autocomplete/src/field_value_lists/index.tsx b/packages/kbn-securitysolution-autocomplete/src/field_value_lists/index.tsx index 79f707feaa70d..8a57f90e75ecc 100644 --- a/packages/kbn-securitysolution-autocomplete/src/field_value_lists/index.tsx +++ b/packages/kbn-securitysolution-autocomplete/src/field_value_lists/index.tsx @@ -11,6 +11,7 @@ import { EuiComboBox, EuiComboBoxOptionOption, EuiFormRow, EuiLink, EuiText } fr import type { ListSchema } from '@kbn/securitysolution-io-ts-list-types'; import { useFindListsBySize } from '@kbn/securitysolution-list-hooks'; import { DataViewFieldBase } from '@kbn/es-query'; +import { getDocLinks } from '@kbn/doc-links'; import { filterFieldToList } from '../filter_field_to_list'; import { getGenericComboBoxProps } from '../get_generic_combo_box_props'; @@ -121,7 +122,11 @@ export const AutocompleteFieldListsComponent: React.FC {i18n.LISTS_TOOLTIP_INFO}{' '} - + {i18n.SEE_DOCUMENTATION} diff --git a/packages/kbn-tinymath/README.md b/packages/kbn-tinymath/README.md index 1094c4286c851..3db95cef9adb0 100644 --- a/packages/kbn-tinymath/README.md +++ b/packages/kbn-tinymath/README.md @@ -66,7 +66,10 @@ parse('1 + random()') This package is rebuilt when running `yarn kbn bootstrap`, but can also be build directly using `yarn build` from the `packages/kbn-tinymath` directory. + ### Running tests -To test `@kbn/tinymath` from Kibana, run `yarn run jest --watch packages/kbn-tinymath` from +To test `@kbn/tinymath` from Kibana, run `node scripts/jest --config packages/kbn-tinymath/jest.config.js` from the top level of Kibana. + +To test grammar changes it is required to run a build task before the test suite. diff --git a/packages/kbn-tinymath/docs/functions.md b/packages/kbn-tinymath/docs/functions.md index 0c7460a8189dd..23d267ec975f5 100644 --- a/packages/kbn-tinymath/docs/functions.md +++ b/packages/kbn-tinymath/docs/functions.md @@ -96,6 +96,143 @@ clamp(35, 10, [20, 30, 40, 50]) // returns [20, 30, 35, 35] clamp([1, 9], 3, [4, 5]) // returns [clamp([1, 3, 4]), clamp([9, 3, 5])] = [3, 5] ``` *** +## _eq(_ _a_, _b_ _)_ +Performs an equality comparison between two values. + + +| Param | Type | Description | +| --- | --- | --- | +| a | number \| Array.<number> | a number or an array of numbers | +| b | number \| Array.<number> | a number or an array of numbers | + +**Returns**: boolean - Returns true if `a` and `b` are equal, false otherwise. Returns an array with the equality comparison of each element if `a` is an array. +**Throws**: + +- `'Missing b value'` if `b` is not provided +- `'Array length mismatch'` if `args` contains arrays of different lengths + +**Example** +```js +eq(1, 1) // returns true +eq(1, 2) // returns false +eq([1, 2], 1) // returns [true, false] +eq([1, 2], [1, 2]) // returns [true, true] +``` +*** +## _gt(_ _a_, _b_ _)_ +Performs a greater than comparison between two values. + + +| Param | Type | Description | +| --- | --- | --- | +| a | number \| Array.<number> | a number or an array of numbers | +| b | number \| Array.<number> | a number or an array of numbers | + +**Returns**: boolean - Returns true if `a` is greater than `b`, false otherwise. Returns an array with the greater than comparison of each element if `a` is an array. +**Throws**: + +- `'Missing b value'` if `b` is not provided +- `'Array length mismatch'` if `args` contains arrays of different lengths + +**Example** +```js +gt(1, 1) // returns false +gt(2, 1) // returns true +gt([1, 2], 1) // returns [true, false] +gt([1, 2], [2, 1]) // returns [false, true] +``` +*** +## _gte(_ _a_, _b_ _)_ +Performs a greater than or equal comparison between two values. + + +| Param | Type | Description | +| --- | --- | --- | +| a | number \| Array.<number> | a number or an array of numbers | +| b | number \| Array.<number> | a number or an array of numbers | + +**Returns**: boolean - Returns true if `a` is greater than or equal to `b`, false otherwise. Returns an array with the greater than or equal comparison of each element if `a` is an array. +**Throws**: + +- `'Array length mismatch'` if `args` contains arrays of different lengths + +**Example** +```js +gte(1, 1) // returns true +gte(1, 2) // returns false +gte([1, 2], 2) // returns [false, true] +gte([1, 2], [1, 1]) // returns [true, true] +``` +*** +## _ifelse(_ _cond_, _a_, _b_ _)_ +Evaluates the a conditional argument and returns one of the two values based on that. + + +| Param | Type | Description | +| --- | --- | --- | +| cond | boolean | a boolean value | +| a | any \| Array.<any> | a value or an array of any values | +| b | any \| Array.<any> | a value or an array of any values | + +**Returns**: any \| Array.<any> - if the value of cond is truthy, return `a`, otherwise return `b`. +**Throws**: + +- `'Condition clause is of the wrong type'` if the `cond` provided is not of boolean type +- `'Missing a value'` if `a` is not provided +- `'Missing b value'` if `b` is not provided + +**Example** +```js +ifelse(5 > 6, 1, 0) // returns 0 +ifelse(1 == 1, [1, 2, 3], 5) // returns [1, 2, 3] +ifelse(1 < 2, [1, 2, 3], [2, 3, 4]) // returns [1, 2, 3] +``` +*** +## _lt(_ _a_, _b_ _)_ +Performs a lower than comparison between two values. + + +| Param | Type | Description | +| --- | --- | --- | +| a | number \| Array.<number> | a number or an array of numbers | +| b | number \| Array.<number> | a number or an array of numbers | + +**Returns**: boolean - Returns true if `a` is lower than `b`, false otherwise. Returns an array with the lower than comparison of each element if `a` is an array. +**Throws**: + +- `'Missing b value'` if `b` is not provided +- `'Array length mismatch'` if `args` contains arrays of different lengths + +**Example** +```js +lt(1, 1) // returns false +lt(1, 2) // returns true +lt([1, 2], 2) // returns [true, false] +lt([1, 2], [1, 2]) // returns [false, false] +``` +*** +## _lte(_ _a_, _b_ _)_ +Performs a lower than or equal comparison between two values. + + +| Param | Type | Description | +| --- | --- | --- | +| a | number \| Array.<number> | a number or an array of numbers | +| b | number \| Array.<number> | a number or an array of numbers | + +**Returns**: boolean - Returns true if `a` is lower than or equal to `b`, false otherwise. Returns an array with the lower than or equal comparison of each element if `a` is an array. +**Throws**: + +- `'Array length mismatch'` if `args` contains arrays of different lengths + +**Example** +```js +lte(1, 1) // returns true +lte(1, 2) // returns true +lte([1, 2], 2) // returns [true, true] +lte([1, 2], [1, 1]) // returns [true, false] +``` +*** ## _cos(_ _a_ _)_ Calculates the the cosine of a number. For arrays, the function will be applied index-wise to each element. diff --git a/packages/kbn-tinymath/grammar/grammar.peggy b/packages/kbn-tinymath/grammar/grammar.peggy index 414bc2fa11cb7..7eb5f6c5f82d6 100644 --- a/packages/kbn-tinymath/grammar/grammar.peggy +++ b/packages/kbn-tinymath/grammar/grammar.peggy @@ -11,6 +11,32 @@ max: location.end.offset } } + + const symbolsToFn = { + '+': 'add', '-': 'subtract', + '*': 'multiply', '/': 'divide', + '<': 'lt', '>': 'gt', '==': 'eq', + '<=': 'lte', '>=': 'gte', + } + + // Shared function for AST operations + function parseSymbol(left, rest){ + const topLevel = rest.reduce((acc, [name, right]) => ({ + type: 'function', + name: symbolsToFn[name], + args: [acc, right], + }), left); + if (typeof topLevel === 'object') { + topLevel.location = simpleLocation(location()); + topLevel.text = text(); + } + return topLevel; + } + + // op is always defined, while eq can be null for gt and lt cases + function getComparisonSymbol([op, eq]){ + return symbolsToFn[op+(eq || '')]; + } } start @@ -70,45 +96,55 @@ Variable // expressions +// An Expression can be of 3 different types: +// * a Comparison operation, which can contain recursive MathOperations inside +// * a MathOperation, which can contain other MathOperations, but not Comparison types +// * an ExpressionGroup, which is a generic Grouping that contains also Comparison operations (i.e. ( 5 > 1)) Expression + = Comparison + / MathOperation + / ExpressionGroup + +Comparison + = _ left:MathOperation op:(('>' / '<')('=')? / '=''=') right:MathOperation _ { + return { + type: 'function', + name: getComparisonSymbol(op), + args: [left, right], + location: simpleLocation(location()), + text: text() + }; + } + +MathOperation = AddSubtract + / MultiplyDivide + / Factor AddSubtract = _ left:MultiplyDivide rest:(('+' / '-') MultiplyDivide)+ _ { - const topLevel = rest.reduce((acc, curr) => ({ - type: 'function', - name: curr[0] === '+' ? 'add' : 'subtract', - args: [acc, curr[1]], - }), left); - if (typeof topLevel === 'object') { - topLevel.location = simpleLocation(location()); - topLevel.text = text(); - } - return topLevel; + return parseSymbol(left, rest, {'+': 'add', '-': 'subtract'}); } - / MultiplyDivide MultiplyDivide = _ left:Factor rest:(('*' / '/') Factor)* _ { - const topLevel = rest.reduce((acc, curr) => ({ - type: 'function', - name: curr[0] === '*' ? 'multiply' : 'divide', - args: [acc, curr[1]], - }), left); - if (typeof topLevel === 'object') { - topLevel.location = simpleLocation(location()); - topLevel.text = text(); - } - return topLevel; + return parseSymbol(left, rest, {'*': 'multiply', '/': 'divide'}); } - / Factor Factor = Group / Function / Literal +// Because of the new Comparison syntax it is required a new Group type +// the previous Group has been renamed into ExpressionGroup while +// a new Group type has been defined to exclude the Comparison type from it Group + = _ '(' _ expr:MathOperation _ ')' _ { + return expr + } + +ExpressionGroup = _ '(' _ expr:Expression _ ')' _ { return expr } diff --git a/packages/kbn-tinymath/src/functions/abs.js b/packages/kbn-tinymath/src/functions/abs.js index aa3c808d89afd..46cf65837621b 100644 --- a/packages/kbn-tinymath/src/functions/abs.js +++ b/packages/kbn-tinymath/src/functions/abs.js @@ -17,11 +17,11 @@ * abs([-1 , -2, 3, -4]) // returns [1, 2, 3, 4] */ -module.exports = { abs }; - function abs(a) { if (Array.isArray(a)) { return a.map((a) => Math.abs(a)); } return Math.abs(a); } + +module.exports = { abs }; diff --git a/packages/kbn-tinymath/src/functions/add.js b/packages/kbn-tinymath/src/functions/add.js index 184c619c94534..b1abb23d99f6e 100644 --- a/packages/kbn-tinymath/src/functions/add.js +++ b/packages/kbn-tinymath/src/functions/add.js @@ -17,8 +17,6 @@ * add([1, 2], 3, [4, 5], 6) // returns [(1 + 3 + 4 + 6), (2 + 3 + 5 + 6)] = [14, 16] */ -module.exports = { add }; - function add(...args) { if (args.length === 1) { if (Array.isArray(args[0])) return args[0].reduce((result, current) => result + current); @@ -35,3 +33,4 @@ function add(...args) { return result + current; }); } +module.exports = { add }; diff --git a/packages/kbn-tinymath/src/functions/cbrt.js b/packages/kbn-tinymath/src/functions/cbrt.js index 1c5f75a724b5e..39ea7ffb33c1e 100644 --- a/packages/kbn-tinymath/src/functions/cbrt.js +++ b/packages/kbn-tinymath/src/functions/cbrt.js @@ -17,11 +17,11 @@ * cbrt([27, 64, 125]) // returns [3, 4, 5] */ -module.exports = { cbrt }; - function cbrt(a) { if (Array.isArray(a)) { return a.map((a) => Math.cbrt(a)); } return Math.cbrt(a); } + +module.exports = { cbrt }; diff --git a/packages/kbn-tinymath/src/functions/ceil.js b/packages/kbn-tinymath/src/functions/ceil.js index fe1ca21e4aed1..3dbfbcabaa224 100644 --- a/packages/kbn-tinymath/src/functions/ceil.js +++ b/packages/kbn-tinymath/src/functions/ceil.js @@ -17,11 +17,11 @@ * ceil([1.1, 2.2, 3.3]) // returns [2, 3, 4] */ -module.exports = { ceil }; - function ceil(a) { if (Array.isArray(a)) { return a.map((a) => Math.ceil(a)); } return Math.ceil(a); } + +module.exports = { ceil }; diff --git a/packages/kbn-tinymath/src/functions/clamp.js b/packages/kbn-tinymath/src/functions/clamp.js index 29c190aa8f921..a8563895abec1 100644 --- a/packages/kbn-tinymath/src/functions/clamp.js +++ b/packages/kbn-tinymath/src/functions/clamp.js @@ -30,8 +30,6 @@ const findClamp = (a, min, max) => { * clamp([1, 9], 3, [4, 5]) // returns [clamp([1, 3, 4]), clamp([9, 3, 5])] = [3, 5] */ -module.exports = { clamp }; - function clamp(a, min, max) { if (max === null) throw new Error("Missing maximum value. You may want to use the 'min' function instead"); @@ -73,3 +71,5 @@ function clamp(a, min, max) { return findClamp(a, min, max); } + +module.exports = { clamp }; diff --git a/packages/kbn-tinymath/src/functions/comparison/eq.js b/packages/kbn-tinymath/src/functions/comparison/eq.js new file mode 100644 index 0000000000000..dc1e7f027c44f --- /dev/null +++ b/packages/kbn-tinymath/src/functions/comparison/eq.js @@ -0,0 +1,39 @@ +/* + * 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. + */ + +/** + * Performs an equality comparison between two values. + * @param {number|number[]} a a number or an array of numbers + * @param {number|number[]} b a number or an array of numbers + * @return {boolean} Returns true if `a` and `b` are equal, false otherwise. Returns an array with the equality comparison of each element if `a` is an array. + * @throws `'Missing b value'` if `b` is not provided + * @throws `'Array length mismatch'` if `args` contains arrays of different lengths + * @example + * eq(1, 1) // returns true + * eq(1, 2) // returns false + * eq([1, 2], 1) // returns [true, false] + * eq([1, 2], [1, 2]) // returns [true, true] + */ + +function eq(a, b) { + if (b == null) { + throw new Error('Missing b value'); + } + if (Array.isArray(a)) { + if (!Array.isArray(b)) { + return a.every((v) => v === b); + } + if (a.length !== b.length) { + throw new Error('Array length mismatch'); + } + return a.every((v, i) => v === b[i]); + } + + return a === b; +} +module.exports = { eq }; diff --git a/packages/kbn-tinymath/src/functions/comparison/gt.js b/packages/kbn-tinymath/src/functions/comparison/gt.js new file mode 100644 index 0000000000000..1fc1a0cac083a --- /dev/null +++ b/packages/kbn-tinymath/src/functions/comparison/gt.js @@ -0,0 +1,39 @@ +/* + * 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. + */ + +/** + * Performs a greater than comparison between two values. + * @param {number|number[]} a a number or an array of numbers + * @param {number|number[]} b a number or an array of numbers + * @return {boolean} Returns true if `a` is greater than `b`, false otherwise. Returns an array with the greater than comparison of each element if `a` is an array. + * @throws `'Missing b value'` if `b` is not provided + * @throws `'Array length mismatch'` if `args` contains arrays of different lengths + * @example + * gt(1, 1) // returns false + * gt(2, 1) // returns true + * gt([1, 2], 1) // returns [true, false] + * gt([1, 2], [2, 1]) // returns [false, true] + */ + +function gt(a, b) { + if (b == null) { + throw new Error('Missing b value'); + } + if (Array.isArray(a)) { + if (!Array.isArray(b)) { + return a.every((v) => v > b); + } + if (a.length !== b.length) { + throw new Error('Array length mismatch'); + } + return a.every((v, i) => v > b[i]); + } + + return a > b; +} +module.exports = { gt }; diff --git a/packages/kbn-tinymath/src/functions/comparison/gte.js b/packages/kbn-tinymath/src/functions/comparison/gte.js new file mode 100644 index 0000000000000..2d70145e90f9e --- /dev/null +++ b/packages/kbn-tinymath/src/functions/comparison/gte.js @@ -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. + */ + +const { eq } = require('./eq'); +const { gt } = require('./gt'); + +/** + * Performs a greater than or equal comparison between two values. + * @param {number|number[]} a a number or an array of numbers + * @param {number|number[]} b a number or an array of numbers + * @return {boolean} Returns true if `a` is greater than or equal to `b`, false otherwise. Returns an array with the greater than or equal comparison of each element if `a` is an array. + * @throws `'Array length mismatch'` if `args` contains arrays of different lengths + * @example + * gte(1, 1) // returns true + * gte(1, 2) // returns false + * gte([1, 2], 2) // returns [false, true] + * gte([1, 2], [1, 1]) // returns [true, true] + */ + +function gte(a, b) { + return eq(a, b) || gt(a, b); +} +module.exports = { gte }; diff --git a/packages/kbn-tinymath/src/functions/comparison/ifelse.js b/packages/kbn-tinymath/src/functions/comparison/ifelse.js new file mode 100644 index 0000000000000..7f9c212d6029d --- /dev/null +++ b/packages/kbn-tinymath/src/functions/comparison/ifelse.js @@ -0,0 +1,38 @@ +/* + * 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. + */ + +/** + * Evaluates the a conditional argument and returns one of the two values based on that. + * @param {(boolean)} cond a boolean value + * @param {(any|any[])} a a value or an array of any values + * @param {(any|any[])} b a value or an array of any values + * @return {(any|any[])} if the value of cond is truthy, return `a`, otherwise return `b`. + * @throws `'Condition clause is of the wrong type'` if the `cond` provided is not of boolean type + * @throws `'Missing a value'` if `a` is not provided + * @throws `'Missing b value'` if `b` is not provided + * @example + * ifelse(5 > 6, 1, 0) // returns 0 + * ifelse(1 == 1, [1, 2, 3], 5) // returns [1, 2, 3] + * ifelse(1 < 2, [1, 2, 3], [2, 3, 4]) // returns [1, 2, 3] + */ + +function ifelse(cond, a, b) { + if (typeof cond !== 'boolean') { + throw Error('Condition clause is of the wrong type'); + } + if (a == null) { + throw new Error('Missing a value'); + } + if (b == null) { + throw new Error('Missing b value'); + } + return cond ? a : b; +} + +ifelse.skipNumberValidation = true; +module.exports = { ifelse }; diff --git a/packages/kbn-tinymath/src/functions/comparison/index.js b/packages/kbn-tinymath/src/functions/comparison/index.js new file mode 100644 index 0000000000000..b20cc39014a51 --- /dev/null +++ b/packages/kbn-tinymath/src/functions/comparison/index.js @@ -0,0 +1,16 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 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. + */ + +const { eq } = require('./eq'); +const { lt } = require('./lt'); +const { gt } = require('./gt'); +const { lte } = require('./lte'); +const { gte } = require('./gte'); +const { ifelse } = require('./ifelse'); + +module.exports = { eq, lt, gt, lte, gte, ifelse }; diff --git a/packages/kbn-tinymath/src/functions/comparison/lt.js b/packages/kbn-tinymath/src/functions/comparison/lt.js new file mode 100644 index 0000000000000..fb7a444d1af7a --- /dev/null +++ b/packages/kbn-tinymath/src/functions/comparison/lt.js @@ -0,0 +1,39 @@ +/* + * 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. + */ + +/** + * Performs a lower than comparison between two values. + * @param {number|number[]} a a number or an array of numbers + * @param {number|number[]} b a number or an array of numbers + * @return {boolean} Returns true if `a` is lower than `b`, false otherwise. Returns an array with the lower than comparison of each element if `a` is an array. + * @throws `'Missing b value'` if `b` is not provided + * @throws `'Array length mismatch'` if `args` contains arrays of different lengths + * @example + * lt(1, 1) // returns false + * lt(1, 2) // returns true + * lt([1, 2], 2) // returns [true, false] + * lt([1, 2], [1, 2]) // returns [false, false] + */ + +function lt(a, b) { + if (b == null) { + throw new Error('Missing b value'); + } + if (Array.isArray(a)) { + if (!Array.isArray(b)) { + return a.every((v) => v < b); + } + if (a.length !== b.length) { + throw new Error('Array length mismatch'); + } + return a.every((v, i) => v < b[i]); + } + + return a < b; +} +module.exports = { lt }; diff --git a/packages/kbn-tinymath/src/functions/comparison/lte.js b/packages/kbn-tinymath/src/functions/comparison/lte.js new file mode 100644 index 0000000000000..36aceb11f3bd7 --- /dev/null +++ b/packages/kbn-tinymath/src/functions/comparison/lte.js @@ -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. + */ + +const { eq } = require('./eq'); +const { lt } = require('./lt'); + +/** + * Performs a lower than or equal comparison between two values. + * @param {number|number[]} a a number or an array of numbers + * @param {number|number[]} b a number or an array of numbers + * @return {boolean} Returns true if `a` is lower than or equal to `b`, false otherwise. Returns an array with the lower than or equal comparison of each element if `a` is an array. + * @throws `'Array length mismatch'` if `args` contains arrays of different lengths + * @example + * lte(1, 1) // returns true + * lte(1, 2) // returns true + * lte([1, 2], 2) // returns [true, true] + * lte([1, 2], [1, 1]) // returns [true, false] + */ + +function lte(a, b) { + return eq(a, b) || lt(a, b); +} +module.exports = { lte }; diff --git a/packages/kbn-tinymath/src/functions/cos.js b/packages/kbn-tinymath/src/functions/cos.js index 590cc2aee06b9..590f2bf5bd5e0 100644 --- a/packages/kbn-tinymath/src/functions/cos.js +++ b/packages/kbn-tinymath/src/functions/cos.js @@ -16,11 +16,10 @@ * cos([0, 1.5707963267948966]) // returns [1, 6.123233995736766e-17] */ -module.exports = { cos }; - function cos(a) { if (Array.isArray(a)) { return a.map((a) => Math.cos(a)); } return Math.cos(a); } +module.exports = { cos }; diff --git a/packages/kbn-tinymath/src/functions/count.js b/packages/kbn-tinymath/src/functions/count.js index aa01e1c25835a..ecddb623180f2 100644 --- a/packages/kbn-tinymath/src/functions/count.js +++ b/packages/kbn-tinymath/src/functions/count.js @@ -19,10 +19,10 @@ const { size } = require('./size'); * count(100) // returns 1 */ -module.exports = { count }; - function count(a) { return size(a); } count.skipNumberValidation = true; + +module.exports = { count }; diff --git a/packages/kbn-tinymath/src/functions/cube.js b/packages/kbn-tinymath/src/functions/cube.js index 4d6f8cbea6374..92fe42326f056 100644 --- a/packages/kbn-tinymath/src/functions/cube.js +++ b/packages/kbn-tinymath/src/functions/cube.js @@ -18,8 +18,7 @@ const { pow } = require('./pow'); * cube([3, 4, 5]) // returns [27, 64, 125] */ -module.exports = { cube }; - function cube(a) { return pow(a, 3); } +module.exports = { cube }; diff --git a/packages/kbn-tinymath/src/functions/degtorad.js b/packages/kbn-tinymath/src/functions/degtorad.js index e50365b0beabc..ce6f53ac29c27 100644 --- a/packages/kbn-tinymath/src/functions/degtorad.js +++ b/packages/kbn-tinymath/src/functions/degtorad.js @@ -16,11 +16,10 @@ * degtorad([0, 90, 180, 360]) // returns [0, 1.5707963267948966, 3.141592653589793, 6.283185307179586] */ -module.exports = { degtorad }; - function degtorad(a) { if (Array.isArray(a)) { return a.map((a) => (a * Math.PI) / 180); } return (a * Math.PI) / 180; } +module.exports = { degtorad }; diff --git a/packages/kbn-tinymath/src/functions/divide.js b/packages/kbn-tinymath/src/functions/divide.js index 3f323944c886b..b572217f3ce7d 100644 --- a/packages/kbn-tinymath/src/functions/divide.js +++ b/packages/kbn-tinymath/src/functions/divide.js @@ -20,8 +20,6 @@ * divide([14, 42, 65, 108], [2, 7, 5, 12]) // returns [7, 6, 13, 9] */ -module.exports = { divide }; - function divide(a, b) { if (Array.isArray(a) && Array.isArray(b)) { if (a.length !== b.length) throw new Error('Array length mismatch'); @@ -30,8 +28,14 @@ function divide(a, b) { return val / b[i]; }); } - if (Array.isArray(b)) return b.map((b) => a / b); + if (Array.isArray(b)) { + return b.map((bi) => { + if (bi === 0) throw new Error('Cannot divide by 0'); + return a / bi; + }); + } if (b === 0) throw new Error('Cannot divide by 0'); if (Array.isArray(a)) return a.map((a) => a / b); return a / b; } +module.exports = { divide }; diff --git a/packages/kbn-tinymath/src/functions/exp.js b/packages/kbn-tinymath/src/functions/exp.js index 79669b9dccedd..cf89785e507c1 100644 --- a/packages/kbn-tinymath/src/functions/exp.js +++ b/packages/kbn-tinymath/src/functions/exp.js @@ -16,11 +16,10 @@ * exp([1, 2, 3]) // returns [e^1, e^2, e^3] = [2.718281828459045, 7.3890560989306495, 20.085536923187668] */ -module.exports = { exp }; - function exp(a) { if (Array.isArray(a)) { return a.map((a) => Math.exp(a)); } return Math.exp(a); } +module.exports = { exp }; diff --git a/packages/kbn-tinymath/src/functions/first.js b/packages/kbn-tinymath/src/functions/first.js index 894cb38e69f47..d7970ac0abb71 100644 --- a/packages/kbn-tinymath/src/functions/first.js +++ b/packages/kbn-tinymath/src/functions/first.js @@ -16,8 +16,6 @@ * first([1, 2, 3]) // returns 1 */ -module.exports = { first }; - function first(a) { if (Array.isArray(a)) { return a[0]; @@ -26,3 +24,5 @@ function first(a) { } first.skipNumberValidation = true; + +module.exports = { first }; diff --git a/packages/kbn-tinymath/src/functions/fix.js b/packages/kbn-tinymath/src/functions/fix.js index 1d297327fd47b..3088a949add77 100644 --- a/packages/kbn-tinymath/src/functions/fix.js +++ b/packages/kbn-tinymath/src/functions/fix.js @@ -24,11 +24,11 @@ const fixer = (a) => { * fix([1.8, 2.9, -3.7, -4.6]) // returns [1, 2, -3, -4] */ -module.exports = { fix }; - function fix(a) { if (Array.isArray(a)) { return a.map((a) => fixer(a)); } return fixer(a); } + +module.exports = { fix }; diff --git a/packages/kbn-tinymath/src/functions/floor.js b/packages/kbn-tinymath/src/functions/floor.js index 5d27228d7cdf9..e13f64dc665ae 100644 --- a/packages/kbn-tinymath/src/functions/floor.js +++ b/packages/kbn-tinymath/src/functions/floor.js @@ -17,11 +17,11 @@ * floor([1.7, 2.8, 3.9]) // returns [1, 2, 3] */ -module.exports = { floor }; - function floor(a) { if (Array.isArray(a)) { return a.map((a) => Math.floor(a)); } return Math.floor(a); } + +module.exports = { floor }; diff --git a/packages/kbn-tinymath/src/functions/index.js b/packages/kbn-tinymath/src/functions/index.js index 37c2a13c41cf4..8f0740cb08571 100644 --- a/packages/kbn-tinymath/src/functions/index.js +++ b/packages/kbn-tinymath/src/functions/index.js @@ -45,6 +45,7 @@ const { subtract } = require('./subtract'); const { sum } = require('./sum'); const { tan } = require('./tan'); const { unique } = require('./unique'); +const { eq, lt, gt, lte, gte, ifelse } = require('./comparison'); module.exports = { functions: { @@ -63,6 +64,7 @@ module.exports = { first, fix, floor, + ifelse, last, log, log10, @@ -87,5 +89,10 @@ module.exports = { sum, tan, unique, + eq, + lt, + gt, + lte, + gte, }, }; diff --git a/packages/kbn-tinymath/src/functions/last.js b/packages/kbn-tinymath/src/functions/last.js index 63ba3bd1cfc35..7cdd5fe9cdde6 100644 --- a/packages/kbn-tinymath/src/functions/last.js +++ b/packages/kbn-tinymath/src/functions/last.js @@ -16,8 +16,6 @@ * last([1, 2, 3]) // returns 3 */ -module.exports = { last }; - function last(a) { if (Array.isArray(a)) { return a[a.length - 1]; @@ -26,3 +24,4 @@ function last(a) { } last.skipNumberValidation = true; +module.exports = { last }; diff --git a/packages/kbn-tinymath/src/functions/lib/transpose.js b/packages/kbn-tinymath/src/functions/lib/transpose.js index 9637971cec7cf..9e4d673fdf57a 100644 --- a/packages/kbn-tinymath/src/functions/lib/transpose.js +++ b/packages/kbn-tinymath/src/functions/lib/transpose.js @@ -8,6 +8,7 @@ /** * Transposes a 2D array, i.e. turns the rows into columns and vice versa. Scalar values are also included in the transpose. + * @private * @param {any[][]} args an array or an array that contains arrays * @param {number} index index of the first array element in args * @return {any[][]} transpose of args diff --git a/packages/kbn-tinymath/src/functions/log.js b/packages/kbn-tinymath/src/functions/log.js index 083c9cdef2dc0..06043eca5384c 100644 --- a/packages/kbn-tinymath/src/functions/log.js +++ b/packages/kbn-tinymath/src/functions/log.js @@ -22,8 +22,6 @@ const changeOfBase = (a, b) => Math.log(a) / Math.log(b); * log([2, 4, 8, 16, 32], 2) // returns [1, 2, 3, 4, 5] */ -module.exports = { log }; - function log(a, b = Math.E) { if (b <= 0) throw new Error('Base out of range'); @@ -36,3 +34,4 @@ function log(a, b = Math.E) { if (a < 0) throw new Error('Must be greater than 0'); return changeOfBase(a, b); } +module.exports = { log }; diff --git a/packages/kbn-tinymath/src/functions/log10.js b/packages/kbn-tinymath/src/functions/log10.js index 68c2ffb2bbd30..09f7182e70375 100644 --- a/packages/kbn-tinymath/src/functions/log10.js +++ b/packages/kbn-tinymath/src/functions/log10.js @@ -20,8 +20,7 @@ const { log } = require('./log'); * log([10, 100, 1000, 10000, 100000]) // returns [1, 2, 3, 4, 5] */ -module.exports = { log10 }; - function log10(a) { return log(a, 10); } +module.exports = { log10 }; diff --git a/packages/kbn-tinymath/src/functions/max.js b/packages/kbn-tinymath/src/functions/max.js index 4b6bb2bd27d5e..46e6fec0f6989 100644 --- a/packages/kbn-tinymath/src/functions/max.js +++ b/packages/kbn-tinymath/src/functions/max.js @@ -17,8 +17,6 @@ * max([1, 9], 4, [3, 5]) // returns [max([1, 4, 3]), max([9, 4, 5])] = [4, 9] */ -module.exports = { max }; - function max(...args) { if (args.length === 1) { if (Array.isArray(args[0])) @@ -36,3 +34,4 @@ function max(...args) { return Math.max(result, current); }); } +module.exports = { max }; diff --git a/packages/kbn-tinymath/src/functions/mean.js b/packages/kbn-tinymath/src/functions/mean.js index 441b90cff2ac3..995c54b3b1ea0 100644 --- a/packages/kbn-tinymath/src/functions/mean.js +++ b/packages/kbn-tinymath/src/functions/mean.js @@ -19,8 +19,6 @@ const { add } = require('./add'); * mean([1, 9], 5, [3, 4]) // returns [mean([1, 5, 3]), mean([9, 5, 4])] = [3, 6] */ -module.exports = { mean }; - function mean(...args) { if (args.length === 1) { if (Array.isArray(args[0])) return add(args[0]) / args[0].length; @@ -34,3 +32,4 @@ function mean(...args) { return sum / args.length; } +module.exports = { mean }; diff --git a/packages/kbn-tinymath/src/functions/median.js b/packages/kbn-tinymath/src/functions/median.js index 7c47158a81dda..facac3d367750 100644 --- a/packages/kbn-tinymath/src/functions/median.js +++ b/packages/kbn-tinymath/src/functions/median.js @@ -33,8 +33,6 @@ const findMedian = (a) => { * median([1, 9], 2, 4, [3, 5]) // returns [median([1, 2, 4, 3]), median([9, 2, 4, 5])] = [2.5, 4.5] */ -module.exports = { median }; - function median(...args) { if (args.length === 1) { if (Array.isArray(args[0])) return findMedian(args[0]); @@ -48,3 +46,4 @@ function median(...args) { } return findMedian(args); } +module.exports = { median }; diff --git a/packages/kbn-tinymath/src/functions/min.js b/packages/kbn-tinymath/src/functions/min.js index 356ccecc4b6f2..8f9ecd7c25c28 100644 --- a/packages/kbn-tinymath/src/functions/min.js +++ b/packages/kbn-tinymath/src/functions/min.js @@ -17,8 +17,6 @@ * min([1, 9], 4, [3, 5]) // returns [min([1, 4, 3]), min([9, 4, 5])] = [1, 4] */ -module.exports = { min }; - function min(...args) { if (args.length === 1) { if (Array.isArray(args[0])) @@ -36,3 +34,4 @@ function min(...args) { return Math.min(result, current); }); } +module.exports = { min }; diff --git a/packages/kbn-tinymath/src/functions/mod.js b/packages/kbn-tinymath/src/functions/mod.js index 7f6a4fffca829..bb945772f41c9 100644 --- a/packages/kbn-tinymath/src/functions/mod.js +++ b/packages/kbn-tinymath/src/functions/mod.js @@ -20,8 +20,6 @@ * mod([14, 42, 65, 108], [5, 4, 14, 2]) // returns [5, 2, 9, 0] */ -module.exports = { mod }; - function mod(a, b) { if (Array.isArray(a) && Array.isArray(b)) { if (a.length !== b.length) throw new Error('Array length mismatch'); @@ -35,3 +33,4 @@ function mod(a, b) { if (Array.isArray(a)) return a.map((a) => a % b); return a % b; } +module.exports = { mod }; diff --git a/packages/kbn-tinymath/src/functions/mode.js b/packages/kbn-tinymath/src/functions/mode.js index 0836c1c939f44..99f0086de0a78 100644 --- a/packages/kbn-tinymath/src/functions/mode.js +++ b/packages/kbn-tinymath/src/functions/mode.js @@ -40,8 +40,6 @@ const findMode = (a) => { * mode([1, 9], 1, 4, [3, 5]) // returns [mode([1, 1, 4, 3]), mode([9, 1, 4, 5])] = [[1], [4, 5, 9]] */ -module.exports = { mode }; - function mode(...args) { if (args.length === 1) { if (Array.isArray(args[0])) return findMode(args[0]); @@ -55,3 +53,4 @@ function mode(...args) { } return findMode(args); } +module.exports = { mode }; diff --git a/packages/kbn-tinymath/src/functions/multiply.js b/packages/kbn-tinymath/src/functions/multiply.js index d7c9c75ee3647..d9d6c751bdaf7 100644 --- a/packages/kbn-tinymath/src/functions/multiply.js +++ b/packages/kbn-tinymath/src/functions/multiply.js @@ -19,8 +19,6 @@ * multiply([1, 2, 3, 4], [2, 7, 5, 12]) // returns [2, 14, 15, 48] */ -module.exports = { multiply }; - function multiply(...args) { return args.reduce((result, current) => { if (Array.isArray(result) && Array.isArray(current)) { @@ -32,3 +30,4 @@ function multiply(...args) { return result * current; }); } +module.exports = { multiply }; diff --git a/packages/kbn-tinymath/src/functions/pi.js b/packages/kbn-tinymath/src/functions/pi.js index 9f0b74292524c..dacb0ea5ea4ed 100644 --- a/packages/kbn-tinymath/src/functions/pi.js +++ b/packages/kbn-tinymath/src/functions/pi.js @@ -14,8 +14,7 @@ * pi() // 3.141592653589793 */ -module.exports = { pi }; - function pi() { return Math.PI; } +module.exports = { pi }; diff --git a/packages/kbn-tinymath/src/functions/pow.js b/packages/kbn-tinymath/src/functions/pow.js index 2c600cb7f47aa..e2be268d3c623 100644 --- a/packages/kbn-tinymath/src/functions/pow.js +++ b/packages/kbn-tinymath/src/functions/pow.js @@ -17,8 +17,6 @@ * pow([1, 2, 3], 4) // returns [1, 16, 81] */ -module.exports = { pow }; - function pow(a, b) { if (b == null) throw new Error('Missing exponent'); if (Array.isArray(a)) { @@ -26,3 +24,4 @@ function pow(a, b) { } return Math.pow(a, b); } +module.exports = { pow }; diff --git a/packages/kbn-tinymath/src/functions/radtodeg.js b/packages/kbn-tinymath/src/functions/radtodeg.js index 6cfd40841ba55..733147334a637 100644 --- a/packages/kbn-tinymath/src/functions/radtodeg.js +++ b/packages/kbn-tinymath/src/functions/radtodeg.js @@ -16,11 +16,10 @@ * radtodeg([0, 1.5707963267948966, 3.141592653589793, 6.283185307179586]) // returns [0, 90, 180, 360] */ -module.exports = { radtodeg }; - function radtodeg(a) { if (Array.isArray(a)) { return a.map((a) => (a * 180) / Math.PI); } return (a * 180) / Math.PI; } +module.exports = { radtodeg }; diff --git a/packages/kbn-tinymath/src/functions/random.js b/packages/kbn-tinymath/src/functions/random.js index 799f6515d4ca5..be2dd2c773322 100644 --- a/packages/kbn-tinymath/src/functions/random.js +++ b/packages/kbn-tinymath/src/functions/random.js @@ -18,8 +18,6 @@ * random(-10,10) // returns a random number between -10 (inclusive) and 10 (exclusive) */ -module.exports = { random }; - function random(a, b) { if (a == null) return Math.random(); @@ -33,3 +31,5 @@ function random(a, b) { if (a > b) throw new Error(`Min is greater than max`); return Math.random() * (b - a) + a; } + +module.exports = { random }; diff --git a/packages/kbn-tinymath/src/functions/range.js b/packages/kbn-tinymath/src/functions/range.js index 571b179b75b65..0b2a05dfb8ae4 100644 --- a/packages/kbn-tinymath/src/functions/range.js +++ b/packages/kbn-tinymath/src/functions/range.js @@ -21,8 +21,7 @@ const { subtract } = require('./subtract'); * range([1, 9], 4, [3, 5]) // returns [range([1, 4, 3]), range([9, 4, 5])] = [3, 5] */ -module.exports = { range }; - function range(...args) { return subtract(max(...args), min(...args)); } +module.exports = { range }; diff --git a/packages/kbn-tinymath/src/functions/round.js b/packages/kbn-tinymath/src/functions/round.js index 9befb64ca5d45..88d45fda42b5f 100644 --- a/packages/kbn-tinymath/src/functions/round.js +++ b/packages/kbn-tinymath/src/functions/round.js @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -const rounder = (a, b) => Math.round(a * Math.pow(10, b)) / Math.pow(10, b); +const rounder = (a, b = 0) => Math.round(a * Math.pow(10, b)) / Math.pow(10, b); /** * Rounds a number towards the nearest integer by default or decimal place if specified. For arrays, the function will be applied index-wise to each element. @@ -22,11 +22,10 @@ const rounder = (a, b) => Math.round(a * Math.pow(10, b)) / Math.pow(10, b); * round([2.9234, 5.1234, 3.5234, 4.49234324], 2) // returns [2.92, 5.12, 3.52, 4.49] */ -module.exports = { round }; - -function round(a, b = 0) { +function round(a, b) { if (Array.isArray(a)) { return a.map((a) => rounder(a, b)); } return rounder(a, b); } +module.exports = { round }; diff --git a/packages/kbn-tinymath/src/functions/sin.js b/packages/kbn-tinymath/src/functions/sin.js index 591c799ff3ebe..6a2801623283e 100644 --- a/packages/kbn-tinymath/src/functions/sin.js +++ b/packages/kbn-tinymath/src/functions/sin.js @@ -16,11 +16,10 @@ * sin([0, 1.5707963267948966]) // returns [0, 1] */ -module.exports = { sin }; - function sin(a) { if (Array.isArray(a)) { return a.map((a) => Math.sin(a)); } return Math.sin(a); } +module.exports = { sin }; diff --git a/packages/kbn-tinymath/src/functions/size.js b/packages/kbn-tinymath/src/functions/size.js index fb16bcb905f96..f862ee33ed92a 100644 --- a/packages/kbn-tinymath/src/functions/size.js +++ b/packages/kbn-tinymath/src/functions/size.js @@ -17,11 +17,10 @@ * size(100) // returns 1 */ -module.exports = { size }; - function size(a) { if (Array.isArray(a)) return a.length; throw new Error('Must pass an array'); } size.skipNumberValidation = true; +module.exports = { size }; diff --git a/packages/kbn-tinymath/src/functions/sqrt.js b/packages/kbn-tinymath/src/functions/sqrt.js index 19aeaab964d03..fa666d6a4b0ba 100644 --- a/packages/kbn-tinymath/src/functions/sqrt.js +++ b/packages/kbn-tinymath/src/functions/sqrt.js @@ -17,8 +17,6 @@ * sqrt([9, 16, 25]) // returns [3, 4, 5] */ -module.exports = { sqrt }; - function sqrt(a) { if (Array.isArray(a)) { return a.map((a) => { @@ -30,3 +28,4 @@ function sqrt(a) { if (a < 0) throw new Error('Unable find the square root of a negative number'); return Math.sqrt(a); } +module.exports = { sqrt }; diff --git a/packages/kbn-tinymath/src/functions/square.js b/packages/kbn-tinymath/src/functions/square.js index 5c285eaee3209..58acd1c7f5e33 100644 --- a/packages/kbn-tinymath/src/functions/square.js +++ b/packages/kbn-tinymath/src/functions/square.js @@ -18,8 +18,7 @@ const { pow } = require('./pow'); * square([3, 4, 5]) // returns [9, 16, 25] */ -module.exports = { square }; - function square(a) { return pow(a, 2); } +module.exports = { square }; diff --git a/packages/kbn-tinymath/src/functions/subtract.js b/packages/kbn-tinymath/src/functions/subtract.js index becc267ca51bb..fe2b5ae754456 100644 --- a/packages/kbn-tinymath/src/functions/subtract.js +++ b/packages/kbn-tinymath/src/functions/subtract.js @@ -19,8 +19,6 @@ * subtract([14, 42, 65, 108], [2, 7, 5, 12]) // returns [12, 35, 52, 96] */ -module.exports = { subtract }; - function subtract(a, b) { if (Array.isArray(a) && Array.isArray(b)) { if (a.length !== b.length) throw new Error('Array length mismatch'); @@ -30,3 +28,4 @@ function subtract(a, b) { if (Array.isArray(b)) return b.map((b) => a - b); return a - b; } +module.exports = { subtract }; diff --git a/packages/kbn-tinymath/src/functions/sum.js b/packages/kbn-tinymath/src/functions/sum.js index d9a8f4e531010..fb5bca8abde00 100644 --- a/packages/kbn-tinymath/src/functions/sum.js +++ b/packages/kbn-tinymath/src/functions/sum.js @@ -20,8 +20,6 @@ const findSum = (total, current) => total + current; * sum([10, 20, 30, 40], 10, [1, 2, 3], 22) // returns sum(10, 20, 30, 40, 10, 1, 2, 3, 22) = 138 */ -module.exports = { sum }; - function sum(...args) { return args.reduce((total, current) => { if (Array.isArray(current)) { @@ -30,3 +28,4 @@ function sum(...args) { return total + current; }, 0); } +module.exports = { sum }; diff --git a/packages/kbn-tinymath/src/functions/tan.js b/packages/kbn-tinymath/src/functions/tan.js index 7f045acce0f38..4c980ee3fd272 100644 --- a/packages/kbn-tinymath/src/functions/tan.js +++ b/packages/kbn-tinymath/src/functions/tan.js @@ -16,11 +16,10 @@ * tan([0, 1, -1]) // returns [0, 1.5574077246549023, -1.5574077246549023] */ -module.exports = { tan }; - function tan(a) { if (Array.isArray(a)) { return a.map((a) => Math.tan(a)); } return Math.tan(a); } +module.exports = { tan }; diff --git a/packages/kbn-tinymath/src/functions/unique.js b/packages/kbn-tinymath/src/functions/unique.js index 5220b4ad79adf..77153c036822d 100644 --- a/packages/kbn-tinymath/src/functions/unique.js +++ b/packages/kbn-tinymath/src/functions/unique.js @@ -18,8 +18,6 @@ * unique([1, 2, 3, 4, 2, 2, 2, 3, 4, 2, 4, 5, 2, 1, 4, 2]) // returns 5 */ -module.exports = { unique }; - function unique(a) { if (Array.isArray(a)) { return a.filter((val, i) => a.indexOf(val) === i).length; @@ -28,3 +26,4 @@ function unique(a) { } unique.skipNumberValidation = true; +module.exports = { unique }; diff --git a/packages/kbn-tinymath/test/functions/comparison/eq.test.js b/packages/kbn-tinymath/test/functions/comparison/eq.test.js new file mode 100644 index 0000000000000..eb84479a3708a --- /dev/null +++ b/packages/kbn-tinymath/test/functions/comparison/eq.test.js @@ -0,0 +1,42 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 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. + */ + +const { eq } = require('../../../src/functions/comparison/eq'); + +describe('Eq', () => { + it('numbers', () => { + expect(eq(-10, -10)).toBeTruthy(); + expect(eq(10, 10)).toBeTruthy(); + expect(eq(0, 0)).toBeTruthy(); + }); + + it('arrays', () => { + // Should pass + expect(eq([-1], -1)).toBeTruthy(); + expect(eq([-1], [-1])).toBeTruthy(); + expect(eq([-1, -1], -1)).toBeTruthy(); + expect(eq([-1, -1], [-1, -1])).toBeTruthy(); + + // Should not pass + expect(eq([-1], 0)).toBeFalsy(); + expect(eq([-1], [0])).toBeFalsy(); + expect(eq([-1, -1], 0)).toBeFalsy(); + expect(eq([-1, -1], [0, 0])).toBeFalsy(); + expect(eq([-1, -1], [-1, 0])).toBeFalsy(); + }); + + it('missing args', () => { + expect(() => eq()).toThrow(); + expect(() => eq(-10)).toThrow(); + expect(() => eq([])).toThrow(); + }); + + it('empty arrays', () => { + expect(eq([], [])).toBeTruthy(); + }); +}); diff --git a/packages/kbn-tinymath/test/functions/comparison/gt.test.js b/packages/kbn-tinymath/test/functions/comparison/gt.test.js new file mode 100644 index 0000000000000..a6a7173d35043 --- /dev/null +++ b/packages/kbn-tinymath/test/functions/comparison/gt.test.js @@ -0,0 +1,42 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 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. + */ + +const { gt } = require('../../../src/functions/comparison/gt'); + +describe('Gt', () => { + it('missing args', () => { + expect(() => gt()).toThrow(); + expect(() => gt(-10)).toThrow(); + expect(() => gt([])).toThrow(); + }); + + it('empty arrays', () => { + expect(gt([], [])).toBeTruthy(); + }); + + it('numbers', () => { + expect(gt(-10, -20)).toBeTruthy(); + expect(gt(10, 0)).toBeTruthy(); + expect(gt(0, -1)).toBeTruthy(); + }); + + it('arrays', () => { + // Should pass + expect(gt([-1], -2)).toBeTruthy(); + expect(gt([-1], [-2])).toBeTruthy(); + expect(gt([-1, -1], -2)).toBeTruthy(); + expect(gt([-1, -1], [-2, -2])).toBeTruthy(); + + // Should not pass + expect(gt([-1], 2)).toBeFalsy(); + expect(gt([-1], [2])).toBeFalsy(); + expect(gt([-1, -1], 2)).toBeFalsy(); + expect(gt([-1, -1], [2, 2])).toBeFalsy(); + expect(gt([-1, -1], [-2, 2])).toBeFalsy(); + }); +}); diff --git a/packages/kbn-tinymath/test/functions/comparison/gte.test.js b/packages/kbn-tinymath/test/functions/comparison/gte.test.js new file mode 100644 index 0000000000000..fde1294a5a0fc --- /dev/null +++ b/packages/kbn-tinymath/test/functions/comparison/gte.test.js @@ -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. + */ + +const { gte } = require('../../../src/functions/comparison/gte'); + +describe('Gte', () => { + it('missing args', () => { + expect(() => gte()).toThrow(); + expect(() => gte(-10)).toThrow(); + expect(() => gte([])).toThrow(); + }); + + it('empty arrays', () => { + expect(gte([], [])).toBeTruthy(); + }); + + describe('eq values', () => { + it('numbers', () => { + expect(gte(-10, -10)).toBeTruthy(); + expect(gte(10, 10)).toBeTruthy(); + expect(gte(0, 0)).toBeTruthy(); + }); + + it('arrays', () => { + expect(gte([-1], -1)).toBeTruthy(); + expect(gte([-1], [-1])).toBeTruthy(); + expect(gte([-1, -1], -1)).toBeTruthy(); + expect(gte([-1, -1], [-1, -1])).toBeTruthy(); + }); + }); + + describe('gt values', () => { + it('numbers', () => { + expect(gte(-10, -20)).toBeTruthy(); + expect(gte(10, 0)).toBeTruthy(); + expect(gte(0, -1)).toBeTruthy(); + }); + + it('arrays', () => { + // Should pass + expect(gte([-1], -2)).toBeTruthy(); + expect(gte([-1], [-2])).toBeTruthy(); + expect(gte([-1, -1], -2)).toBeTruthy(); + expect(gte([-1, -1], [-2, -2])).toBeTruthy(); + + // Should not pass + expect(gte([-1], 2)).toBeFalsy(); + expect(gte([-1], [2])).toBeFalsy(); + expect(gte([-1, -1], 2)).toBeFalsy(); + expect(gte([-1, -1], [2, 2])).toBeFalsy(); + expect(gte([-1, -1], [-2, 2])).toBeFalsy(); + }); + }); +}); diff --git a/packages/kbn-tinymath/test/functions/comparison/ifelse.test.js b/packages/kbn-tinymath/test/functions/comparison/ifelse.test.js new file mode 100644 index 0000000000000..efd098e26292a --- /dev/null +++ b/packages/kbn-tinymath/test/functions/comparison/ifelse.test.js @@ -0,0 +1,33 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 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. + */ + +const { ifelse } = require('../../../src/functions/comparison/ifelse'); + +describe('Ifelse', () => { + it('should basically work', () => { + expect(ifelse(true, 1, 0)).toEqual(1); + expect(ifelse(false, 1, 0)).toEqual(0); + expect(ifelse(1 > 0, 1, 0)).toEqual(1); + expect(ifelse(1 < 0, 1, 0)).toEqual(0); + }); + + it('should throw if cond is not of boolean type', () => { + expect(() => ifelse(5, 1, 0)).toThrow('Condition clause is of the wrong type'); + expect(() => ifelse(null, 1, 0)).toThrow('Condition clause is of the wrong type'); + expect(() => ifelse(undefined, 1, 0)).toThrow('Condition clause is of the wrong type'); + expect(() => ifelse(0, 1, 0)).toThrow('Condition clause is of the wrong type'); + }); + + it('missing args', () => { + expect(() => ifelse()).toThrow(); + expect(() => ifelse(-10)).toThrow(); + expect(() => ifelse([])).toThrow(); + expect(() => ifelse(true)).toThrow(); + expect(() => ifelse(true, 1)).toThrow(); + }); +}); diff --git a/packages/kbn-tinymath/test/functions/comparison/lt.test.js b/packages/kbn-tinymath/test/functions/comparison/lt.test.js new file mode 100644 index 0000000000000..cbd56a4ac674e --- /dev/null +++ b/packages/kbn-tinymath/test/functions/comparison/lt.test.js @@ -0,0 +1,42 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 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. + */ + +const { lt } = require('../../../src/functions/comparison/lt'); + +describe('Lt', () => { + it('missing args', () => { + expect(() => lt()).toThrow(); + expect(() => lt(-10)).toThrow(); + expect(() => lt([])).toThrow(); + }); + + it('empty arrays', () => { + expect(lt([], [])).toBeTruthy(); + }); + + it('numbers', () => { + expect(lt(-10, -2)).toBeTruthy(); + expect(lt(10, 20)).toBeTruthy(); + expect(lt(0, 1)).toBeTruthy(); + }); + + it('arrays', () => { + // Should pass + expect(lt([-1], 0)).toBeTruthy(); + expect(lt([-1], [0])).toBeTruthy(); + expect(lt([-1, -1], 0)).toBeTruthy(); + expect(lt([-1, -1], [0, 0])).toBeTruthy(); + + // Should not pass + expect(lt([-1], -2)).toBeFalsy(); + expect(lt([-1], [-2])).toBeFalsy(); + expect(lt([-1, -1], -2)).toBeFalsy(); + expect(lt([-1, -1], [-2, -2])).toBeFalsy(); + expect(lt([-1, -1], [-2, 2])).toBeFalsy(); + }); +}); diff --git a/packages/kbn-tinymath/test/functions/comparison/lte.test.js b/packages/kbn-tinymath/test/functions/comparison/lte.test.js new file mode 100644 index 0000000000000..5c6f4a4b5eaa7 --- /dev/null +++ b/packages/kbn-tinymath/test/functions/comparison/lte.test.js @@ -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. + */ + +const { lte } = require('../../../src/functions/comparison/lte'); + +describe('Lte', () => { + it('missing args', () => { + expect(() => lte()).toThrow(); + expect(() => lte(-10)).toThrow(); + expect(() => lte([])).toThrow(); + }); + + it('empty arrays', () => { + expect(lte([], [])).toBeTruthy(); + }); + + describe('eq values', () => { + it('numbers', () => { + expect(lte(-10, -10)).toBeTruthy(); + expect(lte(10, 10)).toBeTruthy(); + expect(lte(0, 0)).toBeTruthy(); + }); + + it('arrays', () => { + expect(lte([-1], -1)).toBeTruthy(); + expect(lte([-1], [-1])).toBeTruthy(); + expect(lte([-1, -1], -1)).toBeTruthy(); + expect(lte([-1, -1], [-1, -1])).toBeTruthy(); + }); + }); + + describe('lt values', () => { + it('numbers', () => { + expect(lte(-10, -2)).toBeTruthy(); + expect(lte(10, 20)).toBeTruthy(); + expect(lte(0, 1)).toBeTruthy(); + }); + + it('arrays', () => { + // Should pass + expect(lte([-1], 0)).toBeTruthy(); + expect(lte([-1], [0])).toBeTruthy(); + expect(lte([-1, -1], 0)).toBeTruthy(); + expect(lte([-1, -1], [0, 0])).toBeTruthy(); + + // Should not pass + expect(lte([-1], -2)).toBeFalsy(); + expect(lte([-1], [-2])).toBeFalsy(); + expect(lte([-1, -1], -2)).toBeFalsy(); + expect(lte([-1, -1], [-2, -2])).toBeFalsy(); + expect(lte([-1, -1], [-2, 2])).toBeFalsy(); + }); + }); +}); diff --git a/packages/kbn-tinymath/test/functions/divide.test.js b/packages/kbn-tinymath/test/functions/divide.test.js index 00af7b1430e58..85851e78df8dd 100644 --- a/packages/kbn-tinymath/test/functions/divide.test.js +++ b/packages/kbn-tinymath/test/functions/divide.test.js @@ -29,4 +29,11 @@ describe('Divide', () => { it('array length mismatch', () => { expect(() => divide([1, 2], [3])).toThrow('Array length mismatch'); }); + + it('divide by 0', () => { + expect(() => divide([1, 2], 0)).toThrow('Cannot divide by 0'); + expect(() => divide(1, 0)).toThrow('Cannot divide by 0'); + expect(() => divide([1, 2], [0, 0])).toThrow('Cannot divide by 0'); + expect(() => divide(1, [1, 0])).toThrow('Cannot divide by 0'); + }); }); diff --git a/packages/kbn-tinymath/test/library.test.js b/packages/kbn-tinymath/test/library.test.js index 9d87919c4f1ac..054d78fc60adb 100644 --- a/packages/kbn-tinymath/test/library.test.js +++ b/packages/kbn-tinymath/test/library.test.js @@ -68,6 +68,91 @@ describe('Parser', () => { location: { min: 0, max: 13 }, }); }); + + describe('Comparison', () => { + it('should throw for non valid comparison symbols', () => { + const symbols = ['<>', '><', '===', '>>', '<<']; + for (const symbol of symbols) { + expect(() => parse(`5 ${symbol} 1`)).toThrow(); + } + }); + describe.each` + symbol | fn + ${'<'} | ${'lt'} + ${'>'} | ${'gt'} + ${'=='} | ${'eq'} + ${'>='} | ${'gte'} + ${'<='} | ${'lte'} + `('Symbol "$symbol" ( $fn )', ({ symbol, fn }) => { + it(`should parse comparison symbol: "$symbol"`, () => { + expect(parse(`5 ${symbol} 1`)).toEqual({ + name: fn, + type: 'function', + args: [5, 1], + text: `5 ${symbol} 1`, + location: { min: 0, max: 4 + symbol.length }, + }); + expect(parse(`a ${symbol} b`)).toEqual({ + name: fn, + type: 'function', + args: [variableEqual('a'), variableEqual('b')], + text: `a ${symbol} b`, + location: { min: 0, max: 4 + symbol.length }, + }); + }); + + it.each` + expression + ${`1 + (1 ${symbol} 1)`} + ${`(1 ${symbol} 1) + 1`} + ${`((1 ${symbol} 1) + 1)`} + ${`((1 ${symbol} 1) + (1 ${symbol} 1))`} + ${`((1 ${symbol} 1) + ( ${symbol} 1))`} + ${` ${symbol} 1`} + ${`1 ${symbol} `} + ${`a + (b ${symbol} c)`} + ${`(a ${symbol} b) + c`} + ${`((a ${symbol} b) + c)`} + ${`((a ${symbol} b) + (c ${symbol} d))`} + ${`((a ${symbol} b) + ( ${symbol} c))`} + ${` ${symbol} a`} + ${`a ${symbol} `} + `( + 'should throw for invalid expression with comparison arguments: $expression', + ({ expression }) => { + expect(() => parse(expression)).toThrow(); + } + ); + + it.each` + expression + ${`1 ${symbol} 1 ${symbol} 1`} + ${`(1 ${symbol} 1) ${symbol} 1`} + ${`1 ${symbol} (1 ${symbol} 1)`} + ${`a ${symbol} b ${symbol} c`} + ${`(a ${symbol} b) ${symbol} c`} + ${`a ${symbol} (b ${symbol} c)`} + `('should throw for cascading comparison operators: $expression', ({ expression }) => { + expect(() => parse(expression)).toThrow(); + }); + + it.each` + expression + ${`1 ${symbol} 1`} + ${`(1 ${symbol} 1)`} + ${`((1 ${symbol} 1))`} + ${`((1 + 1) ${symbol} 1)`} + ${`1 + 1 ${symbol} 1 * 1`} + ${`a ${symbol} b`} + ${`(a ${symbol} b)`} + ${`((a ${symbol} b))`} + ${`((a + b) ${symbol} c)`} + ${`a + b ${symbol} c * d`} + `('should parse comparison expressions: $expression', ({ expression }) => { + expect(() => parse(expression)).not.toThrow(); + }); + }); + }); }); describe('Variables', () => { 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 e7d02da09889d..f6591cf7a7759 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 @@ -62,11 +62,11 @@ describe('checking migration metadata changes on all registered SO types', () => "app_search_telemetry": "7fc4fc08852bf0924ee29942bb394fda9aa8954d", "application_usage_daily": "6e645e0b60ef3af2e8fde80963c2a4f09a190d61", "application_usage_totals": "b2af3577dcd50bfae492b166a7804f69e2cc41dc", - "canvas-element": "5f32b99ba6ff9c1f17cc093591b975be65a27b9b", - "canvas-workpad": "b60252414fb6159a14f9febf98dbe41e5a8bf199", - "canvas-workpad-template": "c371cad0a8d61385f4782cab9a9063d3cf241ee0", + "canvas-element": "c27505dcf2970760bea8a0fe1d000253f0c40f08", + "canvas-workpad": "eb7b28a3b1c24af615edbf29becddf2e750a4bb5", + "canvas-workpad-template": "34454b811e32993eaa55c6ec85a7aecca00c4cfc", "cases": "7ff5ce930146a2d6fc8fbf536ce2ee16e9df296f", - "cases-comments": "8cfbad4ede637305eb6fb79db680f03dc0ce5ec4", + "cases-comments": "d7c4c1d24e97620cd415e27e5eb7d5b5f2c5b461", "cases-configure": "1afc414f5563a36e4612fa269193d3ed7277c7bd", "cases-connector-mappings": "4b16d440af966e5d6e0fa33368bfa15d987a4b69", "cases-telemetry": "16e261e7378a72acd0806f18df92525dd1da4f37", @@ -76,7 +76,7 @@ describe('checking migration metadata changes on all registered SO types', () => "core-usage-stats": "f40a213da2c597b0de94e364a4326a5a1baa4ca9", "csp-rule-template": "3679c5f2431da8153878db79c78a4e695357fb61", "csp_rule": "d2bb53ea5d2bdfba1a835ad8956dfcd2b2c32e19", - "dashboard": "0b0842b6aa40c125d64233fd81cee11080580dc2", + "dashboard": "742f2d9f110709fd8599b14f7766f38efc30de61", "endpoint:user-artifact": "f94c250a52b30d0a2d32635f8b4c5bdabd1e25c0", "endpoint:user-artifact-manifest": "8c14d49a385d5d1307d956aa743ec78de0b2be88", "enterprise_search_telemetry": "fafcc8318528d34f721c42d1270787c52565bad5", @@ -103,7 +103,7 @@ describe('checking migration metadata changes on all registered SO types', () => "inventory-view": "bc2bd1e7ec7c186159447ab228d269f22bd39056", "kql-telemetry": "29544cd7d3b767c5399878efae6bd724d24c03fd", "legacy-url-alias": "7172dfd54f2e0c89fe263fd7095519b2d826a930", - "lens": "08769c789ad6d1b8a4d0cffebc9d9bb08bf01ad9", + "lens": "236ecd358ed3a4ecfc03ed676d958b64acf0b697", "lens-ui-telemetry": "df2844565c9e18fed2bdb1f6cc3aadd58cf1e45b", "map": "00ca6c4cf46ae59f70f1436262eb9f457b45eb14", "maps-telemetry": "5adbde35bd50ec2b8e9ea5b96d4d9f886e31ecfb", 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 9a73f1f295492..e0a9171e52169 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 @@ -41,6 +41,9 @@ kibana_vars=( csp.report_to data.autocomplete.valueSuggestions.terminateAfter data.autocomplete.valueSuggestions.timeout + data.search.asyncSearch.waitForCompletion + data.search.asyncSearch.keepAlive + data.search.asyncSearch.batchedReduceSize data.search.sessions.defaultExpiration data.search.sessions.enabled data.search.sessions.maxUpdateRetries diff --git a/src/plugins/chart_expressions/expression_gauge/common/expression_functions/__snapshots__/gauge_function.test.ts.snap b/src/plugins/chart_expressions/expression_gauge/common/expression_functions/__snapshots__/gauge_function.test.ts.snap index bb2fe700f6f19..3a1f13de9c525 100644 --- a/src/plugins/chart_expressions/expression_gauge/common/expression_functions/__snapshots__/gauge_function.test.ts.snap +++ b/src/plugins/chart_expressions/expression_gauge/common/expression_functions/__snapshots__/gauge_function.test.ts.snap @@ -53,6 +53,7 @@ Object { "shape": "arc", "ticksPosition": "auto", }, + "canNavigateToLens": false, "data": Object { "columns": Array [ Object { @@ -105,6 +106,7 @@ Object { "shape": "arc", "ticksPosition": "auto", }, + "canNavigateToLens": false, "data": Object { "columns": Array [ Object { @@ -155,6 +157,7 @@ Object { "shape": "horizontalBullet", "ticksPosition": "auto", }, + "canNavigateToLens": false, "data": Object { "columns": Array [ Object { @@ -205,6 +208,7 @@ Object { "shape": "horizontalBullet", "ticksPosition": "auto", }, + "canNavigateToLens": false, "data": Object { "columns": Array [ Object { @@ -255,6 +259,7 @@ Object { "shape": "horizontalBullet", "ticksPosition": "bands", }, + "canNavigateToLens": false, "data": Object { "columns": Array [ Object { @@ -307,6 +312,7 @@ Object { "shape": "circle", "ticksPosition": "auto", }, + "canNavigateToLens": false, "data": Object { "columns": Array [ Object { @@ -359,6 +365,7 @@ Object { "shape": "circle", "ticksPosition": "auto", }, + "canNavigateToLens": false, "data": Object { "columns": Array [ Object { @@ -409,6 +416,7 @@ Object { "shape": "horizontalBullet", "ticksPosition": "auto", }, + "canNavigateToLens": false, "data": Object { "columns": Array [ Object { @@ -459,6 +467,7 @@ Object { "shape": "horizontalBullet", "ticksPosition": "hidden", }, + "canNavigateToLens": false, "data": Object { "columns": Array [ Object { @@ -509,6 +518,7 @@ Object { "shape": "horizontalBullet", "ticksPosition": "auto", }, + "canNavigateToLens": false, "data": Object { "columns": Array [ Object { @@ -559,6 +569,7 @@ Object { "shape": "horizontalBullet", "ticksPosition": "auto", }, + "canNavigateToLens": false, "data": Object { "columns": Array [ Object { @@ -609,6 +620,7 @@ Object { "shape": "horizontalBullet", "ticksPosition": "auto", }, + "canNavigateToLens": false, "data": Object { "columns": Array [ Object { @@ -659,6 +671,7 @@ Object { "shape": "horizontalBullet", "ticksPosition": "auto", }, + "canNavigateToLens": false, "data": Object { "columns": Array [ Object { @@ -709,6 +722,7 @@ Object { "shape": "verticalBullet", "ticksPosition": "auto", }, + "canNavigateToLens": false, "data": Object { "columns": Array [ Object { diff --git a/src/plugins/chart_expressions/expression_gauge/common/expression_functions/gauge_function.ts b/src/plugins/chart_expressions/expression_gauge/common/expression_functions/gauge_function.ts index 70ecd25839d19..72919e7c9b414 100644 --- a/src/plugins/chart_expressions/expression_gauge/common/expression_functions/gauge_function.ts +++ b/src/plugins/chart_expressions/expression_gauge/common/expression_functions/gauge_function.ts @@ -231,6 +231,7 @@ export const gaugeFunction = (): GaugeExpressionFunctionDefinition => ({ (handlers.variables?.embeddableTitle as string) ?? handlers.getExecutionContext?.()?.description, }, + canNavigateToLens: Boolean(handlers?.variables?.canNavigateToLens), }, }; }, diff --git a/src/plugins/chart_expressions/expression_gauge/common/types/expression_functions.ts b/src/plugins/chart_expressions/expression_gauge/common/types/expression_functions.ts index ed1098ea96ad8..a7a89a876d699 100644 --- a/src/plugins/chart_expressions/expression_gauge/common/types/expression_functions.ts +++ b/src/plugins/chart_expressions/expression_gauge/common/types/expression_functions.ts @@ -62,6 +62,7 @@ export type GaugeInput = Datatable; export interface GaugeExpressionProps { data: Datatable; args: GaugeArguments; + canNavigateToLens: boolean; } export interface GaugeRender { diff --git a/src/plugins/chart_expressions/expression_gauge/public/components/gauge_component.test.tsx b/src/plugins/chart_expressions/expression_gauge/public/components/gauge_component.test.tsx index 6588cefdb8f2b..640a8e17b47c7 100644 --- a/src/plugins/chart_expressions/expression_gauge/public/components/gauge_component.test.tsx +++ b/src/plugins/chart_expressions/expression_gauge/public/components/gauge_component.test.tsx @@ -94,6 +94,7 @@ describe('GaugeComponent', function () { beforeAll(async () => { wrapperProps = { + canNavigateToLens: false, data: createData(), chartsThemeService, args, diff --git a/src/plugins/chart_expressions/expression_gauge/public/expression_renderers/gauge_renderer.tsx b/src/plugins/chart_expressions/expression_gauge/public/expression_renderers/gauge_renderer.tsx index bdaa7f878fd6e..2a18a3891a3a6 100644 --- a/src/plugins/chart_expressions/expression_gauge/public/expression_renderers/gauge_renderer.tsx +++ b/src/plugins/chart_expressions/expression_gauge/public/expression_renderers/gauge_renderer.tsx @@ -57,9 +57,11 @@ export const gaugeRenderer: ( const visualizationType = extractVisualizationType(executionContext); if (containerType && visualizationType) { - plugins.usageCollection?.reportUiCounter(containerType, METRIC_TYPE.COUNT, [ + const events = [ `render_${visualizationType}_${type}`, - ]); + config.canNavigateToLens ? `render_${visualizationType}_${type}_convertable` : undefined, + ].filter((event): event is string => Boolean(event)); + plugins.usageCollection?.reportUiCounter(containerType, METRIC_TYPE.COUNT, events); } handlers.done(); 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 761b2c3adb156..8e84b2c8e22a8 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", }, + "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 954c5acee7152..76ea0f30ac26b 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 @@ -230,6 +230,7 @@ export const heatmapFunction = (): HeatmapExpressionFunctionDefinition => ({ (handlers.variables?.embeddableTitle as string) ?? handlers.getExecutionContext?.()?.description, }, + syncTooltips: handlers?.isSyncTooltipsEnabled?.() ?? false, }, }; }, 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 50be8b847bd6b..c3db9e34394a3 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 @@ -92,6 +92,7 @@ export type HeatmapInput = Datatable; export interface HeatmapExpressionProps { data: Datatable; args: HeatmapArguments; + syncTooltips: 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 77387f6d55c40..c8763903a3927 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 @@ -7,7 +7,7 @@ */ import type { PaletteRegistry } from '@kbn/coloring'; -import type { ChartsPluginSetup } from '@kbn/charts-plugin/public'; +import type { ChartsPluginSetup, ChartsPluginStart } from '@kbn/charts-plugin/public'; import type { DatatableUtilitiesService } from '@kbn/data-plugin/common'; import type { IFieldFormat, SerializedFieldFormat } from '@kbn/field-formats-plugin/common'; import type { RangeSelectContext, ValueClickContext } from '@kbn/embeddable-plugin/public'; @@ -31,11 +31,13 @@ export type HeatmapRenderProps = HeatmapExpressionProps & { timeZone?: string; formatFactory: FormatFactory; chartsThemeService: ChartsPluginSetup['theme']; + chartsActiveCursorService: ChartsPluginStart['activeCursor']; datatableUtilities: DatatableUtilitiesService; onClickValue: (data: FilterEvent['data']) => void; onSelectRange: (data: BrushEvent['data']) => void; paletteService: PaletteRegistry; uiState: PersistedState; interactive: boolean; + syncTooltips: 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 24718a0700198..fa4b58dd89deb 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 @@ -46,8 +46,9 @@ const actWithTimeout = (action: Function, timer: number = 1) => }, timer) ) ); - +const chartStartContract = chartPluginMock.createStartContract(); const chartsThemeService = chartPluginMock.createSetupContract().theme; +const chartsActiveCursorService = chartStartContract.activeCursor; const palettesRegistry = chartPluginMock.createPaletteRegistry(); const formatService = fieldFormatsServiceMock.createStartContract(); const args: HeatmapArguments = { @@ -114,6 +115,7 @@ describe('HeatmapComponent', function () { wrapperProps = { data, chartsThemeService, + chartsActiveCursorService, args, uiState, onClickValue: jest.fn(), @@ -122,6 +124,7 @@ describe('HeatmapComponent', function () { paletteService: palettesRegistry, formatFactory: formatService.deserialize, interactive: true, + syncTooltips: false, 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 f2db5a25ff429..64d7e4d03a46d 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 @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import React, { memo, FC, useMemo, useState, useCallback } from 'react'; +import React, { memo, FC, useMemo, useState, useCallback, useRef } from 'react'; import { Chart, ElementClickListener, @@ -25,7 +25,7 @@ import { } from '@elastic/charts'; import type { CustomPaletteState } from '@kbn/charts-plugin/public'; import { search } from '@kbn/data-plugin/public'; -import { LegendToggle, EmptyPlaceholder } from '@kbn/charts-plugin/public'; +import { LegendToggle, EmptyPlaceholder, useActiveCursor } from '@kbn/charts-plugin/public'; import { getAccessorByDimension, getFormatByAccessor, @@ -138,14 +138,17 @@ export const HeatmapComponent: FC = memo( timeZone, formatFactory, chartsThemeService, + chartsActiveCursorService, datatableUtilities, onClickValue, onSelectRange, paletteService, uiState, interactive, + syncTooltips, renderComplete, }) => { + const chartRef = useRef(null); const chartTheme = chartsThemeService.useChartsTheme(); const isDarkTheme = chartsThemeService.useDarkMode(); // legacy heatmap legend is handled by the uiState @@ -436,6 +439,9 @@ export const HeatmapComponent: FC = memo( } return `${metricFormatter.convert(value) ?? ''}`; }; + const handleCursorUpdate = useActiveCursor(chartsActiveCursorService, chartRef, { + datatables: [formattedTable.table], + }); const { colors, ranges } = computeColorRanges( paletteService, @@ -564,12 +570,16 @@ export const HeatmapComponent: FC = memo( legendPosition: args.legend.position, }} > - + } + onPointerUpdate={handleCursorUpdate} + externalPointerEvents={{ + tooltip: { visible: syncTooltips }, + }} onElementClick={interactive ? (onElementClick as ElementClickListener) : undefined} showLegend={showLegend ?? args.legend.isVisible} legendPosition={args.legend.position} 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 b0801c89031e2..744d5d49f9376 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 @@ -88,6 +88,8 @@ export const heatmapRenderer: ( renderComplete={renderComplete} uiState={handlers.uiState as PersistedState} interactive={isInteractive()} + chartsActiveCursorService={plugins.charts.activeCursor} + syncTooltips={config.syncTooltips} /> , 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 4664902d13876..3976f6977e2be 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, + 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 8dcc58cda01a8..d6553ef3dd7b3 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 @@ -61,6 +61,7 @@ export const layeredXyVisFn: LayeredXyVisFn['fn'] = async (data, args, handlers) (handlers.variables?.embeddableTitle as string) ?? handlers.getExecutionContext?.()?.description, }, + canNavigateToLens: Boolean(handlers.variables.canNavigateToLens), syncColors: handlers?.isSyncColorsEnabled?.() ?? false, syncTooltips: handlers?.isSyncTooltipsEnabled?.() ?? false, }, 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 67c7ab8d1e294..a09c5f05adb08 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 @@ -38,6 +38,7 @@ describe('xyVis', () => { }, ], }, + canNavigateToLens: false, syncColors: false, syncTooltips: false, }, @@ -346,6 +347,7 @@ describe('xyVis', () => { }, ], }, + canNavigateToLens: false, syncColors: false, syncTooltips: false, }, 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 e29f1e5ffff3c..849f2030a4697 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 @@ -136,6 +136,7 @@ export const xyVisFn: XyVisFn['fn'] = async (data, args, handlers) => { (handlers.variables?.embeddableTitle as string) ?? handlers.getExecutionContext?.()?.description, }, + canNavigateToLens: Boolean(handlers.variables.canNavigateToLens), syncColors: handlers?.isSyncColorsEnabled?.() ?? false, syncTooltips: handlers?.isSyncTooltipsEnabled?.() ?? false, }, 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 de387b4113373..94567f563cdb1 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 @@ -18,6 +18,7 @@ export interface XYChartProps { args: XYProps; syncTooltips: boolean; syncColors: boolean; + canNavigateToLens?: boolean; } export interface XYRender { 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 45eca06c670b0..0d88480b00342 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 @@ -110,7 +110,7 @@ declare global { } } -export type XYChartRenderProps = XYChartProps & { +export type XYChartRenderProps = Omit & { chartsThemeService: ChartsPluginSetup['theme']; chartsActiveCursorService: ChartsPluginStart['activeCursor']; data: DataPublicPluginStart; 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 5606bad9050c7..e00f5b04bd590 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 @@ -52,6 +52,7 @@ interface XyChartRendererDeps { const extractCounterEvents = ( originatingApp: string, { layers, yAxisConfigs }: XYChartProps['args'], + canNavigateToLens: boolean, services: { getDataLayers: typeof getDataLayers; } @@ -149,6 +150,7 @@ const extractCounterEvents = ( (aggregateLayers.length === 1 && dataLayer.splitAccessors?.length) ? 'aggregate_bucket' : undefined, + canNavigateToLens ? `render_${byTypes.mixedXY ? 'mixed_xy' : type}_convertable` : undefined, ] .filter(Boolean) .map((item) => `render_${originatingApp}_${item}`); @@ -188,9 +190,14 @@ export const getXyChartRenderer = ({ const visualizationType = extractVisualizationType(executionContext); if (deps.usageCollection && containerType && visualizationType) { - const uiEvents = extractCounterEvents(visualizationType, config.args, { - getDataLayers, - }); + const uiEvents = extractCounterEvents( + visualizationType, + config.args, + Boolean(config.canNavigateToLens), + { + getDataLayers, + } + ); if (uiEvents) { deps.usageCollection.reportUiCounter(containerType, METRIC_TYPE.COUNT, uiEvents); diff --git a/src/plugins/console/public/application/containers/console_history/console_history.tsx b/src/plugins/console/public/application/containers/console_history/console_history.tsx index dcc19d340ae5d..6918f572ce916 100644 --- a/src/plugins/console/public/application/containers/console_history/console_history.tsx +++ b/src/plugins/console/public/application/containers/console_history/console_history.tsx @@ -188,7 +188,11 @@ export function ConsoleHistory({ close }: Props) { - clear()}> + clear()} + > {i18n.translate('console.historyPage.clearHistoryButtonLabel', { defaultMessage: 'Clear', })} @@ -198,7 +202,11 @@ export function ConsoleHistory({ close }: Props) { - close()}> + close()} + > {i18n.translate('console.historyPage.closehistoryButtonLabel', { defaultMessage: 'Close', })} @@ -207,6 +215,7 @@ export function ConsoleHistory({ close }: Props) { restoreRequestFromHistory(selectedReq.current)} diff --git a/src/plugins/controls/common/options_list/ip_search.test.ts b/src/plugins/controls/common/options_list/ip_search.test.ts new file mode 100644 index 0000000000000..1c935b1875311 --- /dev/null +++ b/src/plugins/controls/common/options_list/ip_search.test.ts @@ -0,0 +1,129 @@ +/* + * 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 { getIpRangeQuery, getIpSegments, getMinMaxIp } from './ip_search'; + +describe('test IP search functionality', () => { + test('get IP segments', () => { + expect(getIpSegments('')).toStrictEqual({ segments: [''], type: 'unknown' }); + expect(getIpSegments('test')).toStrictEqual({ segments: ['test'], type: 'unknown' }); + expect(getIpSegments('123.456')).toStrictEqual({ segments: ['123', '456'], type: 'ipv4' }); + expect(getIpSegments('123..456...')).toStrictEqual({ segments: ['123', '456'], type: 'ipv4' }); + expect(getIpSegments('abc:def:')).toStrictEqual({ segments: ['abc', 'def'], type: 'ipv6' }); + expect(getIpSegments(':::x:::abc:::def:::')).toStrictEqual({ + segments: ['x', 'abc', 'def'], + type: 'ipv6', + }); + }); + + test('get min/max IP', () => { + expect(getMinMaxIp('ipv4', ['123'])).toStrictEqual({ + min: '123.0.0.0', + max: '123.255.255.255', + }); + expect(getMinMaxIp('ipv4', ['123', '456', '789'])).toStrictEqual({ + min: '123.456.789.0', + max: '123.456.789.255', + }); + expect(getMinMaxIp('ipv6', ['abc', 'def'])).toStrictEqual({ + min: 'abc:def::', + max: 'abc:def:ffff:ffff:ffff:ffff:ffff:ffff', + }); + expect(getMinMaxIp('ipv6', ['a', 'b', 'c', 'd', 'e', 'f', 'g'])).toStrictEqual({ + min: 'a:b:c:d:e:f:g::', + max: 'a:b:c:d:e:f:g:ffff', + }); + }); + + test('get IP range query', () => { + // invalid searches + expect(getIpRangeQuery('xyz')).toStrictEqual({ + validSearch: false, + }); + expect(getIpRangeQuery('123.456.OVER 9000')).toStrictEqual({ + validSearch: false, + }); + expect(getIpRangeQuery('abc:def:ghi')).toStrictEqual({ + validSearch: false, + }); + + // full IP searches + expect(getIpRangeQuery('1.2.3.4')).toStrictEqual({ + validSearch: true, + rangeQuery: [ + { + key: 'ipv4', + mask: '1.2.3.4/32', + }, + ], + }); + expect(getIpRangeQuery('1.2.3.256')).toStrictEqual({ + validSearch: false, + rangeQuery: undefined, + }); + expect(getIpRangeQuery('fbbe:a363:9e14:987c:49cf:d4d0:d8c8:bc42')).toStrictEqual({ + validSearch: true, + rangeQuery: [ + { + key: 'ipv6', + mask: 'fbbe:a363:9e14:987c:49cf:d4d0:d8c8:bc42/128', + }, + ], + }); + + // partial IP searches - ipv4 + const partialIpv4 = getIpRangeQuery('12.34.'); + expect(partialIpv4.validSearch).toBe(true); + expect(partialIpv4.rangeQuery?.[0]).toStrictEqual({ + key: 'ipv4', + from: '12.34.0.0', + to: '12.34.255.255', + }); + expect(getIpRangeQuery('123.456.7')).toStrictEqual({ + validSearch: false, + rangeQuery: [], + }); + expect(getIpRangeQuery('12:34.56')).toStrictEqual({ + validSearch: false, + rangeQuery: [], + }); + + // partial IP searches - ipv6 + const partialIpv6 = getIpRangeQuery('fbbe:a363:9e14:987c:49cf'); + expect(partialIpv6.validSearch).toBe(true); + expect(partialIpv6.rangeQuery?.[0]).toStrictEqual({ + key: 'ipv6', + from: 'fbbe:a363:9e14:987c:49cf::', + to: 'fbbe:a363:9e14:987c:49cf:ffff:ffff:ffff', + }); + + // partial IP searches - unknown type + let partialUnknownIp = getIpRangeQuery('1234'); + expect(partialUnknownIp.validSearch).toBe(true); + expect(partialUnknownIp.rangeQuery?.length).toBe(1); + expect(partialUnknownIp.rangeQuery?.[0]).toStrictEqual({ + key: 'ipv6', + from: '1234::', + to: '1234:ffff:ffff:ffff:ffff:ffff:ffff:ffff', + }); + + partialUnknownIp = getIpRangeQuery('123'); + expect(partialUnknownIp.validSearch).toBe(true); + expect(partialUnknownIp.rangeQuery?.length).toBe(2); + expect(partialUnknownIp.rangeQuery?.[0]).toStrictEqual({ + key: 'ipv4', + from: '123.0.0.0', + to: '123.255.255.255', + }); + expect(partialUnknownIp.rangeQuery?.[1]).toStrictEqual({ + key: 'ipv6', + from: '123::', + to: '123:ffff:ffff:ffff:ffff:ffff:ffff:ffff', + }); + }); +}); diff --git a/src/plugins/controls/common/options_list/ip_search.ts b/src/plugins/controls/common/options_list/ip_search.ts new file mode 100644 index 0000000000000..f371fbb1f6506 --- /dev/null +++ b/src/plugins/controls/common/options_list/ip_search.ts @@ -0,0 +1,118 @@ +/* + * 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 ipaddr from 'ipaddr.js'; + +export interface IpRangeQuery { + validSearch: boolean; + rangeQuery?: Array<{ key: string; from: string; to: string } | { key: string; mask: string }>; +} +interface IpSegments { + segments: string[]; + type: 'ipv4' | 'ipv6' | 'unknown'; +} + +export const getIpSegments = (searchString: string): IpSegments => { + if (searchString.indexOf('.') !== -1) { + // ipv4 takes priority - so if search string contains both `.` and `:` then it will just be an invalid ipv4 search + const ipv4Segments = searchString.split('.').filter((segment) => segment !== ''); + return { segments: ipv4Segments, type: 'ipv4' }; + } else if (searchString.indexOf(':') !== -1) { + // note that currently, because of the logic of splitting here, searching for shorthand IPv6 IPs is not supported (for example, + // must search for `59fb:0:0:0:0:1005:cc57:6571` and not `59fb::1005:cc57:6571` to get the expected match) + const ipv6Segments = searchString.split(':').filter((segment) => segment !== ''); + return { segments: ipv6Segments, type: 'ipv6' }; + } + return { segments: [searchString], type: 'unknown' }; +}; + +export const getMinMaxIp = ( + type: 'ipv4' | 'ipv6', + segments: IpSegments['segments'] +): { min: string; max: string } => { + const isIpv4 = type === 'ipv4'; + const minIp = isIpv4 + ? segments.concat(Array(4 - segments.length).fill('0')).join('.') + : segments.join(':') + '::'; + const maxIp = isIpv4 + ? segments.concat(Array(4 - segments.length).fill('255')).join('.') + : segments.concat(Array(8 - segments.length).fill('ffff')).join(':'); + return { + min: minIp, + max: maxIp, + }; +}; + +const buildFullIpSearchRangeQuery = (segments: IpSegments): IpRangeQuery['rangeQuery'] => { + const { type: ipType, segments: ipSegments } = segments; + + const isIpv4 = ipType === 'ipv4'; + const searchIp = ipSegments.join(isIpv4 ? '.' : ':'); + if (ipaddr.isValid(searchIp)) { + return [ + { + key: ipType, + mask: isIpv4 ? searchIp + '/32' : searchIp + '/128', + }, + ]; + } + return undefined; +}; + +const buildPartialIpSearchRangeQuery = (segments: IpSegments): IpRangeQuery['rangeQuery'] => { + const { type: ipType, segments: ipSegments } = segments; + + const ranges = []; + if (ipType === 'unknown' || ipType === 'ipv4') { + const { min: minIpv4, max: maxIpv4 } = getMinMaxIp('ipv4', ipSegments); + + if (ipaddr.isValid(minIpv4) && ipaddr.isValid(maxIpv4)) { + ranges.push({ + key: 'ipv4', + from: minIpv4, + to: maxIpv4, + }); + } + } + + if (ipType === 'unknown' || ipType === 'ipv6') { + const { min: minIpv6, max: maxIpv6 } = getMinMaxIp('ipv6', ipSegments); + + if (ipaddr.isValid(minIpv6) && ipaddr.isValid(maxIpv6)) { + ranges.push({ + key: 'ipv6', + from: minIpv6, + to: maxIpv6, + }); + } + } + + return ranges; +}; + +export const getIpRangeQuery = (searchString: string): IpRangeQuery => { + if (searchString.match(/^[A-Fa-f0-9.:]*$/) === null) { + return { validSearch: false }; + } + + const ipSegments = getIpSegments(searchString); + if (ipSegments.type === 'ipv4' && ipSegments.segments.length === 4) { + const ipv4RangeQuery = buildFullIpSearchRangeQuery(ipSegments); + return { validSearch: Boolean(ipv4RangeQuery), rangeQuery: ipv4RangeQuery }; + } + if (ipSegments.type === 'ipv6' && ipSegments.segments.length === 8) { + const ipv6RangeQuery = buildFullIpSearchRangeQuery(ipSegments); + return { validSearch: Boolean(ipv6RangeQuery), rangeQuery: ipv6RangeQuery }; + } + + const partialRangeQuery = buildPartialIpSearchRangeQuery(ipSegments); + return { + validSearch: !(partialRangeQuery?.length === 0), + rangeQuery: partialRangeQuery, + }; +}; diff --git a/src/plugins/controls/common/options_list/mocks.tsx b/src/plugins/controls/common/options_list/mocks.tsx index 2fd4d31a54b21..09f6d9caa33b4 100644 --- a/src/plugins/controls/common/options_list/mocks.tsx +++ b/src/plugins/controls/common/options_list/mocks.tsx @@ -18,7 +18,7 @@ const mockOptionsListComponentState = { availableOptions: ['woof', 'bark', 'meow', 'quack', 'moo'], invalidSelections: [], validSelections: [], - searchString: '', + searchString: { value: '', valid: true }, } as OptionsListComponentState; const mockOptionsListEmbeddableInput = { diff --git a/src/plugins/controls/public/control_group/embeddable/control_group_container.tsx b/src/plugins/controls/public/control_group/embeddable/control_group_container.tsx index c07715007b46c..a1d8bc06f822a 100644 --- a/src/plugins/controls/public/control_group/embeddable/control_group_container.tsx +++ b/src/plugins/controls/public/control_group/embeddable/control_group_container.tsx @@ -10,7 +10,7 @@ import { skip, debounceTime, distinctUntilChanged } from 'rxjs/operators'; import React from 'react'; import ReactDOM from 'react-dom'; import { Filter, uniqFilters } from '@kbn/es-query'; -import { merge, Subject, Subscription } from 'rxjs'; +import { BehaviorSubject, merge, Subject, Subscription } from 'rxjs'; import { EuiContextMenuPanel } from '@elastic/eui'; import { @@ -57,6 +57,8 @@ export class ControlGroupContainer extends Container< public readonly type = CONTROL_GROUP_TYPE; public readonly anyControlOutputConsumerLoading$: Subject = new Subject(); + private initialized$ = new BehaviorSubject(false); + private subscriptions: Subscription = new Subscription(); private domNode?: HTMLElement; private recalculateFilters$: Subject; @@ -194,10 +196,11 @@ export class ControlGroupContainer extends Container< }); // when all children are ready setup subscriptions - this.untilReady().then(() => { + this.untilAllChildrenReady().then(() => { this.recalculateDataViews(); this.recalculateFilters(); this.setupSubscriptions(); + this.initialized$.next(true); }); } @@ -327,7 +330,7 @@ export class ControlGroupContainer extends Container< }; } - public untilReady = () => { + public untilAllChildrenReady = () => { const panelsLoading = () => Object.keys(this.getInput().panels).some( (panelId) => !this.getOutput().embeddableLoaded[panelId] @@ -349,6 +352,24 @@ export class ControlGroupContainer extends Container< return Promise.resolve(); }; + public untilInitialized = () => { + if (this.initialized$.value === false) { + return new Promise((resolve, reject) => { + const subscription = this.initialized$.subscribe((isInitialized) => { + if (this.destroyed) { + subscription.unsubscribe(); + reject(); + } + if (isInitialized) { + subscription.unsubscribe(); + resolve(); + } + }); + }); + } + return Promise.resolve(); + }; + public render(dom: HTMLElement) { if (this.domNode) { ReactDOM.unmountComponentAtNode(this.domNode); diff --git a/src/plugins/controls/public/options_list/components/options_list_popover.tsx b/src/plugins/controls/public/options_list/components/options_list_popover.tsx index 0cdfcefb9baa5..8863a3d1978a3 100644 --- a/src/plugins/controls/public/options_list/components/options_list_popover.tsx +++ b/src/plugins/controls/public/options_list/components/options_list_popover.tsx @@ -26,8 +26,8 @@ import { import { useReduxEmbeddableContext } from '@kbn/presentation-util-plugin/public'; import { optionsListReducers } from '../options_list_reducers'; -import { OptionsListStrings } from './options_list_strings'; import { OptionsListReduxState } from '../types'; +import { OptionsListStrings } from './options_list_strings'; export interface OptionsListPopoverProps { width: number; @@ -80,11 +80,12 @@ export const OptionsListPopover = ({ width, updateSearchString }: OptionsListPop > updateSearchString(event.target.value)} - value={searchString} + value={searchString.value} data-test-subj="optionsList-control-search-input" placeholder={ totalCardinality diff --git a/src/plugins/controls/public/options_list/embeddable/options_list_embeddable.tsx b/src/plugins/controls/public/options_list/embeddable/options_list_embeddable.tsx index 0ccd5d49cabc2..292e7cb6b0597 100644 --- a/src/plugins/controls/public/options_list/embeddable/options_list_embeddable.tsx +++ b/src/plugins/controls/public/options_list/embeddable/options_list_embeddable.tsx @@ -35,7 +35,7 @@ import { OptionsListEmbeddableInput, OPTIONS_LIST_CONTROL, } from '../..'; -import { optionsListReducers } from '../options_list_reducers'; +import { getDefaultComponentState, optionsListReducers } from '../options_list_reducers'; import { OptionsListControl } from '../components/options_list_control'; import { ControlsDataViewsService } from '../../services/data_views/types'; import { ControlsOptionsListService } from '../../services/options_list/types'; @@ -105,6 +105,7 @@ export class OptionsListEmbeddable extends Embeddable({ embeddable: this, reducers: optionsListReducers, + initialComponentState: getDefaultComponentState(), }); this.initialize(); @@ -277,73 +278,87 @@ export class OptionsListEmbeddable extends Embeddable { + dispatch(setLoading(false)); + dispatch(publishFilters(newFilters)); + }); } else { - const valid: string[] = []; - const invalid: string[] = []; - - for (const selectedOption of selectedOptions) { - if (invalidSelections?.includes(selectedOption)) invalid.push(selectedOption); - else valid.push(selectedOption); - } - dispatch( - updateQueryResults({ - availableOptions: suggestions, - invalidSelections: invalid, - validSelections: valid, - totalCardinality, - }) - ); + batch(() => { + dispatch( + updateQueryResults({ + availableOptions: [], + }) + ); + dispatch(setLoading(false)); + }); } - - // publish filter - const newFilters = await this.buildFilter(); - batch(() => { - dispatch(setLoading(false)); - dispatch(publishFilters(newFilters)); - }); }; private buildFilter = async () => { diff --git a/src/plugins/controls/public/options_list/embeddable/options_list_embeddable_factory.tsx b/src/plugins/controls/public/options_list/embeddable/options_list_embeddable_factory.tsx index d0b779e566c31..ea36ede0e1c9d 100644 --- a/src/plugins/controls/public/options_list/embeddable/options_list_embeddable_factory.tsx +++ b/src/plugins/controls/public/options_list/embeddable/options_list_embeddable_factory.tsx @@ -57,7 +57,8 @@ export class OptionsListEmbeddableFactory public isFieldCompatible = (dataControlField: DataControlField) => { if ( (dataControlField.field.aggregatable && dataControlField.field.type === 'string') || - dataControlField.field.type === 'boolean' + dataControlField.field.type === 'boolean' || + dataControlField.field.type === 'ip' ) { dataControlField.compatibleControlTypes.push(this.type); } diff --git a/src/plugins/controls/public/options_list/options_list_reducers.ts b/src/plugins/controls/public/options_list/options_list_reducers.ts index 3b48e6f989f6c..2a0c69126c135 100644 --- a/src/plugins/controls/public/options_list/options_list_reducers.ts +++ b/src/plugins/controls/public/options_list/options_list_reducers.ts @@ -12,6 +12,11 @@ import { Filter } from '@kbn/es-query'; import { OptionsListReduxState, OptionsListComponentState } from './types'; import { OptionsListField } from '../../common/options_list/types'; +import { getIpRangeQuery } from '../../common/options_list/ip_search'; + +export const getDefaultComponentState = (): OptionsListReduxState['componentState'] => ({ + searchString: { value: '', valid: true }, +}); export const optionsListReducers = { deselectOption: (state: WritableDraft, action: PayloadAction) => { @@ -38,7 +43,13 @@ export const optionsListReducers = { } }, setSearchString: (state: WritableDraft, action: PayloadAction) => { - state.componentState.searchString = action.payload; + state.componentState.searchString.value = action.payload; + if ( + action.payload !== '' && // empty string search is never invalid + state.componentState.field?.type === 'ip' // only IP searches can currently be invalid + ) { + state.componentState.searchString.valid = getIpRangeQuery(action.payload).validSearch; + } }, selectOption: (state: WritableDraft, action: PayloadAction) => { if (!state.explicitInput.selectedOptions) state.explicitInput.selectedOptions = []; diff --git a/src/plugins/controls/public/options_list/types.ts b/src/plugins/controls/public/options_list/types.ts index aca0c05fe0893..4001299a9ab53 100644 --- a/src/plugins/controls/public/options_list/types.ts +++ b/src/plugins/controls/public/options_list/types.ts @@ -10,6 +10,11 @@ import { ReduxEmbeddableState } from '@kbn/presentation-util-plugin/public'; import { ControlOutput } from '../types'; import { OptionsListEmbeddableInput, OptionsListField } from '../../common/options_list/types'; +interface SearchString { + value: string; + valid: boolean; +} + // Component state is only used by public components. export interface OptionsListComponentState { field?: OptionsListField; @@ -17,7 +22,7 @@ export interface OptionsListComponentState { availableOptions?: string[]; invalidSelections?: string[]; validSelections?: string[]; - searchString: string; + searchString: SearchString; } // public only - redux embeddable state type diff --git a/src/plugins/controls/server/options_list/options_list_queries.test.ts b/src/plugins/controls/server/options_list/options_list_queries.test.ts index 399154c5518aa..40536822833da 100644 --- a/src/plugins/controls/server/options_list/options_list_queries.test.ts +++ b/src/plugins/controls/server/options_list/options_list_queries.test.ts @@ -102,53 +102,55 @@ describe('options list queries', () => { }); }); - describe('suggestion aggregation and parsing', () => { - test('creates case insensitive aggregation for a text / keyword field with a search string', () => { - const optionsListRequestBodyMock: OptionsListRequestBody = { - fieldName: 'coolTestField.keyword', - textFieldName: 'coolTestField', - searchString: 'cooool', - fieldSpec: { aggregatable: true } as unknown as FieldSpec, - }; - const suggestionAggBuilder = getSuggestionAggregationBuilder(optionsListRequestBodyMock); - expect(suggestionAggBuilder.buildAggregation(optionsListRequestBodyMock)) - .toMatchInlineSnapshot(` - Object { - "aggs": Object { - "keywordSuggestions": Object { - "terms": Object { - "field": "coolTestField.keyword", - "shard_size": 10, + describe('suggestion aggregation', () => { + describe('text / keyword field', () => { + test('with a search string, creates case insensitive aggregation', () => { + const optionsListRequestBodyMock: OptionsListRequestBody = { + fieldName: 'coolTestField.keyword', + textFieldName: 'coolTestField', + searchString: 'cooool', + fieldSpec: { aggregatable: true } as unknown as FieldSpec, + }; + const suggestionAggBuilder = getSuggestionAggregationBuilder(optionsListRequestBodyMock); + expect(suggestionAggBuilder.buildAggregation(optionsListRequestBodyMock)) + .toMatchInlineSnapshot(` + Object { + "aggs": Object { + "keywordSuggestions": Object { + "terms": Object { + "field": "coolTestField.keyword", + "shard_size": 10, + }, }, }, - }, - "filter": Object { - "match_phrase_prefix": Object { - "coolTestField": "cooool", + "filter": Object { + "match_phrase_prefix": Object { + "coolTestField": "cooool", + }, }, - }, - } - `); - }); + } + `); + }); - test('creates keyword aggregation for a text / keyword field without a search string', () => { - const optionsListRequestBodyMock: OptionsListRequestBody = { - fieldName: 'coolTestField.keyword', - textFieldName: 'coolTestField', - fieldSpec: { aggregatable: true } as unknown as FieldSpec, - }; - const suggestionAggBuilder = getSuggestionAggregationBuilder(optionsListRequestBodyMock); - expect(suggestionAggBuilder.buildAggregation(optionsListRequestBodyMock)) - .toMatchInlineSnapshot(` - Object { - "terms": Object { - "execution_hint": "map", - "field": "coolTestField.keyword", - "include": ".*", - "shard_size": 10, - }, - } - `); + test('without a search string, creates keyword aggregation', () => { + const optionsListRequestBodyMock: OptionsListRequestBody = { + fieldName: 'coolTestField.keyword', + textFieldName: 'coolTestField', + fieldSpec: { aggregatable: true } as unknown as FieldSpec, + }; + const suggestionAggBuilder = getSuggestionAggregationBuilder(optionsListRequestBodyMock); + expect(suggestionAggBuilder.buildAggregation(optionsListRequestBodyMock)) + .toMatchInlineSnapshot(` + Object { + "terms": Object { + "execution_hint": "map", + "field": "coolTestField.keyword", + "include": ".*", + "shard_size": 10, + }, + } + `); + }); }); test('creates boolean aggregation for boolean field', () => { @@ -216,6 +218,177 @@ describe('options list queries', () => { `); }); + describe('IP field', () => { + test('without a search string, creates IP range aggregation with default range', () => { + const optionsListRequestBodyMock: OptionsListRequestBody = { + fieldName: 'clientip', + fieldSpec: { type: 'ip' } as unknown as FieldSpec, + }; + const suggestionAggBuilder = getSuggestionAggregationBuilder(optionsListRequestBodyMock); + expect(suggestionAggBuilder.buildAggregation(optionsListRequestBodyMock)) + .toMatchInlineSnapshot(` + Object { + "aggs": Object { + "filteredSuggestions": Object { + "terms": Object { + "execution_hint": "map", + "field": "clientip", + "shard_size": 10, + }, + }, + }, + "ip_range": Object { + "field": "clientip", + "keyed": true, + "ranges": Array [ + Object { + "from": "::", + "key": "ipv6", + "to": "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", + }, + ], + }, + } + `); + }); + + test('full IPv4 in the search string, creates IP range aggregation with CIDR mask', () => { + const optionsListRequestBodyMock: OptionsListRequestBody = { + fieldName: 'clientip', + fieldSpec: { type: 'ip' } as unknown as FieldSpec, + searchString: '41.77.243.255', + }; + const suggestionAggBuilder = getSuggestionAggregationBuilder(optionsListRequestBodyMock); + expect(suggestionAggBuilder.buildAggregation(optionsListRequestBodyMock)) + .toMatchInlineSnapshot(` + Object { + "aggs": Object { + "filteredSuggestions": Object { + "terms": Object { + "execution_hint": "map", + "field": "clientip", + "shard_size": 10, + }, + }, + }, + "ip_range": Object { + "field": "clientip", + "keyed": true, + "ranges": Array [ + Object { + "key": "ipv4", + "mask": "41.77.243.255/32", + }, + ], + }, + } + `); + }); + + test('full IPv6 in the search string, creates IP range aggregation with CIDR mask', () => { + const optionsListRequestBodyMock: OptionsListRequestBody = { + fieldName: 'clientip', + fieldSpec: { type: 'ip' } as unknown as FieldSpec, + searchString: 'f688:fb50:6433:bba2:604:f2c:194a:d3c5', + }; + const suggestionAggBuilder = getSuggestionAggregationBuilder(optionsListRequestBodyMock); + expect(suggestionAggBuilder.buildAggregation(optionsListRequestBodyMock)) + .toMatchInlineSnapshot(` + Object { + "aggs": Object { + "filteredSuggestions": Object { + "terms": Object { + "execution_hint": "map", + "field": "clientip", + "shard_size": 10, + }, + }, + }, + "ip_range": Object { + "field": "clientip", + "keyed": true, + "ranges": Array [ + Object { + "key": "ipv6", + "mask": "f688:fb50:6433:bba2:604:f2c:194a:d3c5/128", + }, + ], + }, + } + `); + }); + + test('partial IPv4 in the search string, creates IP range aggregation with min and max', () => { + const optionsListRequestBodyMock: OptionsListRequestBody = { + fieldName: 'clientip', + fieldSpec: { type: 'ip' } as unknown as FieldSpec, + searchString: '41.77', + }; + const suggestionAggBuilder = getSuggestionAggregationBuilder(optionsListRequestBodyMock); + expect(suggestionAggBuilder.buildAggregation(optionsListRequestBodyMock)) + .toMatchInlineSnapshot(` + Object { + "aggs": Object { + "filteredSuggestions": Object { + "terms": Object { + "execution_hint": "map", + "field": "clientip", + "shard_size": 10, + }, + }, + }, + "ip_range": Object { + "field": "clientip", + "keyed": true, + "ranges": Array [ + Object { + "from": "41.77.0.0", + "key": "ipv4", + "to": "41.77.255.255", + }, + ], + }, + } + `); + }); + + test('partial IPv46 in the search string, creates IP range aggregation with min and max', () => { + const optionsListRequestBodyMock: OptionsListRequestBody = { + fieldName: 'clientip', + fieldSpec: { type: 'ip' } as unknown as FieldSpec, + searchString: 'cdb6:', + }; + const suggestionAggBuilder = getSuggestionAggregationBuilder(optionsListRequestBodyMock); + expect(suggestionAggBuilder.buildAggregation(optionsListRequestBodyMock)) + .toMatchInlineSnapshot(` + Object { + "aggs": Object { + "filteredSuggestions": Object { + "terms": Object { + "execution_hint": "map", + "field": "clientip", + "shard_size": 10, + }, + }, + }, + "ip_range": Object { + "field": "clientip", + "keyed": true, + "ranges": Array [ + Object { + "from": "cdb6::", + "key": "ipv6", + "to": "cdb6:ffff:ffff:ffff:ffff:ffff:ffff:ffff", + }, + ], + }, + } + `); + }); + }); + }); + + describe('suggestion parsing', () => { test('parses keyword / text result', () => { const optionsListRequestBodyMock: OptionsListRequestBody = { fieldName: 'coolTestField.keyword', @@ -318,4 +491,60 @@ describe('options list queries', () => { `); }); }); + + test('parses mixed IPv4 and IPv6 result', () => { + const optionsListRequestBodyMock: OptionsListRequestBody = { + fieldName: 'clientip', + fieldSpec: { type: 'ip' } as unknown as FieldSpec, + }; + const suggestionAggBuilder = getSuggestionAggregationBuilder(optionsListRequestBodyMock); + rawSearchResponseMock.aggregations = { + suggestions: { + buckets: { + ipv4: { + from: '0.0.0.0', + to: '255.255.255.255', + filteredSuggestions: { + buckets: [ + { doc_count: 8, key: '21.35.91.62' }, + { doc_count: 8, key: '21.35.91.61' }, + { doc_count: 11, key: '111.52.174.2' }, + { doc_count: 1, key: '56.73.58.63' }, + { doc_count: 9, key: '23.216.241.120' }, + { doc_count: 10, key: '196.162.13.39' }, + { doc_count: 7, key: '203.88.33.151' }, + ], + }, + }, + ipv6: { + from: '::', + to: 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff', + filteredSuggestions: { + buckets: [ + { doc_count: 12, key: '52:ae76:5947:5e2a:551:fe6a:712a:c72' }, + { doc_count: 1, key: 'fd:4aa0:c27c:b04:997f:2de1:51b4:8418' }, + { doc_count: 9, key: '28c7:c9a4:42fd:16b0:4de5:e41e:28d9:9172' }, + { doc_count: 6, key: '1ec:aa98:b0a6:d07c:590:18a0:8a33:2eb8' }, + { doc_count: 10, key: 'f7a9:640b:b5a0:1219:8d75:ed94:3c3e:2e63' }, + ], + }, + }, + }, + }, + }; + expect(suggestionAggBuilder.parse(rawSearchResponseMock)).toMatchInlineSnapshot(` + Array [ + "52:ae76:5947:5e2a:551:fe6a:712a:c72", + "111.52.174.2", + "196.162.13.39", + "f7a9:640b:b5a0:1219:8d75:ed94:3c3e:2e63", + "23.216.241.120", + "28c7:c9a4:42fd:16b0:4de5:e41e:28d9:9172", + "21.35.91.62", + "21.35.91.61", + "203.88.33.151", + "1ec:aa98:b0a6:d07c:590:18a0:8a33:2eb8", + ] + `); + }); }); diff --git a/src/plugins/controls/server/options_list/options_list_queries.ts b/src/plugins/controls/server/options_list/options_list_queries.ts index 4e88c449a7e8e..d1fa89bbc9358 100644 --- a/src/plugins/controls/server/options_list/options_list_queries.ts +++ b/src/plugins/controls/server/options_list/options_list_queries.ts @@ -7,17 +7,21 @@ */ import { get, isEmpty } from 'lodash'; - import { SearchResponse } from '@elastic/elasticsearch/lib/api/types'; import { getFieldSubtypeNested } from '@kbn/data-views-plugin/common'; import { OptionsListRequestBody } from '../../common/options_list/types'; - +import { getIpRangeQuery, type IpRangeQuery } from '../../common/options_list/ip_search'; export interface OptionsListAggregationBuilder { buildAggregation: (req: OptionsListRequestBody) => unknown; parse: (response: SearchResponse) => string[]; } +interface EsBucket { + key: string; + doc_count: number; +} + /** * Validation aggregations */ @@ -62,6 +66,9 @@ export const getSuggestionAggregationBuilder = ({ if (fieldSpec?.type === 'boolean') { return suggestionAggSubtypes.boolean; } + if (fieldSpec?.type === 'ip') { + return suggestionAggSubtypes.ip; + } if (fieldSpec && getFieldSubtypeNested(fieldSpec)) { return suggestionAggSubtypes.subtypeNested; } @@ -71,6 +78,16 @@ export const getSuggestionAggregationBuilder = ({ const getEscapedQuery = (q: string = '') => q.replace(/[.?+*|{}[\]()"\\#@&<>~]/g, (match) => `\\${match}`); +const getIpBuckets = (rawEsResult: any, combinedBuckets: EsBucket[], type: 'ipv4' | 'ipv6') => { + const results = get( + rawEsResult, + `aggregations.suggestions.buckets.${type}.filteredSuggestions.buckets` + ); + if (results) { + results.forEach((suggestion: EsBucket) => combinedBuckets.push(suggestion)); + } +}; + const suggestionAggSubtypes: { [key: string]: OptionsListAggregationBuilder } = { /** * the "Keyword only" query / parser should be used when the options list is built on a field which has only keyword mappings. @@ -139,6 +156,65 @@ const suggestionAggSubtypes: { [key: string]: OptionsListAggregationBuilder } = ), }, + /** + * the "IP" query / parser should be used when the options list is built on a field of type IP. + */ + ip: { + buildAggregation: ({ fieldName, searchString }: OptionsListRequestBody) => { + let ipRangeQuery: IpRangeQuery = { + validSearch: true, + rangeQuery: [ + { + key: 'ipv6', + from: '::', + to: 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff', + }, + ], + }; + + if (searchString) { + ipRangeQuery = getIpRangeQuery(searchString); + if (!ipRangeQuery.validSearch) { + // ideally should be prevented on the client side but, if somehow an invalid search gets through to the server, + // simply don't return an aggregation query for the ES search request + return undefined; + } + } + + return { + ip_range: { + field: fieldName, + ranges: ipRangeQuery.rangeQuery, + keyed: true, + }, + aggs: { + filteredSuggestions: { + terms: { + field: fieldName, + execution_hint: 'map', + shard_size: 10, + }, + }, + }, + }; + }, + parse: (rawEsResult) => { + if (!Boolean(rawEsResult.aggregations?.suggestions)) { + // if this is happens, that means there is an invalid search that snuck through to the server side code; + // so, might as well early return with no suggestions + return []; + } + + const buckets: EsBucket[] = []; + getIpBuckets(rawEsResult, buckets, 'ipv4'); // modifies buckets array directly, i.e. "by reference" + getIpBuckets(rawEsResult, buckets, 'ipv6'); + return buckets + .sort((bucketA: EsBucket, bucketB: EsBucket) => bucketB.doc_count - bucketA.doc_count) + .slice(0, 10) // only return top 10 results + .map((bucket: EsBucket) => bucket.key); + }, + }, + /** * the "Subtype Nested" query / parser should be used when the options list is built on a field with subtype nested. */ diff --git a/src/plugins/controls/server/options_list/options_list_suggestions_route.ts b/src/plugins/controls/server/options_list/options_list_suggestions_route.ts index 0d7654f318f31..c9af30bb07b82 100644 --- a/src/plugins/controls/server/options_list/options_list_suggestions_route.ts +++ b/src/plugins/controls/server/options_list/options_list_suggestions_route.ts @@ -95,9 +95,12 @@ export const setupOptionsListSuggestionsRoute = ( const suggestionBuilder = getSuggestionAggregationBuilder(request); const validationBuilder = getValidationAggregationBuilder(); - const suggestionAggregations = { - suggestions: suggestionBuilder.buildAggregation(request), - }; + const builtSuggestionAggregation = suggestionBuilder.buildAggregation(request); + const suggestionAggregation = builtSuggestionAggregation + ? { + suggestions: builtSuggestionAggregation, + } + : {}; const builtValidationAggregation = validationBuilder.buildAggregation(request); const validationAggregations = builtValidationAggregation ? { @@ -114,7 +117,7 @@ export const setupOptionsListSuggestionsRoute = ( }, }, aggs: { - ...suggestionAggregations, + ...suggestionAggregation, ...validationAggregations, unique_terms: { cardinality: { diff --git a/src/plugins/custom_integrations/common/index.ts b/src/plugins/custom_integrations/common/index.ts index e52a5deac59e5..6d2252f3c3d43 100755 --- a/src/plugins/custom_integrations/common/index.ts +++ b/src/plugins/custom_integrations/common/index.ts @@ -51,6 +51,13 @@ export const INTEGRATION_CATEGORY_DISPLAY = { geo: 'Geo', }; +// featured integrations will be brought to the top of the search results for +// a given category. Integrations are displayed in the order of the array. +export const FEATURED_INTEGRATIONS_BY_CATEGORY = { + security: ['endpoint', 'cloud_security_posture', 'network_traffic'], + '': ['apm', 'endpoint', 'web_crawler'], // no category selected +}; + /** * A category applicable to an Integration. */ diff --git a/src/plugins/dashboard/public/application/embeddable/dashboard_container.tsx b/src/plugins/dashboard/public/application/embeddable/dashboard_container.tsx index d8c66155d8b30..d4ee045a8d9a8 100644 --- a/src/plugins/dashboard/public/application/embeddable/dashboard_container.tsx +++ b/src/plugins/dashboard/public/application/embeddable/dashboard_container.tsx @@ -153,16 +153,13 @@ export class DashboardContainer extends Container { - if (!this.controlGroup || isErrorEmbeddable(this.controlGroup)) return; - syncDashboardControlGroup({ - dashboardContainer: this, - controlGroup: this.controlGroup, - }).then((result) => { - if (!result) return; - const { onDestroyControlGroup } = result; - this.onDestroyControlGroup = onDestroyControlGroup; - }); + syncDashboardControlGroup({ + dashboardContainer: this, + controlGroup: this.controlGroup, + }).then((result) => { + if (!result) return; + const { onDestroyControlGroup } = result; + this.onDestroyControlGroup = onDestroyControlGroup; }); } diff --git a/src/plugins/dashboard/public/application/embeddable/dashboard_container_factory.tsx b/src/plugins/dashboard/public/application/embeddable/dashboard_container_factory.tsx index 58a2c63492c09..40c25b454be9e 100644 --- a/src/plugins/dashboard/public/application/embeddable/dashboard_container_factory.tsx +++ b/src/plugins/dashboard/public/application/embeddable/dashboard_container_factory.tsx @@ -21,6 +21,7 @@ import { ContainerOutput, EmbeddableFactory, EmbeddableFactoryDefinition, + isErrorEmbeddable, } from '@kbn/embeddable-plugin/public'; import { getDefaultControlGroupInput } from '@kbn/controls-plugin/common'; @@ -73,15 +74,13 @@ export class DashboardContainerFactoryDefinition }; } - public create = async ( - initialInput: DashboardContainerInput, - parent?: Container - ): Promise => { + private buildControlGroup = async ( + initialInput: DashboardContainerInput + ): Promise => { const { pluginServices } = await import('../../services/plugin_services'); const { embeddable: { getEmbeddableFactory }, } = pluginServices.getServices(); - const controlsGroupFactory = getEmbeddableFactory< ControlGroupInput, ControlGroupOutput, @@ -97,10 +96,23 @@ export class DashboardContainerFactoryDefinition filters, query, }); + if (controlGroup && !isErrorEmbeddable(controlGroup)) { + await controlGroup.untilInitialized(); + } + return controlGroup; + }; + + public create = async ( + initialInput: DashboardContainerInput, + parent?: Container + ): Promise => { + const controlGroupPromise = this.buildControlGroup(initialInput); + const dashboardContainerPromise = import('./dashboard_container'); - const { DashboardContainer: DashboardContainerEmbeddable } = await import( - './dashboard_container' - ); + const [controlGroup, { DashboardContainer: DashboardContainerEmbeddable }] = await Promise.all([ + controlGroupPromise, + dashboardContainerPromise, + ]); return Promise.resolve(new DashboardContainerEmbeddable(initialInput, parent, controlGroup)); }; diff --git a/src/plugins/dashboard/public/application/embeddable/viewport/dashboard_viewport.tsx b/src/plugins/dashboard/public/application/embeddable/viewport/dashboard_viewport.tsx index 52e76295eb998..dff5ff80bcc27 100644 --- a/src/plugins/dashboard/public/application/embeddable/viewport/dashboard_viewport.tsx +++ b/src/plugins/dashboard/public/application/embeddable/viewport/dashboard_viewport.tsx @@ -33,7 +33,6 @@ export interface DashboardViewportProps { interface State { isFullScreenMode: boolean; - controlGroupReady: boolean; useMargins: boolean; title: string; description?: string; @@ -57,7 +56,6 @@ export class DashboardViewport extends React.Component this.setState({ controlGroupReady: true })); - } } public componentWillUnmount() { @@ -164,9 +159,7 @@ export class DashboardViewport extends React.Component )} - {this.state.controlGroupReady && ( - - )} + ); diff --git a/src/plugins/data/common/search/aggs/agg_type.ts b/src/plugins/data/common/search/aggs/agg_type.ts index 8d01377ddf808..4812ac6f07c5f 100644 --- a/src/plugins/data/common/search/aggs/agg_type.ts +++ b/src/plugins/data/common/search/aggs/agg_type.ts @@ -29,7 +29,8 @@ type PostFlightRequestFn = ( searchSource: ISearchSource, inspectorRequestAdapter?: RequestAdapter, abortSignal?: AbortSignal, - searchSessionId?: string + searchSessionId?: string, + disableShardFailureWarning?: boolean ) => Promise>; export interface AggTypeConfig< diff --git a/src/plugins/data/common/search/aggs/buckets/_terms_other_bucket_helper.ts b/src/plugins/data/common/search/aggs/buckets/_terms_other_bucket_helper.ts index cc49c896bdfe5..f695dc1b1d399 100644 --- a/src/plugins/data/common/search/aggs/buckets/_terms_other_bucket_helper.ts +++ b/src/plugins/data/common/search/aggs/buckets/_terms_other_bucket_helper.ts @@ -333,7 +333,8 @@ export const createOtherBucketPostFlightRequest = ( searchSource, inspectorRequestAdapter, abortSignal, - searchSessionId + searchSessionId, + disableShardFailureWarning ) => { if (!resp.aggregations) return resp; const nestedSearchSource = searchSource.createChild(); @@ -347,6 +348,7 @@ export const createOtherBucketPostFlightRequest = ( nestedSearchSource.fetch$({ abortSignal, sessionId: searchSessionId, + disableShardFailureWarning, inspector: { adapter: inspectorRequestAdapter, title: i18n.translate('data.search.aggs.buckets.terms.otherBucketTitle', { diff --git a/src/plugins/data/common/search/search_source/search_source.ts b/src/plugins/data/common/search/search_source/search_source.ts index d6ec49360e95b..497a247668694 100644 --- a/src/plugins/data/common/search/search_source/search_source.ts +++ b/src/plugins/data/common/search/search_source/search_source.ts @@ -511,7 +511,8 @@ export class SearchSource { this, options.inspector?.adapter, options.abortSignal, - options.sessionId + options.sessionId, + options.disableShardFailureWarning ); } } diff --git a/src/plugins/data/config.mock.ts b/src/plugins/data/config.mock.ts new file mode 100644 index 0000000000000..ab1d02cb63b31 --- /dev/null +++ b/src/plugins/data/config.mock.ts @@ -0,0 +1,40 @@ +/* + * 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 moment from 'moment/moment'; +import { SearchConfigSchema, SearchSessionsConfigSchema } from './config'; + +export const getMockSearchConfig = ({ + sessions: { enabled = true, defaultExpiration = moment.duration(7, 'd') } = { + enabled: true, + defaultExpiration: moment.duration(7, 'd'), + }, + asyncSearch: { + waitForCompletion = moment.duration(100, 'ms'), + keepAlive = moment.duration(1, 'm'), + batchedReduceSize = 64, + } = { + waitForCompletion: moment.duration(100, 'ms'), + keepAlive: moment.duration(1, 'm'), + batchedReduceSize: 64, + }, +}: Partial<{ + sessions: Partial; + asyncSearch: Partial; +}>): SearchConfigSchema => + ({ + asyncSearch: { + waitForCompletion, + keepAlive, + batchedReduceSize, + } as SearchConfigSchema['asyncSearch'], + sessions: { + enabled, + defaultExpiration, + } as SearchSessionsConfigSchema, + } as SearchConfigSchema); diff --git a/src/plugins/data/config.ts b/src/plugins/data/config.ts index d4331ecd760b4..05d52b4e127b3 100644 --- a/src/plugins/data/config.ts +++ b/src/plugins/data/config.ts @@ -23,7 +23,7 @@ export const searchSessionsConfigSchema = schema.object({ /** * maxUpdateRetries controls how many retries we perform while attempting to save a search session */ - maxUpdateRetries: schema.number({ defaultValue: 3 }), + maxUpdateRetries: schema.number({ defaultValue: 10 }), /** * defaultExpiration controls how long search sessions are valid for, until they are expired. @@ -46,20 +46,29 @@ export const searchSessionsConfigSchema = schema.object({ }), }); -export const configSchema = schema.object({ - search: schema.object({ - aggs: schema.object({ - shardDelay: schema.object({ - // Whether or not to register the shard_delay (which is only available in snapshot versions - // of Elasticsearch) agg type/expression function to make it available in the UI for either - // functional or manual testing - enabled: schema.boolean({ defaultValue: false }), - }), +export const searchConfigSchema = schema.object({ + asyncSearch: schema.object({ + waitForCompletion: schema.duration({ defaultValue: '100ms' }), + keepAlive: schema.duration({ defaultValue: '1m' }), + batchedReduceSize: schema.number({ defaultValue: 64 }), + }), + aggs: schema.object({ + shardDelay: schema.object({ + // Whether or not to register the shard_delay (which is only available in snapshot versions + // of Elasticsearch) agg type/expression function to make it available in the UI for either + // functional or manual testing + enabled: schema.boolean({ defaultValue: false }), }), - sessions: searchSessionsConfigSchema, }), + sessions: searchSessionsConfigSchema, +}); + +export const configSchema = schema.object({ + search: searchConfigSchema, }); export type ConfigSchema = TypeOf; +export type SearchConfigSchema = TypeOf; + export type SearchSessionsConfigSchema = TypeOf; diff --git a/src/plugins/data/server/search/collectors/search/usage.ts b/src/plugins/data/server/search/collectors/search/usage.ts index c3e09257a4628..fb2a9acc37009 100644 --- a/src/plugins/data/server/search/collectors/search/usage.ts +++ b/src/plugins/data/server/search/collectors/search/usage.ts @@ -87,11 +87,11 @@ export function searchUsageObserver( return { next(response: IEsSearchResponse) { if (isRestore || !isCompleteResponse(response)) return; - logger.debug(`trackSearchStatus:next ${response.rawResponse.took}`); + logger.debug(`trackSearchStatus:success, took:${response.rawResponse.took}`); usage?.trackSuccess(response.rawResponse.took); }, - error() { - logger.debug(`trackSearchStatus:error`); + error(e: Error) { + logger.debug(`trackSearchStatus:error, ${e}`); usage?.trackError(); }, }; diff --git a/src/plugins/data/server/search/search_service.ts b/src/plugins/data/server/search/search_service.ts index 7523da61752b4..eba7ea22acf4f 100644 --- a/src/plugins/data/server/search/search_service.ts +++ b/src/plugins/data/server/search/search_service.ts @@ -178,6 +178,7 @@ export class SearchService implements Plugin { ENHANCED_ES_SEARCH_STRATEGY, enhancedEsSearchStrategyProvider( this.initializerContext.config.legacy.globalConfig$, + this.initializerContext.config.get().search, this.logger, usage ) @@ -189,13 +190,20 @@ export class SearchService implements Plugin { // for example use case this.searchAsInternalUser = enhancedEsSearchStrategyProvider( this.initializerContext.config.legacy.globalConfig$, + this.initializerContext.config.get().search, this.logger, usage, true ); - this.registerSearchStrategy(EQL_SEARCH_STRATEGY, eqlSearchStrategyProvider(this.logger)); - this.registerSearchStrategy(SQL_SEARCH_STRATEGY, sqlSearchStrategyProvider(this.logger)); + this.registerSearchStrategy( + EQL_SEARCH_STRATEGY, + eqlSearchStrategyProvider(this.initializerContext.config.get().search, this.logger) + ); + this.registerSearchStrategy( + SQL_SEARCH_STRATEGY, + sqlSearchStrategyProvider(this.initializerContext.config.get().search, this.logger) + ); registerBsearchRoute( bfetch, diff --git a/src/plugins/data/server/search/session/session_service.test.ts b/src/plugins/data/server/search/session/session_service.test.ts index b44b9a08b8d38..38a4f027765df 100644 --- a/src/plugins/data/server/search/session/session_service.test.ts +++ b/src/plugins/data/server/search/session/session_service.test.ts @@ -187,43 +187,12 @@ describe('SearchSessionService', () => { ).rejects.toMatchInlineSnapshot(`[Error: locatorId is required]`); }); - it('saving updates an existing saved object and persists it', async () => { - const mockUpdateSavedObject = { - ...mockSavedObject, - attributes: {}, - }; - savedObjectsClient.get.mockResolvedValue(mockSavedObject); - savedObjectsClient.update.mockResolvedValue(mockUpdateSavedObject); - - await service.save({ savedObjectsClient }, mockUser1, sessionId, { - name: 'banana', - appId: 'nanana', - locatorId: 'panama', - }); - - expect(savedObjectsClient.update).toHaveBeenCalled(); - expect(savedObjectsClient.create).not.toHaveBeenCalled(); - - const [type, id, callAttributes] = savedObjectsClient.update.mock.calls[0]; - expect(type).toBe(SEARCH_SESSION_TYPE); - expect(id).toBe(sessionId); - expect(callAttributes).not.toHaveProperty('idMapping'); - expect(callAttributes).toHaveProperty('name', 'banana'); - expect(callAttributes).toHaveProperty('appId', 'nanana'); - expect(callAttributes).toHaveProperty('locatorId', 'panama'); - expect(callAttributes).toHaveProperty('initialState', {}); - expect(callAttributes).toHaveProperty('restoreState', {}); - }); - - it('saving creates a new persisted saved object, if it did not exist', async () => { + it('saving creates a new persisted saved object', async () => { const mockCreatedSavedObject = { ...mockSavedObject, attributes: {}, }; - savedObjectsClient.update.mockRejectedValue( - SavedObjectsErrorHelpers.createGenericNotFoundError(sessionId) - ); savedObjectsClient.create.mockResolvedValue(mockCreatedSavedObject); await service.save({ savedObjectsClient }, mockUser1, sessionId, { @@ -232,7 +201,7 @@ describe('SearchSessionService', () => { locatorId: 'panama', }); - expect(savedObjectsClient.update).toHaveBeenCalledTimes(1); + expect(savedObjectsClient.update).toHaveBeenCalledTimes(0); expect(savedObjectsClient.create).toHaveBeenCalledTimes(1); const [type, callAttributes, options] = savedObjectsClient.create.mock.calls[0]; @@ -738,147 +707,19 @@ describe('SearchSessionService', () => { }); }); - it('retries updating the saved object if there was a ES conflict 409', async () => { + it('passes retryOnConflict param to es', async () => { const searchRequest = { params: {} }; const searchId = 'FnpFYlBpeXdCUTMyZXhCLTc1TWFKX0EbdDFDTzJzTE1Sck9PVTBIcW1iU05CZzo4MDA0'; - const mockUpdateSavedObject = { - ...mockSavedObject, - attributes: {}, - }; - - let counter = 0; - - savedObjectsClient.update.mockImplementation(() => { - return new Promise((resolve, reject) => { - if (counter === 0) { - counter++; - reject(SavedObjectsErrorHelpers.createConflictError(SEARCH_SESSION_TYPE, searchId)); - } else { - resolve(mockUpdateSavedObject); - } - }); - }); - - await service.trackId({ savedObjectsClient }, mockUser1, searchRequest, searchId, { - sessionId, - strategy: MOCK_STRATEGY, - }); - - expect(savedObjectsClient.update).toHaveBeenCalledTimes(2); - expect(savedObjectsClient.create).not.toHaveBeenCalled(); - }); - - it('retries updating the saved object if theres a ES conflict 409, but stops after MAX_RETRIES times', async () => { - const searchRequest = { params: {} }; - const searchId = 'FnpFYlBpeXdCUTMyZXhCLTc1TWFKX0EbdDFDTzJzTE1Sck9PVTBIcW1iU05CZzo4MDA0'; - - savedObjectsClient.update.mockImplementation(() => { - return new Promise((resolve, reject) => { - reject(SavedObjectsErrorHelpers.createConflictError(SEARCH_SESSION_TYPE, searchId)); - }); - }); - - await service.trackId({ savedObjectsClient }, mockUser1, searchRequest, searchId, { - sessionId, - strategy: MOCK_STRATEGY, - }); - - // Track ID doesn't throw errors even in cases of failure! - expect(savedObjectsClient.update).toHaveBeenCalledTimes(MAX_UPDATE_RETRIES); - expect(savedObjectsClient.create).not.toHaveBeenCalled(); - }); - - it('creates the saved object in non persisted state, if search session doesnt exists', async () => { - const searchRequest = { params: {} }; - const requestHash = createRequestHash(searchRequest.params); - const searchId = 'FnpFYlBpeXdCUTMyZXhCLTc1TWFKX0EbdDFDTzJzTE1Sck9PVTBIcW1iU05CZzo4MDA0'; - - const mockCreatedSavedObject = { - ...mockSavedObject, - attributes: {}, - }; - - savedObjectsClient.update.mockRejectedValue( - SavedObjectsErrorHelpers.createGenericNotFoundError(sessionId) - ); - savedObjectsClient.create.mockResolvedValue(mockCreatedSavedObject); - await service.trackId({ savedObjectsClient }, mockUser1, searchRequest, searchId, { sessionId, strategy: MOCK_STRATEGY, }); expect(savedObjectsClient.update).toHaveBeenCalled(); - expect(savedObjectsClient.create).toHaveBeenCalled(); - - const [type, callAttributes, options] = savedObjectsClient.create.mock.calls[0]; - expect(type).toBe(SEARCH_SESSION_TYPE); - expect(options).toStrictEqual({ id: sessionId }); - expect(callAttributes).toHaveProperty('idMapping', { - [requestHash]: { - id: searchId, - strategy: MOCK_STRATEGY, - }, - }); - expect(callAttributes).toHaveProperty('expires'); - expect(callAttributes).toHaveProperty('created'); - expect(callAttributes).toHaveProperty('sessionId', sessionId); - }); - - it('retries updating if update returned 404 and then update returned conflict 409 (first create race condition)', async () => { - const searchRequest = { params: {} }; - const searchId = 'FnpFYlBpeXdCUTMyZXhCLTc1TWFKX0EbdDFDTzJzTE1Sck9PVTBIcW1iU05CZzo4MDA0'; - - const mockUpdateSavedObject = { - ...mockSavedObject, - attributes: {}, - }; - - let counter = 0; - - savedObjectsClient.update.mockImplementation(() => { - return new Promise((resolve, reject) => { - if (counter === 0) { - counter++; - reject(SavedObjectsErrorHelpers.createGenericNotFoundError(sessionId)); - } else { - resolve(mockUpdateSavedObject); - } - }); - }); - - savedObjectsClient.create.mockRejectedValue( - SavedObjectsErrorHelpers.createConflictError(SEARCH_SESSION_TYPE, searchId) - ); - - await service.trackId({ savedObjectsClient }, mockUser1, searchRequest, searchId, { - sessionId, - strategy: MOCK_STRATEGY, - }); - - expect(savedObjectsClient.update).toHaveBeenCalledTimes(2); - expect(savedObjectsClient.create).toHaveBeenCalledTimes(1); - }); - - it('retries everything at most MAX_RETRIES times', async () => { - const searchRequest = { params: {} }; - const searchId = 'FnpFYlBpeXdCUTMyZXhCLTc1TWFKX0EbdDFDTzJzTE1Sck9PVTBIcW1iU05CZzo4MDA0'; - - savedObjectsClient.update.mockRejectedValue( - SavedObjectsErrorHelpers.createGenericNotFoundError(sessionId) - ); - savedObjectsClient.create.mockRejectedValue( - SavedObjectsErrorHelpers.createConflictError(SEARCH_SESSION_TYPE, searchId) - ); - await service.trackId({ savedObjectsClient }, mockUser1, searchRequest, searchId, { - sessionId, - strategy: MOCK_STRATEGY, - }); - - expect(savedObjectsClient.update).toHaveBeenCalledTimes(MAX_UPDATE_RETRIES); - expect(savedObjectsClient.create).toHaveBeenCalledTimes(MAX_UPDATE_RETRIES); + const [, , , opts] = savedObjectsClient.update.mock.calls[0]; + expect(opts).toHaveProperty('retryOnConflict', MAX_UPDATE_RETRIES); }); it('batches updates for the same session', async () => { @@ -921,7 +762,13 @@ describe('SearchSessionService', () => { expect(savedObjectsClient.update).toHaveBeenCalledTimes(2); // 3 trackIds calls batched into 2 update calls (2 different sessions) expect(savedObjectsClient.create).not.toHaveBeenCalled(); - const [type1, id1, callAttributes1] = savedObjectsClient.update.mock.calls[0]; + const sessionId1UpdateCallArgs = savedObjectsClient.update.mock.calls.find( + (args) => args[1] === sessionId1 + ); + + expect(sessionId1UpdateCallArgs).toBeDefined(); + + const [type1, id1, callAttributes1] = sessionId1UpdateCallArgs!; expect(type1).toBe(SEARCH_SESSION_TYPE); expect(id1).toBe(sessionId1); expect(callAttributes1).toHaveProperty('idMapping', { @@ -935,7 +782,11 @@ describe('SearchSessionService', () => { }, }); - const [type2, id2, callAttributes2] = savedObjectsClient.update.mock.calls[1]; + const sessionId2UpdateCallArgs = savedObjectsClient.update.mock.calls.find( + (args) => args[1] === sessionId2 + ); + expect(sessionId2UpdateCallArgs).toBeDefined(); + const [type2, id2, callAttributes2] = sessionId2UpdateCallArgs!; expect(type2).toBe(SEARCH_SESSION_TYPE); expect(id2).toBe(sessionId2); expect(callAttributes2).toHaveProperty('idMapping', { diff --git a/src/plugins/data/server/search/session/session_service.ts b/src/plugins/data/server/search/session/session_service.ts index d82956d19f73f..d8426c03e91ed 100644 --- a/src/plugins/data/server/search/session/session_service.ts +++ b/src/plugins/data/server/search/session/session_service.ts @@ -7,7 +7,6 @@ */ import { notFound } from '@hapi/boom'; -import { debounce } from 'lodash'; import { fromKueryExpression, nodeBuilder } from '@kbn/es-query'; import { CoreSetup, @@ -16,11 +15,12 @@ import { Logger, SavedObject, SavedObjectsClientContract, - SavedObjectsErrorHelpers, SavedObjectsFindOptions, ElasticsearchClient, } from '@kbn/core/server'; import type { AuthenticatedUser, SecurityPluginSetup } from '@kbn/security-plugin/server'; +import { defer } from '@kbn/kibana-utils-plugin/common'; +import { debounce } from 'lodash'; import { ENHANCED_ES_SEARCH_STRATEGY, IKibanaSearchRequest, @@ -51,24 +51,24 @@ interface SetupDependencies { // eslint-disable-next-line @typescript-eslint/no-empty-interface interface StartDependencies {} -const DEBOUNCE_UPDATE_OR_CREATE_WAIT = 1000; -const DEBOUNCE_UPDATE_OR_CREATE_MAX_WAIT = 5000; - -interface UpdateOrCreateQueueEntry { +/** + * Used to batch requests that add searches into the session saved object + */ +const DEBOUNCE_TRACK_ID_WAIT = 1000; +const DEBOUNCE_TRACK_ID_MAX_WAIT = 5000; +interface TrackIdQueueEntry { deps: SearchSessionDependencies; user: AuthenticatedUser | null; sessionId: string; - attributes: Partial; resolve: () => void; reject: (reason?: unknown) => void; -} -function sleep(ms: number) { - return new Promise((r) => setTimeout(r, ms)); + searchInfo: SearchSessionRequestInfo; + requestHash: string; } + export class SearchSessionService implements ISearchSessionService { private sessionConfig: SearchSessionsConfigSchema; - private readonly updateOrCreateBatchQueue: UpdateOrCreateQueueEntry[] = []; private security?: SecurityPluginSetup; private setupCompleted = false; @@ -93,109 +93,6 @@ export class SearchSessionService implements ISearchSessionService { public stop() {} - private processUpdateOrCreateBatchQueue = debounce( - () => { - const queue = [...this.updateOrCreateBatchQueue]; - if (queue.length === 0) return; - this.updateOrCreateBatchQueue.length = 0; - const batchedSessionAttributes = queue.reduce((res, next) => { - if (!res[next.sessionId]) { - res[next.sessionId] = next.attributes; - } else { - res[next.sessionId] = { - ...res[next.sessionId], - ...next.attributes, - idMapping: { - ...res[next.sessionId].idMapping, - ...next.attributes.idMapping, - }, - }; - } - return res; - }, {} as { [sessionId: string]: Partial }); - - Object.keys(batchedSessionAttributes).forEach((sessionId) => { - const thisSession = queue.filter((s) => s.sessionId === sessionId); - this.updateOrCreate( - thisSession[0].deps, - thisSession[0].user, - sessionId, - batchedSessionAttributes[sessionId] - ) - .then(() => { - thisSession.forEach((s) => s.resolve()); - }) - .catch((e) => { - thisSession.forEach((s) => s.reject(e)); - }); - }); - }, - DEBOUNCE_UPDATE_OR_CREATE_WAIT, - { maxWait: DEBOUNCE_UPDATE_OR_CREATE_MAX_WAIT } - ); - private scheduleUpdateOrCreate = ( - deps: SearchSessionDependencies, - user: AuthenticatedUser | null, - sessionId: string, - attributes: Partial - ): Promise => { - return new Promise((resolve, reject) => { - this.updateOrCreateBatchQueue.push({ deps, user, sessionId, attributes, resolve, reject }); - // TODO: this would be better if we'd debounce per sessionId - this.processUpdateOrCreateBatchQueue(); - }); - }; - - private updateOrCreate = async ( - deps: SearchSessionDependencies, - user: AuthenticatedUser | null, - sessionId: string, - attributes: Partial, - retry: number = 1 - ): Promise | undefined> => { - const retryOnConflict = async (e: any) => { - this.logger.debug(`Conflict error | ${sessionId}`); - // Randomize sleep to spread updates out in case of conflicts - await sleep(100 + Math.random() * 50); - return await this.updateOrCreate(deps, user, sessionId, attributes, retry + 1); - }; - - this.logger.debug(`updateOrCreate | ${sessionId} | ${retry}`); - try { - return (await this.update( - deps, - user, - sessionId, - attributes - )) as SavedObject; - } catch (e) { - if (SavedObjectsErrorHelpers.isNotFoundError(e)) { - try { - this.logger.debug(`Object not found | ${sessionId}`); - return await this.create(deps, user, sessionId, attributes); - } catch (createError) { - if ( - SavedObjectsErrorHelpers.isConflictError(createError) && - retry < this.sessionConfig.maxUpdateRetries - ) { - return await retryOnConflict(createError); - } else { - this.logger.error(createError); - } - } - } else if ( - SavedObjectsErrorHelpers.isConflictError(e) && - retry < this.sessionConfig.maxUpdateRetries - ) { - return await retryOnConflict(e); - } else { - this.logger.error(e); - } - } - - return undefined; - }; - public save = async ( deps: SearchSessionDependencies, user: AuthenticatedUser | null, @@ -213,7 +110,7 @@ export class SearchSessionService implements ISearchSessionService { if (!appId) throw new Error('AppId is required'); if (!locatorId) throw new Error('locatorId is required'); - return this.updateOrCreate(deps, user, sessionId, { + return this.create(deps, user, sessionId, { name, appId, locatorId, @@ -228,7 +125,7 @@ export class SearchSessionService implements ISearchSessionService { sessionId: string, attributes: Partial ) => { - this.logger.debug(`create | ${sessionId}`); + this.logger.debug(`SearchSessionService: create | ${sessionId}`); const realmType = user?.authentication_realm.type; const realmName = user?.authentication_realm.name; @@ -310,10 +207,13 @@ export class SearchSessionService implements ISearchSessionService { return { ...findResponse, - statuses: sessionStatuses.reduce((res, status, index) => { - res[findResponse.saved_objects[index].id] = { status }; - return res; - }, {} as Record), + statuses: sessionStatuses.reduce>( + (res, status, index) => { + res[findResponse.saved_objects[index].id] = { status }; + return res; + }, + {} + ), }; }; @@ -323,7 +223,7 @@ export class SearchSessionService implements ISearchSessionService { sessionId: string, attributes: Partial ) => { - this.logger.debug(`update | ${sessionId}`); + this.logger.debug(`SearchSessionService: update | ${sessionId}`); if (!this.sessionConfig.enabled) throw new Error('Search sessions are disabled'); await this.get(deps, user, sessionId); // Verify correct user return deps.savedObjectsClient.update( @@ -331,7 +231,8 @@ export class SearchSessionService implements ISearchSessionService { sessionId, { ...attributes, - } + }, + { retryOnConflict: this.sessionConfig.maxUpdateRetries } ); }; @@ -341,7 +242,7 @@ export class SearchSessionService implements ISearchSessionService { sessionId: string, expires: Date ) { - this.logger.debug(`extend | ${sessionId}`); + this.logger.debug(`SearchSessionService: extend | ${sessionId}`); return this.update(deps, user, sessionId, { expires: expires.toISOString() }); } @@ -350,7 +251,7 @@ export class SearchSessionService implements ISearchSessionService { user: AuthenticatedUser | null, sessionId: string ) => { - this.logger.debug(`cancel | ${sessionId}`); + this.logger.debug(`SearchSessionService: cancel | ${sessionId}`); return this.update(deps, user, sessionId, { isCanceled: true, }); @@ -362,13 +263,25 @@ export class SearchSessionService implements ISearchSessionService { sessionId: string ) => { if (!this.sessionConfig.enabled) throw new Error('Search sessions are disabled'); - this.logger.debug(`delete | ${sessionId}`); + this.logger.debug(`SearchSessionService: delete | ${sessionId}`); await this.get(deps, user, sessionId); // Verify correct user return deps.savedObjectsClient.delete(SEARCH_SESSION_TYPE, sessionId); }; + /** + * Used to batch requests that add searches into the session saved object + * Requests are grouped and executed per sessionId + * @private + */ + private readonly trackIdBatchQueueMap = new Map< + string /* sessionId */, + { queue: TrackIdQueueEntry[]; scheduleProcessQueue: () => void } + >(); + /** * Tracks the given search request/search ID in the saved session. + * Instead of updating search-session saved object immediately, it debounces and batches updates internally, + * to reduce number of saved object updates and reduce a chance of running over update retries limit * @internal */ public trackId = async ( @@ -380,20 +293,63 @@ export class SearchSessionService implements ISearchSessionService { ) => { const { sessionId, strategy = ENHANCED_ES_SEARCH_STRATEGY } = options; if (!this.sessionConfig.enabled || !sessionId || !searchId) return; - this.logger.debug(`trackId | ${sessionId} | ${searchId}`); + if (!searchRequest.params) return; - let idMapping: Record = {}; + const requestHash = createRequestHash(searchRequest.params); - if (searchRequest.params) { - const requestHash = createRequestHash(searchRequest.params); - const searchInfo: SearchSessionRequestInfo = { - id: searchId, - strategy, - }; - idMapping = { [requestHash]: searchInfo }; + this.logger.debug( + `SearchSessionService: trackId | sessionId: "${sessionId}" | searchId:"${searchId}" | requestHash: "${requestHash}"` + ); + + const searchInfo: SearchSessionRequestInfo = { + id: searchId, + strategy, + }; + + if (!this.trackIdBatchQueueMap.has(sessionId)) { + this.trackIdBatchQueueMap.set(sessionId, { + queue: [], + scheduleProcessQueue: debounce( + () => { + const queue = this.trackIdBatchQueueMap.get(sessionId)?.queue ?? []; + if (queue.length === 0) return; + this.trackIdBatchQueueMap.delete(sessionId); + const batchedIdMapping = queue.reduce( + (res, next) => { + res[next.requestHash] = next.searchInfo; + return res; + }, + {} + ); + this.update(queue[0].deps, queue[0].user, sessionId, { idMapping: batchedIdMapping }) + .then(() => { + queue.forEach((q) => q.resolve()); + }) + .catch((e) => { + queue.forEach((q) => q.reject(e)); + }); + }, + DEBOUNCE_TRACK_ID_WAIT, + { maxWait: DEBOUNCE_TRACK_ID_MAX_WAIT } + ), + }); } - await this.scheduleUpdateOrCreate(deps, user, sessionId, { idMapping }); + const deferred = defer(); + const { queue, scheduleProcessQueue } = this.trackIdBatchQueueMap.get(sessionId)!; + queue.push({ + deps, + sessionId, + searchInfo, + requestHash, + resolve: deferred.resolve, + reject: deferred.reject, + user, + }); + + scheduleProcessQueue(); + + return deferred.promise; }; public async getSearchIdMapping( @@ -415,7 +371,7 @@ export class SearchSessionService implements ISearchSessionService { user: AuthenticatedUser | null, sessionId: string ): Promise { - this.logger.debug(`status | ${sessionId}`); + this.logger.debug(`SearchSessionService: status | ${sessionId}`); const session = await this.get(deps, user, sessionId); const sessionStatus = await getSessionStatus( @@ -451,10 +407,15 @@ export class SearchSessionService implements ISearchSessionService { const session = await this.get(deps, user, sessionId); const requestHash = createRequestHash(searchRequest.params); if (!session.attributes.idMapping.hasOwnProperty(requestHash)) { - this.logger.error(`getId | ${sessionId} | ${requestHash} not found`); + this.logger.error(`SearchSessionService: getId | ${sessionId} | ${requestHash} not found`); + this.logger.debug( + `SearchSessionService: getId not found search with params: ${JSON.stringify( + searchRequest.params + )}` + ); throw new NoSearchIdInSessionError(); } - this.logger.debug(`getId | ${sessionId} | ${requestHash}`); + this.logger.debug(`SearchSessionService: getId | ${sessionId} | ${requestHash}`); return session.attributes.idMapping[requestHash].id; }; diff --git a/src/plugins/data/server/search/session/types.ts b/src/plugins/data/server/search/session/types.ts index 76d5f30028736..88ad5f21e2755 100644 --- a/src/plugins/data/server/search/session/types.ts +++ b/src/plugins/data/server/search/session/types.ts @@ -49,7 +49,7 @@ export interface IScopedSearchSessionsClient { expires: Date ) => Promise>; status: (sessionId: string) => Promise; - getConfig: () => SearchSessionsConfigSchema | null; + getConfig: () => SearchSessionsConfigSchema; } export interface ISearchSessionService { diff --git a/src/plugins/data/server/search/strategies/common/async_utils.test.ts b/src/plugins/data/server/search/strategies/common/async_utils.test.ts index 9771a042f1872..f8cabdae04923 100644 --- a/src/plugins/data/server/search/strategies/common/async_utils.test.ts +++ b/src/plugins/data/server/search/strategies/common/async_utils.test.ts @@ -6,42 +6,39 @@ * Side Public License, v 1. */ -import { getCommonDefaultAsyncSubmitParams, getCommonDefaultAsyncGetParams } from './async_utils'; +import { getCommonDefaultAsyncGetParams, getCommonDefaultAsyncSubmitParams } from './async_utils'; import moment from 'moment'; -import { SearchSessionsConfigSchema } from '../../../../config'; - -const getMockSearchSessionsConfig = ({ - enabled = true, - defaultExpiration = moment.duration(7, 'd'), -} = {}) => - ({ - enabled, - defaultExpiration, - } as SearchSessionsConfigSchema); +import { getMockSearchConfig } from '../../../../config.mock'; describe('request utils', () => { describe('getCommonDefaultAsyncSubmitParams', () => { - test('Uses short `keep_alive` if no `sessionId` is provided', async () => { - const mockConfig = getMockSearchSessionsConfig({ - defaultExpiration: moment.duration(3, 'd'), + test('Uses `keep_alive` from asyncSearch config if no `sessionId` is provided', async () => { + const mockConfig = getMockSearchConfig({ + sessions: { + defaultExpiration: moment.duration(3, 'd'), + }, }); const params = getCommonDefaultAsyncSubmitParams(mockConfig, {}); - expect(params).toHaveProperty('keep_alive', '1m'); + expect(params).toHaveProperty('keep_alive', '60000ms'); }); test('Uses short `keep_alive` if sessions enabled but no yet saved', async () => { - const mockConfig = getMockSearchSessionsConfig({ - defaultExpiration: moment.duration(3, 'd'), + const mockConfig = getMockSearchConfig({ + sessions: { + defaultExpiration: moment.duration(3, 'd'), + }, }); const params = getCommonDefaultAsyncSubmitParams(mockConfig, { sessionId: 'foo', }); - expect(params).toHaveProperty('keep_alive', '1m'); + expect(params).toHaveProperty('keep_alive', '60000ms'); }); test('Uses `keep_alive` from config if sessions enabled and session is saved', async () => { - const mockConfig = getMockSearchSessionsConfig({ - defaultExpiration: moment.duration(3, 'd'), + const mockConfig = getMockSearchConfig({ + sessions: { + defaultExpiration: moment.duration(3, 'd'), + }, }); const params = getCommonDefaultAsyncSubmitParams(mockConfig, { sessionId: 'foo', @@ -50,29 +47,33 @@ describe('request utils', () => { expect(params).toHaveProperty('keep_alive', '259200000ms'); }); - test('Uses `keepAlive` of `1m` if disabled', async () => { - const mockConfig = getMockSearchSessionsConfig({ - defaultExpiration: moment.duration(3, 'd'), - enabled: false, + test('Uses `keepAlive` from asyncSearch config if sessions disabled', async () => { + const mockConfig = getMockSearchConfig({ + sessions: { + defaultExpiration: moment.duration(3, 'd'), + enabled: false, + }, }); const params = getCommonDefaultAsyncSubmitParams(mockConfig, { sessionId: 'foo', }); - expect(params).toHaveProperty('keep_alive', '1m'); + expect(params).toHaveProperty('keep_alive', '60000ms'); }); - test('Uses `keep_on_completion` if enabled', async () => { - const mockConfig = getMockSearchSessionsConfig({}); + test('Uses `keep_on_completion` if sessions enabled', async () => { + const mockConfig = getMockSearchConfig({}); const params = getCommonDefaultAsyncSubmitParams(mockConfig, { sessionId: 'foo', }); expect(params).toHaveProperty('keep_on_completion', true); }); - test('Does not use `keep_on_completion` if disabled', async () => { - const mockConfig = getMockSearchSessionsConfig({ - defaultExpiration: moment.duration(3, 'd'), - enabled: false, + test('Does not use `keep_on_completion` if sessions disabled', async () => { + const mockConfig = getMockSearchConfig({ + sessions: { + defaultExpiration: moment.duration(3, 'd'), + enabled: false, + }, }); const params = getCommonDefaultAsyncSubmitParams(mockConfig, { sessionId: 'foo', @@ -83,36 +84,44 @@ describe('request utils', () => { describe('getCommonDefaultAsyncGetParams', () => { test('Uses `wait_for_completion_timeout`', async () => { - const mockConfig = getMockSearchSessionsConfig({ - defaultExpiration: moment.duration(3, 'd'), - enabled: true, + const mockConfig = getMockSearchConfig({ + sessions: { + defaultExpiration: moment.duration(3, 'd'), + enabled: true, + }, }); const params = getCommonDefaultAsyncGetParams(mockConfig, {}); expect(params).toHaveProperty('wait_for_completion_timeout'); }); test('Uses `keep_alive` if `sessionId` is not provided', async () => { - const mockConfig = getMockSearchSessionsConfig({ - defaultExpiration: moment.duration(3, 'd'), - enabled: true, + const mockConfig = getMockSearchConfig({ + sessions: { + defaultExpiration: moment.duration(3, 'd'), + enabled: true, + }, }); const params = getCommonDefaultAsyncGetParams(mockConfig, {}); - expect(params).toHaveProperty('keep_alive', '1m'); + expect(params).toHaveProperty('keep_alive', '60000ms'); }); - test('Has short `keep_alive` if `sessionId` is provided', async () => { - const mockConfig = getMockSearchSessionsConfig({ - defaultExpiration: moment.duration(3, 'd'), - enabled: true, + test('Has `keep_alive` from asyncSearch config if `sessionId` is provided', async () => { + const mockConfig = getMockSearchConfig({ + sessions: { + defaultExpiration: moment.duration(3, 'd'), + enabled: true, + }, }); const params = getCommonDefaultAsyncGetParams(mockConfig, { sessionId: 'foo' }); - expect(params).toHaveProperty('keep_alive', '1m'); + expect(params).toHaveProperty('keep_alive', '60000ms'); }); test('Has `keep_alive` from config if `sessionId` is provided and session is stored', async () => { - const mockConfig = getMockSearchSessionsConfig({ - defaultExpiration: moment.duration(3, 'd'), - enabled: true, + const mockConfig = getMockSearchConfig({ + sessions: { + defaultExpiration: moment.duration(3, 'd'), + enabled: true, + }, }); const params = getCommonDefaultAsyncGetParams(mockConfig, { sessionId: 'foo', @@ -122,9 +131,11 @@ describe('request utils', () => { }); test("Don't extend keepAlive if search has already been extended", async () => { - const mockConfig = getMockSearchSessionsConfig({ - defaultExpiration: moment.duration(3, 'd'), - enabled: true, + const mockConfig = getMockSearchConfig({ + sessions: { + defaultExpiration: moment.duration(3, 'd'), + enabled: true, + }, }); const params = getCommonDefaultAsyncGetParams(mockConfig, { sessionId: 'foo', @@ -135,9 +146,11 @@ describe('request utils', () => { }); test("Don't extend keepAlive if search is being restored", async () => { - const mockConfig = getMockSearchSessionsConfig({ - defaultExpiration: moment.duration(3, 'd'), - enabled: true, + const mockConfig = getMockSearchConfig({ + sessions: { + defaultExpiration: moment.duration(3, 'd'), + enabled: true, + }, }); const params = getCommonDefaultAsyncGetParams(mockConfig, { sessionId: 'foo', @@ -149,12 +162,68 @@ describe('request utils', () => { }); test('Uses `keep_alive` if `sessionId` is provided but sessions disabled', async () => { - const mockConfig = getMockSearchSessionsConfig({ - defaultExpiration: moment.duration(3, 'd'), - enabled: false, + const mockConfig = getMockSearchConfig({ + sessions: { + defaultExpiration: moment.duration(3, 'd'), + enabled: false, + }, }); const params = getCommonDefaultAsyncGetParams(mockConfig, { sessionId: 'foo' }); - expect(params).toHaveProperty('keep_alive', '1m'); + expect(params).toHaveProperty('keep_alive', '60000ms'); + }); + }); + + describe('overrides: force disable sessions', () => { + test('Does not use `keep_on_completion` if sessions disabled through overrides', async () => { + const mockConfig = getMockSearchConfig({ + sessions: { + defaultExpiration: moment.duration(3, 'd'), + enabled: true, + }, + }); + const params = getCommonDefaultAsyncSubmitParams( + mockConfig, + { + sessionId: 'foo', + }, + { disableSearchSessions: true } + ); + expect(params).toHaveProperty('keep_on_completion', false); + }); + + test('Uses `keepAlive` from asyncSearch config if sessions disabled through overrides', async () => { + const mockConfig = getMockSearchConfig({ + sessions: { + defaultExpiration: moment.duration(3, 'd'), + enabled: true, + }, + }); + const params = getCommonDefaultAsyncSubmitParams( + mockConfig, + { + sessionId: 'foo', + }, + { disableSearchSessions: true } + ); + expect(params).toHaveProperty('keep_alive', '60000ms'); + }); + + test('Uses `keep_alive` from asyncSearch config if sessions disabled through overrides and session is saved', async () => { + const mockConfig = getMockSearchConfig({ + sessions: { + defaultExpiration: moment.duration(3, 'd'), + enabled: true, + }, + }); + const params = getCommonDefaultAsyncSubmitParams( + mockConfig, + { + sessionId: 'foo', + isStored: true, + }, + { disableSearchSessions: true } + ); + expect(params).toHaveProperty('keep_alive', '60000ms'); }); }); }); diff --git a/src/plugins/data/server/search/strategies/common/async_utils.ts b/src/plugins/data/server/search/strategies/common/async_utils.ts index c0af68f915bd8..cbc1e1acd3cd0 100644 --- a/src/plugins/data/server/search/strategies/common/async_utils.ts +++ b/src/plugins/data/server/search/strategies/common/async_utils.ts @@ -10,29 +10,35 @@ import { AsyncSearchSubmitRequest, AsyncSearchGetRequest, } from '@elastic/elasticsearch/lib/api/types'; -import { SearchSessionsConfigSchema } from '../../../../config'; import { ISearchOptions } from '../../../../common'; +import { SearchConfigSchema } from '../../../../config'; /** @internal */ export function getCommonDefaultAsyncSubmitParams( - searchSessionsConfig: SearchSessionsConfigSchema | null, - options: ISearchOptions + config: SearchConfigSchema, + options: ISearchOptions, + /** + * Allows to override some of internal logic (e.g. eql / sql searches don't fully support search sessions yet) + */ + overrides?: { + disableSearchSessions?: true; + } ): Pick< AsyncSearchSubmitRequest, 'keep_alive' | 'wait_for_completion_timeout' | 'keep_on_completion' > { - const useSearchSessions = searchSessionsConfig?.enabled && !!options.sessionId; - + const useSearchSessions = + config.sessions.enabled && !!options.sessionId && !overrides?.disableSearchSessions; const keepAlive = useSearchSessions && options.isStored - ? `${searchSessionsConfig!.defaultExpiration.asMilliseconds()}ms` - : '1m'; + ? `${config.sessions.defaultExpiration.asMilliseconds()}ms` + : `${config.asyncSearch.keepAlive.asMilliseconds()}ms`; return { - // Wait up to 100ms for the response to return - wait_for_completion_timeout: '100ms', + // Wait up to the timeout for the response to return + wait_for_completion_timeout: `${config.asyncSearch.waitForCompletion.asMilliseconds()}ms`, // If search sessions are used, store and get an async ID even for short running requests. keep_on_completion: useSearchSessions, // The initial keepalive is as defined in defaultExpiration if search sessions are used or 1m otherwise. @@ -44,24 +50,31 @@ export function getCommonDefaultAsyncSubmitParams( @internal */ export function getCommonDefaultAsyncGetParams( - searchSessionsConfig: SearchSessionsConfigSchema | null, - options: ISearchOptions + config: SearchConfigSchema, + options: ISearchOptions, + /** + * Allows to override some of internal logic (e.g. eql / sql searches don't fully support search sessions yet) + */ + overrides?: { + disableSearchSessions?: true; + } ): Pick { - const useSearchSessions = searchSessionsConfig?.enabled && !!options.sessionId; + const useSearchSessions = + config.sessions.enabled && !!options.sessionId && !overrides?.disableSearchSessions; return { - // Wait up to 100ms for the response to return - wait_for_completion_timeout: '100ms', + // Wait up to the timeout for the response to return + wait_for_completion_timeout: `${config.asyncSearch.waitForCompletion.asMilliseconds()}ms`, ...(useSearchSessions && options.isStored ? // Use session's keep_alive if search belongs to a stored session options.isSearchStored || options.isRestore // if search was already stored and extended, then no need to extend keepAlive ? {} : { - keep_alive: `${searchSessionsConfig!.defaultExpiration.asMilliseconds()}ms`, + keep_alive: `${config.sessions.defaultExpiration.asMilliseconds()}ms`, } : { // We still need to do polling for searches not within the context of a search session or when search session disabled - keep_alive: '1m', + keep_alive: `${config.asyncSearch.keepAlive.asMilliseconds()}ms`, }), }; } diff --git a/src/plugins/data/server/search/strategies/eql_search/eql_search_strategy.test.ts b/src/plugins/data/server/search/strategies/eql_search/eql_search_strategy.test.ts index 7394f51f861ef..d6015c23058b1 100644 --- a/src/plugins/data/server/search/strategies/eql_search/eql_search_strategy.test.ts +++ b/src/plugins/data/server/search/strategies/eql_search/eql_search_strategy.test.ts @@ -11,6 +11,7 @@ import { eqlSearchStrategyProvider } from './eql_search_strategy'; import { SearchStrategyDependencies } from '../../types'; import { EqlSearchStrategyRequest } from '../../../../common'; import { firstValueFrom } from 'rxjs'; +import { getMockSearchConfig } from '../../../../config.mock'; const getMockEqlResponse = () => ({ body: { @@ -32,6 +33,7 @@ const getMockEqlResponse = () => ({ describe('EQL search strategy', () => { let mockLogger: Logger; + const mockSearchConfig = getMockSearchConfig({}); beforeEach(() => { mockLogger = { debug: jest.fn() } as unknown as Logger; @@ -39,12 +41,12 @@ describe('EQL search strategy', () => { describe('strategy interface', () => { it('returns a strategy with a `search` function', async () => { - const eqlSearch = await eqlSearchStrategyProvider(mockLogger); + const eqlSearch = await eqlSearchStrategyProvider(mockSearchConfig, mockLogger); expect(typeof eqlSearch.search).toBe('function'); }); it('returns a strategy with a `cancel` function', async () => { - const eqlSearch = await eqlSearchStrategyProvider(mockLogger); + const eqlSearch = await eqlSearchStrategyProvider(mockSearchConfig, mockLogger); expect(typeof eqlSearch.cancel).toBe('function'); }); }); @@ -81,7 +83,7 @@ describe('EQL search strategy', () => { describe('async functionality', () => { it('performs an eql client search with params when no ID is provided', async () => { - const eqlSearch = await eqlSearchStrategyProvider(mockLogger); + const eqlSearch = await eqlSearchStrategyProvider(mockSearchConfig, mockLogger); await eqlSearch.search({ options, params }, {}, mockDeps).toPromise(); const [[request, requestOptions]] = mockEqlSearch.mock.calls; @@ -89,7 +91,7 @@ describe('EQL search strategy', () => { body: { query: 'process where 1 == 1' }, ignore_unavailable: true, index: 'logstash-*', - keep_alive: '1m', + keep_alive: '60000ms', max_concurrent_shard_requests: undefined, wait_for_completion_timeout: '100ms', }); @@ -97,14 +99,14 @@ describe('EQL search strategy', () => { }); it('retrieves the current request if an id is provided', async () => { - const eqlSearch = await eqlSearchStrategyProvider(mockLogger); + const eqlSearch = await eqlSearchStrategyProvider(mockSearchConfig, mockLogger); await eqlSearch.search({ id: 'my-search-id' }, {}, mockDeps).toPromise(); const [[requestParams]] = mockEqlGet.mock.calls; expect(mockEqlSearch).not.toHaveBeenCalled(); expect(requestParams).toEqual({ id: 'my-search-id', - keep_alive: '1m', + keep_alive: '60000ms', wait_for_completion_timeout: '100ms', }); }); @@ -112,7 +114,7 @@ describe('EQL search strategy', () => { it('emits an error if the client throws', async () => { expect.assertions(1); mockEqlSearch.mockReset().mockRejectedValueOnce(new Error('client error')); - const eqlSearch = await eqlSearchStrategyProvider(mockLogger); + const eqlSearch = await eqlSearchStrategyProvider(mockSearchConfig, mockLogger); eqlSearch.search({ options, params }, {}, mockDeps).subscribe( () => {}, (err) => { @@ -124,7 +126,7 @@ describe('EQL search strategy', () => { describe('arguments', () => { it('sends along async search options', async () => { - const eqlSearch = await eqlSearchStrategyProvider(mockLogger); + const eqlSearch = await eqlSearchStrategyProvider(mockSearchConfig, mockLogger); await eqlSearch.search({ options, params }, {}, mockDeps).toPromise(); const [[request]] = mockEqlSearch.mock.calls; @@ -136,7 +138,7 @@ describe('EQL search strategy', () => { }); it('sends along default search parameters', async () => { - const eqlSearch = await eqlSearchStrategyProvider(mockLogger); + const eqlSearch = await eqlSearchStrategyProvider(mockSearchConfig, mockLogger); await eqlSearch.search({ options, params }, {}, mockDeps).toPromise(); const [[request]] = mockEqlSearch.mock.calls; @@ -148,7 +150,7 @@ describe('EQL search strategy', () => { }); it('allows search parameters to be overridden', async () => { - const eqlSearch = await eqlSearchStrategyProvider(mockLogger); + const eqlSearch = await eqlSearchStrategyProvider(mockSearchConfig, mockLogger); await eqlSearch .search( { @@ -174,7 +176,7 @@ describe('EQL search strategy', () => { }); it('allows search options to be overridden', async () => { - const eqlSearch = await eqlSearchStrategyProvider(mockLogger); + const eqlSearch = await eqlSearchStrategyProvider(mockSearchConfig, mockLogger); await eqlSearch .search( { @@ -196,7 +198,7 @@ describe('EQL search strategy', () => { }); it('passes (deprecated) transport options for an existing request', async () => { - const eqlSearch = await eqlSearchStrategyProvider(mockLogger); + const eqlSearch = await eqlSearchStrategyProvider(mockSearchConfig, mockLogger); await eqlSearch .search({ id: 'my-search-id', options: { ignore: [400] } }, {}, mockDeps) .toPromise(); @@ -207,7 +209,7 @@ describe('EQL search strategy', () => { }); it('passes abort signal', async () => { - const eqlSearch = eqlSearchStrategyProvider(mockLogger); + const eqlSearch = eqlSearchStrategyProvider(mockSearchConfig, mockLogger); const eql: EqlSearchStrategyRequest = { id: 'my-search-id' }; const abortController = new AbortController(); await firstValueFrom( @@ -219,7 +221,7 @@ describe('EQL search strategy', () => { }); it('passes transport options for search with id', async () => { - const eqlSearch = eqlSearchStrategyProvider(mockLogger); + const eqlSearch = eqlSearchStrategyProvider(mockSearchConfig, mockLogger); const eql: EqlSearchStrategyRequest = { id: 'my-search-id' }; await firstValueFrom( eqlSearch.search(eql, { transport: { maxResponseSize: 13131313 } }, mockDeps) @@ -234,7 +236,7 @@ describe('EQL search strategy', () => { }); it('passes transport options for search without id', async () => { - const eqlSearch = eqlSearchStrategyProvider(mockLogger); + const eqlSearch = eqlSearchStrategyProvider(mockSearchConfig, mockLogger); const eql: EqlSearchStrategyRequest = { params: { index: 'all' } }; await firstValueFrom(eqlSearch.search(eql, { transport: { ignore: [400] } }, mockDeps)); const [[_params, requestOptions]] = mockEqlSearch.mock.calls; @@ -245,7 +247,7 @@ describe('EQL search strategy', () => { describe('response', () => { it('contains a rawResponse field containing the full search response', async () => { - const eqlSearch = await eqlSearchStrategyProvider(mockLogger); + const eqlSearch = await eqlSearchStrategyProvider(mockSearchConfig, mockLogger); const response = await eqlSearch .search({ id: 'my-search-id', options: { ignore: [400] } }, {}, mockDeps) .toPromise(); diff --git a/src/plugins/data/server/search/strategies/eql_search/eql_search_strategy.ts b/src/plugins/data/server/search/strategies/eql_search/eql_search_strategy.ts index aab1341f9dbfa..14b5c76c67f46 100644 --- a/src/plugins/data/server/search/strategies/eql_search/eql_search_strategy.ts +++ b/src/plugins/data/server/search/strategies/eql_search/eql_search_strategy.ts @@ -9,6 +9,7 @@ import type { TransportResult } from '@elastic/elasticsearch'; import { tap } from 'rxjs/operators'; import type { IScopedClusterClient, Logger } from '@kbn/core/server'; +import { SearchConfigSchema } from '../../../../config'; import { EqlSearchStrategyRequest, EqlSearchStrategyResponse, @@ -23,6 +24,7 @@ import { getIgnoreThrottled } from '../ese_search/request_utils'; import { getCommonDefaultAsyncGetParams } from '../common/async_utils'; export const eqlSearchStrategyProvider = ( + searchConfig: SearchConfigSchema, logger: Logger ): ISearchStrategy => { async function cancelAsyncSearch(id: string, esClient: IScopedClusterClient) { @@ -46,11 +48,15 @@ export const eqlSearchStrategyProvider = ( uiSettingsClient ); const params = id - ? getCommonDefaultAsyncGetParams(null, options) + ? getCommonDefaultAsyncGetParams(searchConfig, options, { + /* disable until full eql support */ disableSearchSessions: true, + }) : { ...(await getIgnoreThrottled(uiSettingsClient)), ...defaultParams, - ...getCommonDefaultAsyncGetParams(null, options), + ...getCommonDefaultAsyncGetParams(searchConfig, options, { + /* disable until full eql support */ disableSearchSessions: true, + }), ...request.params, }; const response = id diff --git a/src/plugins/data/server/search/strategies/ese_search/ese_search_strategy.test.ts b/src/plugins/data/server/search/strategies/ese_search/ese_search_strategy.test.ts index c2c42f1ff8963..070d07c07c956 100644 --- a/src/plugins/data/server/search/strategies/ese_search/ese_search_strategy.test.ts +++ b/src/plugins/data/server/search/strategies/ese_search/ese_search_strategy.test.ts @@ -14,6 +14,7 @@ import * as xContentParseException from '../../../../common/search/test_data/x_c import { SearchStrategyDependencies } from '../../types'; import { enhancedEsSearchStrategyProvider } from './ese_search_strategy'; import { createSearchSessionsClientMock } from '../../mocks'; +import { getMockSearchConfig } from '../../../../config.mock'; const mockAsyncResponse = { body: { @@ -74,6 +75,8 @@ describe('ES search strategy', () => { }, }); + const mockSearchConfig = getMockSearchConfig({}); + beforeEach(() => { mockApiCaller.mockClear(); mockGetCaller.mockClear(); @@ -82,7 +85,11 @@ describe('ES search strategy', () => { }); it('returns a strategy with `search and `cancel`', async () => { - const esSearch = await enhancedEsSearchStrategyProvider(mockLegacyConfig$, mockLogger); + const esSearch = await enhancedEsSearchStrategyProvider( + mockLegacyConfig$, + mockSearchConfig, + mockLogger + ); expect(typeof esSearch.search).toBe('function'); }); @@ -93,7 +100,11 @@ describe('ES search strategy', () => { mockSubmitCaller.mockResolvedValueOnce(mockAsyncResponse); const params = { index: 'logstash-*', body: { query: {} } }; - const esSearch = await enhancedEsSearchStrategyProvider(mockLegacyConfig$, mockLogger); + const esSearch = await enhancedEsSearchStrategyProvider( + mockLegacyConfig$, + mockSearchConfig, + mockLogger + ); await esSearch.search({ params }, {}, mockDeps).toPromise(); @@ -101,14 +112,18 @@ describe('ES search strategy', () => { const request = mockSubmitCaller.mock.calls[0][0]; expect(request.index).toEqual(params.index); expect(request.body).toEqual(params.body); - expect(request).toHaveProperty('keep_alive', '1m'); + expect(request).toHaveProperty('keep_alive', '60000ms'); }); it('makes a GET request to async search with ID', async () => { mockGetCaller.mockResolvedValueOnce(mockAsyncResponse); const params = { index: 'logstash-*', body: { query: {} } }; - const esSearch = await enhancedEsSearchStrategyProvider(mockLegacyConfig$, mockLogger); + const esSearch = await enhancedEsSearchStrategyProvider( + mockLegacyConfig$, + mockSearchConfig, + mockLogger + ); await esSearch.search({ id: 'foo', params }, {}, mockDeps).toPromise(); @@ -116,14 +131,18 @@ describe('ES search strategy', () => { const request = mockGetCaller.mock.calls[0][0]; expect(request.id).toEqual('foo'); expect(request).toHaveProperty('wait_for_completion_timeout'); - expect(request).toHaveProperty('keep_alive', '1m'); + expect(request).toHaveProperty('keep_alive', '60000ms'); }); it('sets transport options on POST requests', async () => { const transportOptions = { maxRetries: 1 }; mockSubmitCaller.mockResolvedValueOnce(mockAsyncResponse); const params = { index: 'logstash-*', body: { query: {} } }; - const esSearch = enhancedEsSearchStrategyProvider(mockLegacyConfig$, mockLogger); + const esSearch = enhancedEsSearchStrategyProvider( + mockLegacyConfig$, + mockSearchConfig, + mockLogger + ); await firstValueFrom( esSearch.search({ params }, { transport: transportOptions }, mockDeps) @@ -136,7 +155,7 @@ describe('ES search strategy', () => { body: { query: {} }, ignore_unavailable: true, index: 'logstash-*', - keep_alive: '1m', + keep_alive: '60000ms', keep_on_completion: false, max_concurrent_shard_requests: undefined, track_total_hits: true, @@ -149,7 +168,11 @@ describe('ES search strategy', () => { it('sets transport options on GET requests', async () => { mockGetCaller.mockResolvedValueOnce(mockAsyncResponse); const params = { index: 'logstash-*', body: { query: {} } }; - const esSearch = enhancedEsSearchStrategyProvider(mockLegacyConfig$, mockLogger); + const esSearch = enhancedEsSearchStrategyProvider( + mockLegacyConfig$, + mockSearchConfig, + mockLogger + ); await firstValueFrom( esSearch.search({ id: 'foo', params }, { transport: { maxRetries: 1 } }, mockDeps) @@ -159,7 +182,7 @@ describe('ES search strategy', () => { 1, expect.objectContaining({ id: 'foo', - keep_alive: '1m', + keep_alive: '60000ms', wait_for_completion_timeout: '100ms', }), expect.objectContaining({ maxRetries: 1, meta: true, signal: undefined }) @@ -170,7 +193,11 @@ describe('ES search strategy', () => { mockSubmitCaller.mockResolvedValueOnce(mockAsyncResponse); const params = { index: 'foo-*', body: {} }; - const esSearch = await enhancedEsSearchStrategyProvider(mockLegacyConfig$, mockLogger); + const esSearch = await enhancedEsSearchStrategyProvider( + mockLegacyConfig$, + mockSearchConfig, + mockLogger + ); await esSearch.search({ params }, {}, mockDeps).toPromise(); @@ -184,7 +211,11 @@ describe('ES search strategy', () => { mockApiCaller.mockResolvedValueOnce(mockRollupResponse); const params = { index: 'foo-程', body: {} }; - const esSearch = await enhancedEsSearchStrategyProvider(mockLegacyConfig$, mockLogger); + const esSearch = await enhancedEsSearchStrategyProvider( + mockLegacyConfig$, + mockSearchConfig, + mockLogger + ); await esSearch .search( @@ -209,7 +240,11 @@ describe('ES search strategy', () => { mockSubmitCaller.mockResolvedValueOnce(mockAsyncResponse); const params = { index: 'logstash-*', body: { query: {} } }; - const esSearch = await enhancedEsSearchStrategyProvider(mockLegacyConfig$, mockLogger); + const esSearch = await enhancedEsSearchStrategyProvider( + mockLegacyConfig$, + mockSearchConfig, + mockLogger + ); await esSearch.search({ params }, { sessionId: '1' }, mockDeps).toPromise(); @@ -218,14 +253,18 @@ describe('ES search strategy', () => { expect(request.index).toEqual(params.index); expect(request.body).toEqual(params.body); - expect(request).toHaveProperty('keep_alive', '1m'); + expect(request).toHaveProperty('keep_alive', '60000ms'); }); it('Submit search with session id and session is saved creates a search with long keep_alive', async () => { mockSubmitCaller.mockResolvedValueOnce(mockAsyncResponse); const params = { index: 'logstash-*', body: { query: {} } }; - const esSearch = await enhancedEsSearchStrategyProvider(mockLegacyConfig$, mockLogger); + const esSearch = await enhancedEsSearchStrategyProvider( + mockLegacyConfig$, + mockSearchConfig, + mockLogger + ); await esSearch.search({ params }, { sessionId: '1', isStored: true }, mockDeps).toPromise(); @@ -241,7 +280,11 @@ describe('ES search strategy', () => { mockGetCaller.mockResolvedValueOnce(mockAsyncResponse); const params = { index: 'logstash-*', body: { query: {} } }; - const esSearch = await enhancedEsSearchStrategyProvider(mockLegacyConfig$, mockLogger); + const esSearch = await enhancedEsSearchStrategyProvider( + mockLegacyConfig$, + mockSearchConfig, + mockLogger + ); await esSearch.search({ id: 'foo', params }, { sessionId: '1' }, mockDeps).toPromise(); @@ -249,14 +292,18 @@ describe('ES search strategy', () => { const request = mockGetCaller.mock.calls[0][0]; expect(request.id).toEqual('foo'); expect(request).toHaveProperty('wait_for_completion_timeout'); - expect(request).toHaveProperty('keep_alive', '1m'); + expect(request).toHaveProperty('keep_alive', '60000ms'); }); it('makes a GET request to async search with long keepalive, if session is saved', async () => { mockGetCaller.mockResolvedValueOnce(mockAsyncResponse); const params = { index: 'logstash-*', body: { query: {} } }; - const esSearch = await enhancedEsSearchStrategyProvider(mockLegacyConfig$, mockLogger); + const esSearch = await enhancedEsSearchStrategyProvider( + mockLegacyConfig$, + mockSearchConfig, + mockLogger + ); await esSearch .search({ id: 'foo', params }, { sessionId: '1', isStored: true }, mockDeps) @@ -273,7 +320,11 @@ describe('ES search strategy', () => { mockGetCaller.mockResolvedValueOnce(mockAsyncResponse); const params = { index: 'logstash-*', body: { query: {} } }; - const esSearch = await enhancedEsSearchStrategyProvider(mockLegacyConfig$, mockLogger); + const esSearch = await enhancedEsSearchStrategyProvider( + mockLegacyConfig$, + mockSearchConfig, + mockLogger + ); await esSearch .search( @@ -303,7 +354,11 @@ describe('ES search strategy', () => { mockSubmitCaller.mockRejectedValue(errResponse); const params = { index: 'logstash-*', body: { query: {} } }; - const esSearch = await enhancedEsSearchStrategyProvider(mockLegacyConfig$, mockLogger); + const esSearch = await enhancedEsSearchStrategyProvider( + mockLegacyConfig$, + mockSearchConfig, + mockLogger + ); let err: KbnServerError | undefined; try { @@ -324,7 +379,11 @@ describe('ES search strategy', () => { mockSubmitCaller.mockRejectedValue(errResponse); const params = { index: 'logstash-*', body: { query: {} } }; - const esSearch = await enhancedEsSearchStrategyProvider(mockLegacyConfig$, mockLogger); + const esSearch = await enhancedEsSearchStrategyProvider( + mockLegacyConfig$, + mockSearchConfig, + mockLogger + ); let err: KbnServerError | undefined; try { @@ -345,7 +404,11 @@ describe('ES search strategy', () => { mockDeleteCaller.mockResolvedValueOnce(200); const id = 'some_id'; - const esSearch = await enhancedEsSearchStrategyProvider(mockLegacyConfig$, mockLogger); + const esSearch = await enhancedEsSearchStrategyProvider( + mockLegacyConfig$, + mockSearchConfig, + mockLogger + ); await esSearch.cancel!(id, {}, mockDeps); @@ -365,7 +428,11 @@ describe('ES search strategy', () => { mockDeleteCaller.mockRejectedValue(errResponse); const id = 'some_id'; - const esSearch = await enhancedEsSearchStrategyProvider(mockLegacyConfig$, mockLogger); + const esSearch = await enhancedEsSearchStrategyProvider( + mockLegacyConfig$, + mockSearchConfig, + mockLogger + ); let err: KbnServerError | undefined; try { @@ -388,7 +455,11 @@ describe('ES search strategy', () => { const id = 'some_other_id'; const keepAlive = '1d'; - const esSearch = await enhancedEsSearchStrategyProvider(mockLegacyConfig$, mockLogger); + const esSearch = await enhancedEsSearchStrategyProvider( + mockLegacyConfig$, + mockSearchConfig, + mockLogger + ); await esSearch.extend!(id, keepAlive, {}, mockDeps); @@ -403,7 +474,11 @@ describe('ES search strategy', () => { const id = 'some_other_id'; const keepAlive = '1d'; - const esSearch = await enhancedEsSearchStrategyProvider(mockLegacyConfig$, mockLogger); + const esSearch = await enhancedEsSearchStrategyProvider( + mockLegacyConfig$, + mockSearchConfig, + mockLogger + ); let err: KbnServerError | undefined; try { diff --git a/src/plugins/data/server/search/strategies/ese_search/ese_search_strategy.ts b/src/plugins/data/server/search/strategies/ese_search/ese_search_strategy.ts index 33234d7c65730..3c9d6a40c58c1 100644 --- a/src/plugins/data/server/search/strategies/ese_search/ese_search_strategy.ts +++ b/src/plugins/data/server/search/strategies/ese_search/ese_search_strategy.ts @@ -33,9 +33,11 @@ import { getTotalLoaded, shimHitsTotal, } from '../es_search'; +import { SearchConfigSchema } from '../../../../config'; export const enhancedEsSearchStrategyProvider = ( legacyConfig$: Observable, + searchConfig: SearchConfigSchema, logger: Logger, usage?: SearchUsage, useInternalUser: boolean = false @@ -52,19 +54,15 @@ export const enhancedEsSearchStrategyProvider = ( function asyncSearch( { id, ...request }: IEsSearchRequest, options: IAsyncSearchOptions, - { esClient, uiSettingsClient, searchSessionsClient }: SearchStrategyDependencies + { esClient, uiSettingsClient }: SearchStrategyDependencies ) { const client = useInternalUser ? esClient.asInternalUser : esClient.asCurrentUser; const search = async () => { const params = id - ? getDefaultAsyncGetParams(searchSessionsClient.getConfig(), options) + ? getDefaultAsyncGetParams(searchConfig, options) : { - ...(await getDefaultAsyncSubmitParams( - uiSettingsClient, - searchSessionsClient.getConfig(), - options - )), + ...(await getDefaultAsyncSubmitParams(uiSettingsClient, searchConfig, options)), ...request.params, }; const { body, headers } = id diff --git a/src/plugins/data/server/search/strategies/ese_search/request_utils.test.ts b/src/plugins/data/server/search/strategies/ese_search/request_utils.test.ts index b908a1df4f0ec..e14be555535d3 100644 --- a/src/plugins/data/server/search/strategies/ese_search/request_utils.test.ts +++ b/src/plugins/data/server/search/strategies/ese_search/request_utils.test.ts @@ -14,21 +14,12 @@ import { import { IUiSettingsClient } from '@kbn/core/server'; import { UI_SETTINGS } from '../../../../common'; import moment from 'moment'; -import { SearchSessionsConfigSchema } from '../../../../config'; +import { getMockSearchConfig } from '../../../../config.mock'; const getMockUiSettingsClient = (config: Record) => { return { get: async (key: string) => config[key] } as IUiSettingsClient; }; -const getMockSearchSessionsConfig = ({ - enabled = true, - defaultExpiration = moment.duration(7, 'd'), -} = {}) => - ({ - enabled, - defaultExpiration, - } as SearchSessionsConfigSchema); - describe('request utils', () => { describe('getIgnoreThrottled', () => { test('does not return `ignore_throttled` when `includeFrozen` is `false`', async () => { @@ -53,19 +44,23 @@ describe('request utils', () => { const mockUiSettingsClient = getMockUiSettingsClient({ [UI_SETTINGS.SEARCH_INCLUDE_FROZEN]: false, }); - const mockConfig = getMockSearchSessionsConfig({ - defaultExpiration: moment.duration(3, 'd'), + const mockConfig = getMockSearchConfig({ + sessions: { + defaultExpiration: moment.duration(3, 'd'), + }, }); const params = await getDefaultAsyncSubmitParams(mockUiSettingsClient, mockConfig, {}); - expect(params).toHaveProperty('keep_alive', '1m'); + expect(params).toHaveProperty('keep_alive', '60000ms'); }); test('Uses `keep_alive` from config if enabled and session is stored', async () => { const mockUiSettingsClient = getMockUiSettingsClient({ [UI_SETTINGS.SEARCH_INCLUDE_FROZEN]: false, }); - const mockConfig = getMockSearchSessionsConfig({ - defaultExpiration: moment.duration(3, 'd'), + const mockConfig = getMockSearchConfig({ + sessions: { + defaultExpiration: moment.duration(3, 'd'), + }, }); const params = await getDefaultAsyncSubmitParams(mockUiSettingsClient, mockConfig, { sessionId: 'foo', @@ -78,21 +73,23 @@ describe('request utils', () => { const mockUiSettingsClient = getMockUiSettingsClient({ [UI_SETTINGS.SEARCH_INCLUDE_FROZEN]: false, }); - const mockConfig = getMockSearchSessionsConfig({ - defaultExpiration: moment.duration(3, 'd'), - enabled: false, + const mockConfig = getMockSearchConfig({ + sessions: { + defaultExpiration: moment.duration(3, 'd'), + enabled: false, + }, }); const params = await getDefaultAsyncSubmitParams(mockUiSettingsClient, mockConfig, { sessionId: 'foo', }); - expect(params).toHaveProperty('keep_alive', '1m'); + expect(params).toHaveProperty('keep_alive', '60000ms'); }); test('Uses `keep_on_completion` if enabled', async () => { const mockUiSettingsClient = getMockUiSettingsClient({ [UI_SETTINGS.SEARCH_INCLUDE_FROZEN]: false, }); - const mockConfig = getMockSearchSessionsConfig({}); + const mockConfig = getMockSearchConfig({}); const params = await getDefaultAsyncSubmitParams(mockUiSettingsClient, mockConfig, { sessionId: 'foo', }); @@ -103,9 +100,11 @@ describe('request utils', () => { const mockUiSettingsClient = getMockUiSettingsClient({ [UI_SETTINGS.SEARCH_INCLUDE_FROZEN]: false, }); - const mockConfig = getMockSearchSessionsConfig({ - defaultExpiration: moment.duration(3, 'd'), - enabled: false, + const mockConfig = getMockSearchConfig({ + sessions: { + defaultExpiration: moment.duration(3, 'd'), + enabled: false, + }, }); const params = await getDefaultAsyncSubmitParams(mockUiSettingsClient, mockConfig, { sessionId: 'foo', @@ -116,27 +115,33 @@ describe('request utils', () => { describe('getDefaultAsyncGetParams', () => { test('Uses `wait_for_completion_timeout`', async () => { - const mockConfig = getMockSearchSessionsConfig({ - defaultExpiration: moment.duration(3, 'd'), - enabled: true, + const mockConfig = getMockSearchConfig({ + sessions: { + defaultExpiration: moment.duration(3, 'd'), + enabled: true, + }, }); const params = getDefaultAsyncGetParams(mockConfig, {}); expect(params).toHaveProperty('wait_for_completion_timeout'); }); test('Uses `keep_alive` if `sessionId` is not provided', async () => { - const mockConfig = getMockSearchSessionsConfig({ - defaultExpiration: moment.duration(3, 'd'), - enabled: true, + const mockConfig = getMockSearchConfig({ + sessions: { + defaultExpiration: moment.duration(3, 'd'), + enabled: true, + }, }); const params = getDefaultAsyncGetParams(mockConfig, {}); - expect(params).toHaveProperty('keep_alive', '1m'); + expect(params).toHaveProperty('keep_alive', '60000ms'); }); test('Has no `keep_alive` if `sessionId` is provided and search already stored', async () => { - const mockConfig = getMockSearchSessionsConfig({ - defaultExpiration: moment.duration(3, 'd'), - enabled: true, + const mockConfig = getMockSearchConfig({ + sessions: { + defaultExpiration: moment.duration(3, 'd'), + enabled: true, + }, }); const params = getDefaultAsyncGetParams(mockConfig, { sessionId: 'foo', @@ -147,12 +152,14 @@ describe('request utils', () => { }); test('Uses `keep_alive` if `sessionId` is provided but sessions disabled', async () => { - const mockConfig = getMockSearchSessionsConfig({ - defaultExpiration: moment.duration(3, 'd'), - enabled: false, + const mockConfig = getMockSearchConfig({ + sessions: { + defaultExpiration: moment.duration(3, 'd'), + enabled: false, + }, }); const params = getDefaultAsyncGetParams(mockConfig, { sessionId: 'foo' }); - expect(params).toHaveProperty('keep_alive', '1m'); + expect(params).toHaveProperty('keep_alive', '60000ms'); }); }); }); diff --git a/src/plugins/data/server/search/strategies/ese_search/request_utils.ts b/src/plugins/data/server/search/strategies/ese_search/request_utils.ts index 07f1c9d1ae9a5..e9bd7a54c0071 100644 --- a/src/plugins/data/server/search/strategies/ese_search/request_utils.ts +++ b/src/plugins/data/server/search/strategies/ese_search/request_utils.ts @@ -11,7 +11,7 @@ import { AsyncSearchGetRequest } from '@elastic/elasticsearch/lib/api/typesWithB import { AsyncSearchSubmitRequest } from '@elastic/elasticsearch/lib/api/types'; import { ISearchOptions, UI_SETTINGS } from '../../../../common'; import { getDefaultSearchParams } from '../es_search'; -import { SearchSessionsConfigSchema } from '../../../../config'; +import { SearchConfigSchema } from '../../../../config'; import { getCommonDefaultAsyncGetParams, getCommonDefaultAsyncSubmitParams, @@ -32,7 +32,7 @@ export async function getIgnoreThrottled( */ export async function getDefaultAsyncSubmitParams( uiSettingsClient: Pick, - searchSessionsConfig: SearchSessionsConfigSchema | null, + searchConfig: SearchConfigSchema, options: ISearchOptions ): Promise< Pick< @@ -49,11 +49,10 @@ export async function getDefaultAsyncSubmitParams( > { return { // TODO: adjust for partial results - batched_reduce_size: 64, - ...getCommonDefaultAsyncSubmitParams(searchSessionsConfig, options), + batched_reduce_size: searchConfig.asyncSearch.batchedReduceSize, + ...getCommonDefaultAsyncSubmitParams(searchConfig, options), ...(await getIgnoreThrottled(uiSettingsClient)), ...(await getDefaultSearchParams(uiSettingsClient)), - // If search sessions are used, set the initial expiration time. }; } @@ -61,10 +60,10 @@ export async function getDefaultAsyncSubmitParams( @internal */ export function getDefaultAsyncGetParams( - searchSessionsConfig: SearchSessionsConfigSchema | null, + searchConfig: SearchConfigSchema, options: ISearchOptions ): Pick { return { - ...getCommonDefaultAsyncGetParams(searchSessionsConfig, options), + ...getCommonDefaultAsyncGetParams(searchConfig, options), }; } diff --git a/src/plugins/data/server/search/strategies/sql_search/request_utils.test.ts b/src/plugins/data/server/search/strategies/sql_search/request_utils.test.ts index d37bcfb0655f8..f21b766db3e1d 100644 --- a/src/plugins/data/server/search/strategies/sql_search/request_utils.test.ts +++ b/src/plugins/data/server/search/strategies/sql_search/request_utils.test.ts @@ -8,30 +8,26 @@ import { getDefaultAsyncSubmitParams, getDefaultAsyncGetParams } from './request_utils'; import moment from 'moment'; -import { SearchSessionsConfigSchema } from '../../../../config'; - -const getMockSearchSessionsConfig = ({ - enabled = true, - defaultExpiration = moment.duration(7, 'd'), -} = {}) => - ({ - enabled, - defaultExpiration, - } as SearchSessionsConfigSchema); +import { getMockSearchConfig } from '../../../../config.mock'; describe('request utils', () => { describe('getDefaultAsyncSubmitParams', () => { test('Uses `keep_alive` from default params if no `sessionId` is provided', async () => { - const mockConfig = getMockSearchSessionsConfig({ - defaultExpiration: moment.duration(3, 'd'), + const mockConfig = getMockSearchConfig({ + sessions: { + defaultExpiration: moment.duration(3, 'd'), + }, }); const params = getDefaultAsyncSubmitParams(mockConfig, {}); - expect(params).toHaveProperty('keep_alive', '1m'); + expect(params).toHaveProperty('keep_alive', '60000ms'); }); - test('Uses `keep_alive` from config if enabled and session is stored', async () => { - const mockConfig = getMockSearchSessionsConfig({ - defaultExpiration: moment.duration(3, 'd'), + // unskip when SQL has full session support https://github.com/elastic/kibana/issues/127880 + test.skip('Uses `keep_alive` from config if enabled and session is stored', async () => { + const mockConfig = getMockSearchConfig({ + sessions: { + defaultExpiration: moment.duration(3, 'd'), + }, }); const params = getDefaultAsyncSubmitParams(mockConfig, { sessionId: 'foo', @@ -40,29 +36,57 @@ describe('request utils', () => { expect(params).toHaveProperty('keep_alive', '259200000ms'); }); + // remove when SQL has full session support https://github.com/elastic/kibana/issues/127880 + test('Uses `keep_alive` from asyncSearch config if sessions enabled and session is stored', async () => { + const mockConfig = getMockSearchConfig({ + sessions: { + defaultExpiration: moment.duration(3, 'd'), + }, + }); + const params = getDefaultAsyncSubmitParams(mockConfig, { + sessionId: 'foo', + isStored: true, + }); + expect(params).toHaveProperty('keep_alive', '60000ms'); + }); + test('Uses `keepAlive` of `1m` if disabled', async () => { - const mockConfig = getMockSearchSessionsConfig({ - defaultExpiration: moment.duration(3, 'd'), - enabled: false, + const mockConfig = getMockSearchConfig({ + sessions: { + defaultExpiration: moment.duration(3, 'd'), + enabled: false, + }, }); const params = getDefaultAsyncSubmitParams(mockConfig, { sessionId: 'foo', }); - expect(params).toHaveProperty('keep_alive', '1m'); + expect(params).toHaveProperty('keep_alive', '60000ms'); }); - test('Uses `keep_on_completion` if enabled', async () => { - const mockConfig = getMockSearchSessionsConfig({}); + // unskip when SQL has full session support https://github.com/elastic/kibana/issues/127880 + test.skip('Uses `keep_on_completion` if sessions enabled', async () => { + const mockConfig = getMockSearchConfig({}); const params = getDefaultAsyncSubmitParams(mockConfig, { sessionId: 'foo', }); expect(params).toHaveProperty('keep_on_completion', true); }); + // remove when SQL has full session support https://github.com/elastic/kibana/issues/127880 + test("Don't use `keep_on_completion` if sessions enabled", async () => { + const mockConfig = getMockSearchConfig({}); + const params = getDefaultAsyncSubmitParams(mockConfig, { + sessionId: 'foo', + }); + expect(params).toHaveProperty('keep_on_completion', false); + }); + test('Does not use `keep_on_completion` if disabled', async () => { - const mockConfig = getMockSearchSessionsConfig({ - defaultExpiration: moment.duration(3, 'd'), - enabled: false, + const mockConfig = getMockSearchConfig({ + sessions: { + defaultExpiration: moment.duration(3, 'd'), + enabled: false, + }, }); const params = getDefaultAsyncSubmitParams(mockConfig, { sessionId: 'foo', @@ -73,27 +97,34 @@ describe('request utils', () => { describe('getDefaultAsyncGetParams', () => { test('Uses `wait_for_completion_timeout`', async () => { - const mockConfig = getMockSearchSessionsConfig({ - defaultExpiration: moment.duration(3, 'd'), - enabled: true, + const mockConfig = getMockSearchConfig({ + sessions: { + defaultExpiration: moment.duration(3, 'd'), + enabled: true, + }, }); const params = getDefaultAsyncGetParams(mockConfig, {}); expect(params).toHaveProperty('wait_for_completion_timeout'); }); test('Uses `keep_alive` if `sessionId` is not provided', async () => { - const mockConfig = getMockSearchSessionsConfig({ - defaultExpiration: moment.duration(3, 'd'), - enabled: true, + const mockConfig = getMockSearchConfig({ + sessions: { + defaultExpiration: moment.duration(3, 'd'), + enabled: true, + }, }); const params = getDefaultAsyncGetParams(mockConfig, {}); - expect(params).toHaveProperty('keep_alive', '1m'); + expect(params).toHaveProperty('keep_alive', '60000ms'); }); - test('Has no `keep_alive` if `sessionId` is provided, search and session are stored', async () => { - const mockConfig = getMockSearchSessionsConfig({ - defaultExpiration: moment.duration(3, 'd'), - enabled: true, + // remove when SQL has full session support https://github.com/elastic/kibana/issues/127880 + test.skip('Has no `keep_alive` if `sessionId` is provided, search and session are stored', async () => { + const mockConfig = getMockSearchConfig({ + sessions: { + defaultExpiration: moment.duration(3, 'd'), + enabled: true, + }, }); const params = getDefaultAsyncGetParams(mockConfig, { sessionId: 'foo', @@ -104,12 +135,14 @@ describe('request utils', () => { }); test('Uses `keep_alive` if `sessionId` is provided but sessions disabled', async () => { - const mockConfig = getMockSearchSessionsConfig({ - defaultExpiration: moment.duration(3, 'd'), - enabled: false, + const mockConfig = getMockSearchConfig({ + sessions: { + defaultExpiration: moment.duration(3, 'd'), + enabled: false, + }, }); const params = getDefaultAsyncGetParams(mockConfig, { sessionId: 'foo' }); - expect(params).toHaveProperty('keep_alive', '1m'); + expect(params).toHaveProperty('keep_alive', '60000ms'); }); }); }); diff --git a/src/plugins/data/server/search/strategies/sql_search/request_utils.ts b/src/plugins/data/server/search/strategies/sql_search/request_utils.ts index de8ced65d16c6..e170b506b537d 100644 --- a/src/plugins/data/server/search/strategies/sql_search/request_utils.ts +++ b/src/plugins/data/server/search/strategies/sql_search/request_utils.ts @@ -8,7 +8,7 @@ import { SqlGetAsyncRequest, SqlQueryRequest } from '@elastic/elasticsearch/lib/api/types'; import { ISearchOptions } from '../../../../common'; -import { SearchSessionsConfigSchema } from '../../../../config'; +import { SearchConfigSchema } from '../../../../config'; import { getCommonDefaultAsyncGetParams, getCommonDefaultAsyncSubmitParams, @@ -18,11 +18,17 @@ import { @internal */ export function getDefaultAsyncSubmitParams( - searchSessionsConfig: SearchSessionsConfigSchema | null, + searchConfig: SearchConfigSchema, options: ISearchOptions ): Pick { return { - ...getCommonDefaultAsyncSubmitParams(searchSessionsConfig, options), + ...getCommonDefaultAsyncSubmitParams(searchConfig, options, { + /** + * force disable search sessions until sessions support SQL + * https://github.com/elastic/kibana/issues/127880 + */ + disableSearchSessions: true, + }), }; } @@ -30,10 +36,16 @@ export function getDefaultAsyncSubmitParams( @internal */ export function getDefaultAsyncGetParams( - searchSessionsConfig: SearchSessionsConfigSchema | null, + searchConfig: SearchConfigSchema, options: ISearchOptions ): Pick { return { - ...getCommonDefaultAsyncGetParams(searchSessionsConfig, options), + ...getCommonDefaultAsyncGetParams(searchConfig, options, { + /** + * force disable search sessions until sessions support SQL + * https://github.com/elastic/kibana/issues/127880 + */ + disableSearchSessions: true, + }), }; } diff --git a/src/plugins/data/server/search/strategies/sql_search/sql_search_strategy.test.ts b/src/plugins/data/server/search/strategies/sql_search/sql_search_strategy.test.ts index e36b66a31c017..f4cfcabf0737b 100644 --- a/src/plugins/data/server/search/strategies/sql_search/sql_search_strategy.test.ts +++ b/src/plugins/data/server/search/strategies/sql_search/sql_search_strategy.test.ts @@ -14,6 +14,7 @@ import { SearchStrategyDependencies } from '../../types'; import { sqlSearchStrategyProvider } from './sql_search_strategy'; import { createSearchSessionsClientMock } from '../../mocks'; import { SqlSearchStrategyRequest } from '../../../../common'; +import { getMockSearchConfig } from '../../../../config.mock'; const mockSqlResponse = { body: { @@ -46,6 +47,8 @@ describe('SQL search strategy', () => { searchSessionsClient: createSearchSessionsClientMock(), } as unknown as SearchStrategyDependencies; + const mockSearchConfig = getMockSearchConfig({}); + beforeEach(() => { mockSqlGetAsync.mockClear(); mockSqlQuery.mockClear(); @@ -54,7 +57,7 @@ describe('SQL search strategy', () => { }); it('returns a strategy with `search and `cancel`, `extend`', async () => { - const esSearch = await sqlSearchStrategyProvider(mockLogger); + const esSearch = await sqlSearchStrategyProvider(mockSearchConfig, mockLogger); expect(typeof esSearch.search).toBe('function'); expect(typeof esSearch.cancel).toBe('function'); @@ -70,7 +73,7 @@ describe('SQL search strategy', () => { query: 'SELECT customer_first_name FROM kibana_sample_data_ecommerce ORDER BY order_date DESC', }; - const esSearch = await sqlSearchStrategyProvider(mockLogger); + const esSearch = await sqlSearchStrategyProvider(mockSearchConfig, mockLogger); await esSearch .search({ params }, { transport: { requestTimeout: 30000 } }, mockDeps) @@ -80,8 +83,8 @@ describe('SQL search strategy', () => { const [request, searchOptions] = mockSqlQuery.mock.calls[0]; expect(request).toEqual({ format: 'json', - keep_alive: '1m', - keep_on_completion: undefined, + keep_alive: '60000ms', + keep_on_completion: false, query: 'SELECT customer_first_name FROM kibana_sample_data_ecommerce ORDER BY order_date DESC', wait_for_completion_timeout: '100ms', @@ -101,7 +104,7 @@ describe('SQL search strategy', () => { 'SELECT customer_first_name FROM kibana_sample_data_ecommerce ORDER BY order_date DESC', }; - const esSearch = await sqlSearchStrategyProvider(mockLogger); + const esSearch = await sqlSearchStrategyProvider(mockSearchConfig, mockLogger); await esSearch .search({ id: 'foo', params }, { transport: { requestTimeout: 30000 } }, mockDeps) @@ -112,7 +115,7 @@ describe('SQL search strategy', () => { expect(request).toEqual({ format: 'json', id: 'foo', - keep_alive: '1m', + keep_alive: '60000ms', wait_for_completion_timeout: '100ms', }); expect(searchOptions).toEqual({ @@ -131,7 +134,7 @@ describe('SQL search strategy', () => { query: 'SELECT customer_first_name FROM kibana_sample_data_ecommerce ORDER BY order_date DESC', }; - const esSearch = await sqlSearchStrategyProvider(mockLogger); + const esSearch = await sqlSearchStrategyProvider(mockSearchConfig, mockLogger); await esSearch.search({ params }, { sessionId: '1' }, mockDeps).toPromise(); @@ -150,7 +153,7 @@ describe('SQL search strategy', () => { 'SELECT customer_first_name FROM kibana_sample_data_ecommerce ORDER BY order_date DESC', }; - const esSearch = await sqlSearchStrategyProvider(mockLogger); + const esSearch = await sqlSearchStrategyProvider(mockSearchConfig, mockLogger); await esSearch.search({ id: 'foo', params }, { sessionId: '1' }, mockDeps).toPromise(); @@ -169,7 +172,7 @@ describe('SQL search strategy', () => { query: 'SELECT customer_first_name FROM kibana_sample_data_ecommerce ORDER BY order_date DESC', }; - const esSearch = await sqlSearchStrategyProvider(mockLogger); + const esSearch = await sqlSearchStrategyProvider(mockSearchConfig, mockLogger); await esSearch.search({ params }, { sessionId: '1' }, mockDeps).toPromise(); @@ -178,7 +181,7 @@ describe('SQL search strategy', () => { expect(request.query).toEqual(params.query); expect(request).toHaveProperty('wait_for_completion_timeout'); - expect(request).toHaveProperty('keep_alive', '1m'); + expect(request).toHaveProperty('keep_alive', '60000ms'); }); it('makes a GET request to async search with keepalive', async () => { @@ -189,7 +192,7 @@ describe('SQL search strategy', () => { 'SELECT customer_first_name FROM kibana_sample_data_ecommerce ORDER BY order_date DESC', }; - const esSearch = await sqlSearchStrategyProvider(mockLogger); + const esSearch = await sqlSearchStrategyProvider(mockSearchConfig, mockLogger); await esSearch.search({ id: 'foo', params }, { sessionId: '1' }, mockDeps).toPromise(); @@ -197,7 +200,7 @@ describe('SQL search strategy', () => { const request = mockSqlGetAsync.mock.calls[0][0]; expect(request.id).toEqual('foo'); expect(request).toHaveProperty('wait_for_completion_timeout'); - expect(request).toHaveProperty('keep_alive', '1m'); + expect(request).toHaveProperty('keep_alive', '60000ms'); }); }); @@ -216,7 +219,7 @@ describe('SQL search strategy', () => { query: 'SELECT customer_first_name FROM kibana_sample_data_ecommerce ORDER BY order_date DESC', }; - const esSearch = await sqlSearchStrategyProvider(mockLogger); + const esSearch = await sqlSearchStrategyProvider(mockSearchConfig, mockLogger); let err: KbnServerError | undefined; try { @@ -240,7 +243,7 @@ describe('SQL search strategy', () => { query: 'SELECT customer_first_name FROM kibana_sample_data_ecommerce ORDER BY order_date DESC', }; - const esSearch = await sqlSearchStrategyProvider(mockLogger); + const esSearch = await sqlSearchStrategyProvider(mockSearchConfig, mockLogger); let err: KbnServerError | undefined; try { @@ -262,7 +265,7 @@ describe('SQL search strategy', () => { }) ); - const esSearch = await sqlSearchStrategyProvider(mockLogger); + const esSearch = await sqlSearchStrategyProvider(mockSearchConfig, mockLogger); await esSearch.search({ id: 'foo', params: { query: 'query' } }, {}, mockDeps).toPromise(); expect(mockSqlClearCursor).not.toHaveBeenCalled(); @@ -273,7 +276,7 @@ describe('SQL search strategy', () => { merge({}, mockSqlResponse, { body: { cursor: 'cursor' } }) ); - const esSearch = await sqlSearchStrategyProvider(mockLogger); + const esSearch = await sqlSearchStrategyProvider(mockSearchConfig, mockLogger); await esSearch .search({ id: 'foo', params: { query: 'query', keep_cursor: true } }, {}, mockDeps) .toPromise(); @@ -286,7 +289,7 @@ describe('SQL search strategy', () => { merge({}, mockSqlResponse, { body: { cursor: 'cursor' } }) ); - const esSearch = await sqlSearchStrategyProvider(mockLogger); + const esSearch = await sqlSearchStrategyProvider(mockSearchConfig, mockLogger); await esSearch.search({ id: 'foo', params: { query: 'query' } }, {}, mockDeps).toPromise(); expect(mockSqlClearCursor).toHaveBeenCalledWith({ cursor: 'cursor' }); @@ -295,7 +298,7 @@ describe('SQL search strategy', () => { it('returns the time it took to run a search', async () => { mockSqlGetAsync.mockResolvedValueOnce(mockSqlResponse); - const esSearch = await sqlSearchStrategyProvider(mockLogger); + const esSearch = await sqlSearchStrategyProvider(mockSearchConfig, mockLogger); await expect( esSearch.search({ id: 'foo', params: { query: 'query' } }, {}, mockDeps).toPromise() ).resolves.toHaveProperty('took', expect.any(Number)); @@ -307,7 +310,7 @@ describe('SQL search strategy', () => { mockSqlDelete.mockResolvedValueOnce(200); const id = 'some_id'; - const esSearch = await sqlSearchStrategyProvider(mockLogger); + const esSearch = await sqlSearchStrategyProvider(mockSearchConfig, mockLogger); await esSearch.cancel!(id, {}, mockDeps); @@ -323,7 +326,7 @@ describe('SQL search strategy', () => { const id = 'some_other_id'; const keepAlive = '1d'; - const esSearch = await sqlSearchStrategyProvider(mockLogger); + const esSearch = await sqlSearchStrategyProvider(mockSearchConfig, mockLogger); await esSearch.extend!(id, keepAlive, {}, mockDeps); expect(mockSqlGetAsync).toBeCalled(); diff --git a/src/plugins/data/server/search/strategies/sql_search/sql_search_strategy.ts b/src/plugins/data/server/search/strategies/sql_search/sql_search_strategy.ts index b84dcfe45d2cf..64c4d6fd5ee0f 100644 --- a/src/plugins/data/server/search/strategies/sql_search/sql_search_strategy.ts +++ b/src/plugins/data/server/search/strategies/sql_search/sql_search_strategy.ts @@ -20,8 +20,10 @@ import type { import { pollSearch } from '../../../../common'; import { getDefaultAsyncGetParams, getDefaultAsyncSubmitParams } from './request_utils'; import { toAsyncKibanaSearchResponse } from './response_utils'; +import { SearchConfigSchema } from '../../../../config'; export const sqlSearchStrategyProvider = ( + searchConfig: SearchConfigSchema, logger: Logger, useInternalUser: boolean = false ): ISearchStrategy => { @@ -42,11 +44,6 @@ export const sqlSearchStrategyProvider = ( const client = useInternalUser ? esClient.asInternalUser : esClient.asCurrentUser; const startTime = Date.now(); - // disable search sessions until session task manager supports SQL - // https://github.com/elastic/kibana/issues/127880 - // const sessionConfig = searchSessionsClient.getConfig(); - const sessionConfig = null; - const search = async () => { const { keep_cursor: keepCursor, ...params } = request.params ?? {}; let body: SqlQueryResponse; @@ -56,7 +53,7 @@ export const sqlSearchStrategyProvider = ( ({ body, headers } = await client.sql.getAsync( { format: params?.format ?? 'json', - ...getDefaultAsyncGetParams(sessionConfig, options), + ...getDefaultAsyncGetParams(searchConfig, options), id, }, { ...options.transport, signal: options.abortSignal, meta: true } @@ -65,7 +62,7 @@ export const sqlSearchStrategyProvider = ( ({ headers, body } = await client.sql.query( { format: params.format ?? 'json', - ...getDefaultAsyncSubmitParams(sessionConfig, options), + ...getDefaultAsyncSubmitParams(searchConfig, options), ...params, }, { ...options.transport, signal: options.abortSignal, meta: true } diff --git a/src/plugins/data/server/ui_settings.ts b/src/plugins/data/server/ui_settings.ts index fce2680f5fc03..a1ac225ba4b38 100644 --- a/src/plugins/data/server/ui_settings.ts +++ b/src/plugins/data/server/ui_settings.ts @@ -295,7 +295,7 @@ export function getUiSettings( name: i18n.translate('data.advancedSettings.histogram.maxBarsTitle', { defaultMessage: 'Maximum buckets', }), - value: 100, + value: 1000, description: i18n.translate('data.advancedSettings.histogram.maxBarsText', { defaultMessage: ` Limits the density of date and number histograms across Kibana diff --git a/src/plugins/data/tsconfig.json b/src/plugins/data/tsconfig.json index 8f391fc15e871..2e9c05992cc9d 100644 --- a/src/plugins/data/tsconfig.json +++ b/src/plugins/data/tsconfig.json @@ -11,6 +11,7 @@ "public/**/*", "server/**/*", "config.ts", + "config.mock.ts", "common/**/*.json", "public/**/*.json", "../../../typings/index.d.ts" diff --git a/src/plugins/discover/public/__mocks__/discover_state.mock.ts b/src/plugins/discover/public/__mocks__/discover_state.mock.ts new file mode 100644 index 0000000000000..30c40ef77bfb9 --- /dev/null +++ b/src/plugins/discover/public/__mocks__/discover_state.mock.ts @@ -0,0 +1,21 @@ +/* + * 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 { createBrowserHistory } from 'history'; +import { getState } from '../application/main/services/discover_state'; +import { savedSearchMockWithTimeField, savedSearchMock } from './saved_search'; +import { discoverServiceMock } from './services'; + +export function getDiscoverStateMock({ isTimeBased = true }) { + const history = createBrowserHistory(); + history.push('/'); + return getState({ + savedSearch: isTimeBased ? savedSearchMockWithTimeField : savedSearchMock, + services: discoverServiceMock, + history, + }); +} diff --git a/src/plugins/discover/public/__mocks__/services.ts b/src/plugins/discover/public/__mocks__/services.ts index 252aead2f76ed..97de63d231a46 100644 --- a/src/plugins/discover/public/__mocks__/services.ts +++ b/src/plugins/discover/public/__mocks__/services.ts @@ -26,10 +26,12 @@ import { FORMATS_UI_SETTINGS } from '@kbn/field-formats-plugin/common'; import { LocalStorageMock } from './local_storage_mock'; import { fieldFormatsMock } from '@kbn/field-formats-plugin/common/mocks'; import { dataViewsMock } from './data_views'; +import { Observable, of } from 'rxjs'; const dataPlugin = dataPluginMock.createStartContract(); const expressionsPlugin = expressionsPluginMock.createStartContract(); dataPlugin.query.filterManager.getFilters = jest.fn(() => []); +dataPlugin.query.filterManager.getUpdates$ = jest.fn(() => of({}) as unknown as Observable); export const discoverServiceMock = { core: coreMock.createStart(), diff --git a/src/plugins/discover/public/application/main/components/chart/histogram.tsx b/src/plugins/discover/public/application/main/components/chart/histogram.tsx index b34aa1595f81e..62ade96fceb86 100644 --- a/src/plugins/discover/public/application/main/components/chart/histogram.tsx +++ b/src/plugins/discover/public/application/main/components/chart/histogram.tsx @@ -41,6 +41,7 @@ import { renderEndzoneTooltip, } 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'; @@ -252,12 +253,16 @@ export function DiscoverHistogram({ ); if (bucketInterval?.scaled) { + const timeRangeWrapperCss = css` + flex-grow: 0; + `; timeRange = ( {timeRange} 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 39db1481500fa..32aa0b0999bbe 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 @@ -37,9 +37,20 @@ 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 { getDiscoverStateMock } from '../../../../__mocks__/discover_state.mock'; setHeaderActionMenuMounter(jest.fn()); +function getAppStateContainer() { + const appStateContainer = getDiscoverStateMock({ isTimeBased: true }).appStateContainer; + appStateContainer.set({ + query: { query: '', language: 'lucene' }, + filters: [], + }); + return appStateContainer; +} + function mountComponent( dataView: DataView, prevSidebarClosed?: boolean, @@ -167,7 +178,9 @@ function mountComponent( return mountWithIntl( - + + + , mountOptions ); diff --git a/src/plugins/discover/public/application/main/components/layout/discover_layout.tsx b/src/plugins/discover/public/application/main/components/layout/discover_layout.tsx index fe6ac392c35a8..a7cde67d4869b 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_layout.tsx +++ b/src/plugins/discover/public/application/main/components/layout/discover_layout.tsx @@ -152,9 +152,13 @@ export function DiscoverLayout({ [filterManager, dataView, dataViews, trackUiMetric, capabilities] ); - const onFieldEdited = useCallback(() => { + const onFieldEdited = useCallback(async () => { + if (!dataView.isPersisted()) { + await updateAdHocDataViewId(dataView); + return; + } savedSearchRefetch$.next('reset'); - }, [savedSearchRefetch$]); + }, [dataView, savedSearchRefetch$, updateAdHocDataViewId]); const onDisableFilters = useCallback(() => { const disabledFilters = filterManager @@ -247,7 +251,6 @@ export function DiscoverLayout({ onRemoveField={onRemoveColumn} onChangeDataView={onChangeDataView} selectedDataView={dataView} - state={state} isClosed={isSidebarClosed} trackUiMetric={trackUiMetric} useNewFieldsApi={useNewFieldsApi} 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 ae433ee8ba38e..6f66b1f613b22 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 @@ -256,7 +256,10 @@ describe('Discover main content component', () => { }); it('should pass undefined for onResetChartHeight to DiscoverChart when panels mode is DISCOVER_PANELS_MODE.FIXED', async () => { - const component = await mountComponent(); + 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(); @@ -340,5 +343,21 @@ describe('Discover main content component', () => { expect(storage.set).toHaveBeenCalledWith(HISTOGRAM_HEIGHT_KEY, defaultTopPanelHeight); expect(component.find(DiscoverPanels).prop('topPanelHeight')).toBe(defaultTopPanelHeight); }); + + 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); + }); + 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(); + }); }); }); 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 68d91c9123a6d..4998e561f5dd7 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 @@ -52,7 +52,7 @@ export interface DiscoverMainContentProps { isTimeBased: boolean; viewMode: VIEW_MODE; onAddFilter: DocViewFilterFn | undefined; - onFieldEdited: () => void; + onFieldEdited: () => Promise; columns: string[]; resizeRef: RefObject; } @@ -161,7 +161,10 @@ export const DiscoverMainContent = ({ isTimeBased={isTimeBased} appendHistogram={showFixedPanels ? : } onResetChartHeight={ - panelsMode === DISCOVER_PANELS_MODE.RESIZABLE ? resetTopPanelHeight : undefined + topPanelHeight !== defaultTopPanelHeight && + panelsMode === DISCOVER_PANELS_MODE.RESIZABLE + ? resetTopPanelHeight + : undefined } /> diff --git a/src/plugins/discover/public/application/main/components/sidebar/discover_field.test.tsx b/src/plugins/discover/public/application/main/components/sidebar/discover_field.test.tsx index caa8539ab6b32..dd27369a74a04 100644 --- a/src/plugins/discover/public/application/main/components/sidebar/discover_field.test.tsx +++ b/src/plugins/discover/public/application/main/components/sidebar/discover_field.test.tsx @@ -19,6 +19,8 @@ import { DiscoverField, DiscoverFieldProps } from './discover_field'; import { DataViewField } from '@kbn/data-views-plugin/public'; import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; import { stubDataView } from '@kbn/data-views-plugin/common/data_view.stub'; +import { DiscoverAppStateProvider } from '../../services/discover_app_state_container'; +import { getDiscoverStateMock } from '../../../../__mocks__/discover_state.mock'; jest.mock('@kbn/unified-field-list-plugin/public/services/field_stats', () => ({ loadFieldStats: jest.fn().mockResolvedValue({ @@ -88,10 +90,6 @@ async function getComponent({ onRemoveField: jest.fn(), showFieldStats, selected, - state: { - query: { query: '', language: 'lucene' }, - filters: [], - }, contextualFields: [], }; const services = { @@ -135,9 +133,16 @@ async function getComponent({ fieldFormats: fieldFormatsServiceMock.createStartContract(), charts: chartPluginMock.createSetupContract(), }; + const appStateContainer = getDiscoverStateMock({ isTimeBased: true }).appStateContainer; + appStateContainer.set({ + query: { query: '', language: 'lucene' }, + filters: [], + }); const comp = await mountWithIntl( - + + + ); // wait for lazy modules diff --git a/src/plugins/discover/public/application/main/components/sidebar/discover_field.tsx b/src/plugins/discover/public/application/main/components/sidebar/discover_field.tsx index 591475d949c63..03e742da3514f 100644 --- a/src/plugins/discover/public/application/main/components/sidebar/discover_field.tsx +++ b/src/plugins/discover/public/application/main/components/sidebar/discover_field.tsx @@ -26,10 +26,10 @@ import { getTypeForFieldIcon } from '../../../../utils/get_type_for_field_icon'; import { DiscoverFieldDetails } from './discover_field_details'; import { FieldDetails } from './types'; import { getFieldTypeName } from '../../../../utils/get_field_type_name'; -import type { AppState } from '../../services/discover_state'; import { useDiscoverServices } from '../../../../hooks/use_discover_services'; import { SHOW_LEGACY_FIELD_TOP_VALUES, PLUGIN_ID } from '../../../../../common'; import { getUiActions } from '../../../../kibana_services'; +import { useAppStateSelector } from '../../services/discover_app_state_container'; function wrapOnDot(str?: string) { // u200B is a non-width white-space character, which allows @@ -261,12 +261,6 @@ export interface DiscoverFieldProps { * Optionally show or hide field stats in the popover */ showFieldStats?: boolean; - - /** - * Discover App State - */ - state: AppState; - /** * Columns */ @@ -287,13 +281,14 @@ function DiscoverFieldComponent({ onEditField, onDeleteField, showFieldStats, - state, contextualFields, }: DiscoverFieldProps) { const services = useDiscoverServices(); const { data } = services; const [infoIsOpen, setOpen] = useState(false); const isDocumentRecord = !!onAddFilter; + const query = useAppStateSelector((state) => state.query); + const filters = useAppStateSelector((state) => state.filters); const addFilterAndClosePopover: typeof onAddFilter | undefined = useMemo( () => @@ -429,8 +424,8 @@ function DiscoverFieldComponent({ {Boolean(dateRange) && ( >>, [string, { fieldName: string }]>( () => Promise.resolve([]) @@ -67,7 +69,6 @@ function getCompProps(): DiscoverSidebarProps { onAddField: jest.fn(), onRemoveField: jest.fn(), selectedDataView: dataView, - state: {}, trackUiMetric: jest.fn(), fieldFilter: getDefaultFieldFilter(), setFieldFilter: jest.fn(), @@ -81,6 +82,15 @@ function getCompProps(): DiscoverSidebarProps { }; } +function getAppStateContainer() { + const appStateContainer = getDiscoverStateMock({ isTimeBased: true }).appStateContainer; + appStateContainer.set({ + query: { query: '', language: 'lucene' }, + filters: [], + }); + return appStateContainer; +} + describe('discover sidebar', function () { let props: DiscoverSidebarProps; let comp: ReactWrapper; @@ -97,7 +107,9 @@ describe('discover sidebar', function () { comp = await mountWithIntl( - + + + ); // wait for lazy modules @@ -142,7 +154,9 @@ describe('discover sidebar', function () { it('should not render Add/Edit field buttons in viewer mode', () => { const compInViewerMode = mountWithIntl( - + + + ); const addFieldButton = findTestSubject(compInViewerMode, 'dataView-add-field_btn'); @@ -155,7 +169,9 @@ describe('discover sidebar', function () { it('should render buttons in data view picker correctly', async () => { const compWithPicker = mountWithIntl( - + + + ); // open data view picker @@ -179,12 +195,14 @@ describe('discover sidebar', function () { it('should not render buttons in data view picker when in viewer mode', async () => { const compWithPickerInViewerMode = mountWithIntl( - + + + ); // open data view picker @@ -203,7 +221,9 @@ describe('discover sidebar', function () { it('should render the Visualize in Lens button in text based languages mode', () => { const compInViewerMode = mountWithIntl( - + + + ); const visualizeField = findTestSubject(compInViewerMode, 'textBased-visualize'); diff --git a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar.tsx b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar.tsx index 436fdc36f4d32..938885a5278da 100644 --- a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar.tsx +++ b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar.tsx @@ -29,6 +29,7 @@ import { FormattedMessage } from '@kbn/i18n-react'; import { DataViewPicker } from '@kbn/unified-search-plugin/public'; import { DataViewField, getFieldSubtypeMulti } from '@kbn/data-views-plugin/public'; import { triggerVisualizeActionsTextBasedLanguages } from '@kbn/unified-field-list-plugin/public'; +import { useAppStateSelector } from '../../services/discover_app_state_container'; import { useDiscoverServices } from '../../../../hooks/use_discover_services'; import { DiscoverField } from './discover_field'; import { DiscoverFieldSearch } from './discover_field_search'; @@ -119,7 +120,6 @@ export function DiscoverSidebarComponent({ viewMode, createNewDataView, showDataViewPicker, - state, }: DiscoverSidebarProps) { const { uiSettings, dataViewFieldEditor } = useDiscoverServices(); const [fields, setFields] = useState(null); @@ -128,6 +128,7 @@ export function DiscoverSidebarComponent({ const [fieldsPerPage, setFieldsPerPage] = useState(FIELDS_PER_PAGE); const availableFieldsContainer = useRef(null); const isPlainRecord = !onAddFilter; + const query = useAppStateSelector((state) => state.query); useEffect(() => { if (documents) { @@ -283,7 +284,7 @@ export function DiscoverSidebarComponent({ }, fieldName, onDelete: async () => { - onFieldEdited(); + await onFieldEdited(); }, }); if (setFieldEditorRef) { @@ -314,8 +315,7 @@ export function DiscoverSidebarComponent({ const filterChanged = useMemo(() => isEqual(fieldFilter, getDefaultFieldFilter()), [fieldFilter]); const visualizeAggregateQuery = useCallback(() => { - const aggregateQuery = - state.query && isOfAggregateQueryType(state.query) ? state.query : undefined; + const aggregateQuery = query && isOfAggregateQueryType(query) ? query : undefined; triggerVisualizeActionsTextBasedLanguages( getUiActions(), columns, @@ -323,7 +323,7 @@ export function DiscoverSidebarComponent({ selectedDataView, aggregateQuery ); - }, [columns, selectedDataView, state.query]); + }, [columns, selectedDataView, query]); if (!selectedDataView) { return null; @@ -429,7 +429,6 @@ export function DiscoverSidebarComponent({ onEditField={editField} onDeleteField={deleteField} showFieldStats={showFieldStats} - state={state} contextualFields={columns} /> @@ -491,7 +490,6 @@ export function DiscoverSidebarComponent({ onEditField={editField} onDeleteField={deleteField} showFieldStats={showFieldStats} - state={state} contextualFields={columns} /> @@ -522,7 +520,6 @@ export function DiscoverSidebarComponent({ onEditField={editField} onDeleteField={deleteField} showFieldStats={showFieldStats} - state={state} contextualFields={columns} /> diff --git a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.test.tsx b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.test.tsx index 944355c9a9db3..40cab06039f6e 100644 --- a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.test.tsx +++ b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.test.tsx @@ -28,6 +28,8 @@ import { chartPluginMock } from '@kbn/charts-plugin/public/mocks'; import { dataViewPluginMocks } from '@kbn/data-views-plugin/public/mocks'; import { fieldFormatsServiceMock } from '@kbn/field-formats-plugin/public/mocks'; import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; +import { getDiscoverStateMock } from '../../../../__mocks__/discover_state.mock'; +import { DiscoverAppStateProvider } from '../../services/discover_app_state_container'; jest.mock('@kbn/unified-field-list-plugin/public/services/field_stats', () => ({ loadFieldStats: jest.fn().mockResolvedValue({ @@ -166,10 +168,6 @@ function getCompProps(): DiscoverSidebarResponsiveProps { onAddField: jest.fn(), onRemoveField: jest.fn(), selectedDataView: dataView, - state: { - query: { query: '', language: 'lucene' }, - filters: [], - }, trackUiMetric: jest.fn(), onFieldEdited: jest.fn(), viewMode: VIEW_MODE.DOCUMENT_LEVEL, @@ -185,9 +183,17 @@ describe('discover responsive sidebar', function () { beforeAll(async () => { props = getCompProps(); await act(async () => { + const appStateContainer = getDiscoverStateMock({ isTimeBased: true }).appStateContainer; + appStateContainer.set({ + query: { query: '', language: 'lucene' }, + filters: [], + }); + comp = await mountWithIntl( - + + + ); // wait for lazy modules @@ -262,14 +268,16 @@ describe('discover responsive sidebar', function () { recordRawType: RecordRawType.PLAIN, result: getDataTableRecords(stubLogstashDataView), }) as DataDocuments$, - state: { - ...initialProps.state, - query: { sql: 'SELECT * FROM `index`' }, - }, }; + const appStateContainer = getDiscoverStateMock({ isTimeBased: true }).appStateContainer; + appStateContainer.set({ + query: { sql: 'SELECT * FROM `index`' }, + }); const compInViewerMode = mountWithIntl( - + + + ); expect(findTestSubject(compInViewerMode, 'indexPattern-add-field_btn').length).toBe(0); @@ -286,9 +294,16 @@ describe('discover responsive sidebar', function () { }, }, }; + const appStateContainer = getDiscoverStateMock({ isTimeBased: true }).appStateContainer; + appStateContainer.set({ + query: { query: '', language: 'lucene' }, + filters: [], + }); const compInViewerMode = mountWithIntl( - + + + ); expect( diff --git a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.tsx b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.tsx index 274cb85cc3535..9e8ad96f9abb6 100644 --- a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.tsx +++ b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.tsx @@ -26,13 +26,13 @@ import type { DataView, DataViewField, DataViewListItem } from '@kbn/data-views- import { useDiscoverServices } from '../../../../hooks/use_discover_services'; import { getDefaultFieldFilter } from './lib/field_filter'; import { DiscoverSidebar } from './discover_sidebar'; -import { AppState } from '../../services/discover_state'; import { AvailableFields$, DataDocuments$, RecordRawType } from '../../hooks/use_saved_search'; import { calcFieldCounts } from '../../utils/calc_field_counts'; import { VIEW_MODE } from '../../../../components/view_mode_toggle'; import { FetchStatus } from '../../../types'; import { DISCOVER_TOUR_STEP_ANCHOR_IDS } from '../../../../components/discover_tour'; import { getRawRecordType } from '../../utils/get_raw_record_type'; +import { useAppStateSelector } from '../../services/discover_app_state_container'; export interface DiscoverSidebarResponsiveProps { /** @@ -76,10 +76,6 @@ export interface DiscoverSidebarResponsiveProps { * Currently selected data view */ selectedDataView?: DataView; - /** - * Discover App state - */ - state: AppState; /** * Metric tracking function * @param metricType @@ -93,7 +89,7 @@ export interface DiscoverSidebarResponsiveProps { /** * callback to execute on edit runtime field */ - onFieldEdited: () => void; + onFieldEdited: () => Promise; /** * callback to execute on create dataview */ @@ -115,9 +111,8 @@ export interface DiscoverSidebarResponsiveProps { */ export function DiscoverSidebarResponsive(props: DiscoverSidebarResponsiveProps) { const services = useDiscoverServices(); - const isPlainRecord = useMemo( - () => getRawRecordType(props.state.query) === RecordRawType.PLAIN, - [props.state.query] + const isPlainRecord = useAppStateSelector( + (state) => getRawRecordType(state.query) === RecordRawType.PLAIN ); const { selectedDataView, onFieldEdited, onDataViewCreated } = props; const [fieldFilter, setFieldFilter] = useState(getDefaultFieldFilter()); @@ -220,7 +215,7 @@ export function DiscoverSidebarResponsive(props: DiscoverSidebarResponsiveProps) }, fieldName, onSave: async () => { - onFieldEdited(); + await onFieldEdited(); }, }); if (setFieldEditorRef) { diff --git a/src/plugins/discover/public/application/main/components/top_nav/discover_topnav.tsx b/src/plugins/discover/public/application/main/components/top_nav/discover_topnav.tsx index 66f06169256ab..0aa132d1437d3 100644 --- a/src/plugins/discover/public/application/main/components/top_nav/discover_topnav.tsx +++ b/src/plugins/discover/public/application/main/components/top_nav/discover_topnav.tsx @@ -34,7 +34,7 @@ export type DiscoverTopNavProps = Pick< onChangeDataView: (dataView: string) => void; isPlainRecord: boolean; textBasedLanguageModeErrors?: Error; - onFieldEdited: () => void; + onFieldEdited: () => Promise; persistDataView: (dataView: DataView) => Promise; updateAdHocDataViewId: (dataView: DataView) => Promise; adHocDataViewList: DataView[]; @@ -111,7 +111,7 @@ export const DiscoverTopNav = ({ }, fieldName, onSave: async () => { - onFieldEdited(); + await onFieldEdited(); }, }); } diff --git a/src/plugins/discover/public/application/main/discover_main_app.tsx b/src/plugins/discover/public/application/main/discover_main_app.tsx index d7c8435cdfbd0..abd714fea8f07 100644 --- a/src/plugins/discover/public/application/main/discover_main_app.tsx +++ b/src/plugins/discover/public/application/main/discover_main_app.tsx @@ -17,6 +17,7 @@ import { useUrl } from './hooks/use_url'; import { useDiscoverServices } from '../../hooks/use_discover_services'; import { DataTableRecord } from '../../types'; import { useSavedSearchAliasMatchRedirect } from '../../hooks/saved_search_alias_match_redirect'; +import { DiscoverAppStateProvider } from './services/discover_app_state_container'; const DiscoverLayoutMemoized = React.memo(DiscoverLayout); @@ -100,25 +101,27 @@ export function DiscoverMainApp(props: DiscoverMainProps) { useSavedSearchAliasMatchRedirect({ savedSearch, spaces, history }); return ( - + + + ); } diff --git a/src/plugins/discover/public/application/main/hooks/use_adhoc_data_views.test.ts b/src/plugins/discover/public/application/main/hooks/use_adhoc_data_views.test.ts index d06521d345270..e14defbdeb585 100644 --- a/src/plugins/discover/public/application/main/hooks/use_adhoc_data_views.test.ts +++ b/src/plugins/discover/public/application/main/hooks/use_adhoc_data_views.test.ts @@ -75,12 +75,18 @@ describe('useAdHocDataViews', () => { const hook = renderHook((d: DataView) => useAdHocDataViews({ dataView: mockDataView, - dataViews: mockDiscoverServices.dataViews, savedSearch: savedSearchMock, stateContainer: { appStateContainer: { getState: jest.fn().mockReturnValue({}) }, + replaceUrlAppState: jest.fn(), + kbnUrlStateStorage: { + kbnUrlControls: { flush: jest.fn() }, + }, } as unknown as GetStateReturn, - onChangeDataView: jest.fn(), + setUrlTracking: jest.fn(), + dataViews: mockDiscoverServices.dataViews, + filterManager: mockDiscoverServices.filterManager, + toastNotifications: mockDiscoverServices.toastNotifications, }) ); @@ -101,12 +107,18 @@ describe('useAdHocDataViews', () => { const hook = renderHook((d: DataView) => useAdHocDataViews({ dataView: mockDataView, - dataViews: mockDiscoverServices.dataViews, savedSearch: savedSearchMock, stateContainer: { appStateContainer: { getState: jest.fn().mockReturnValue({}) }, + replaceUrlAppState: jest.fn(), + kbnUrlStateStorage: { + kbnUrlControls: { flush: jest.fn() }, + }, } as unknown as GetStateReturn, - onChangeDataView: jest.fn(), + setUrlTracking: jest.fn(), + dataViews: mockDiscoverServices.dataViews, + filterManager: mockDiscoverServices.filterManager, + toastNotifications: mockDiscoverServices.toastNotifications, }) ); diff --git a/src/plugins/discover/public/application/main/hooks/use_adhoc_data_views.ts b/src/plugins/discover/public/application/main/hooks/use_adhoc_data_views.ts index ded1b90d69873..89fd4477da34c 100644 --- a/src/plugins/discover/public/application/main/hooks/use_adhoc_data_views.ts +++ b/src/plugins/discover/public/application/main/hooks/use_adhoc_data_views.ts @@ -7,29 +7,36 @@ */ import { useCallback, useEffect, useState } from 'react'; -import { DataViewsContract, type DataView } from '@kbn/data-views-plugin/public'; +import type { DataView, DataViewsContract } from '@kbn/data-views-plugin/public'; import { SavedSearch } from '@kbn/saved-search-plugin/public'; import { UPDATE_FILTER_REFERENCES_ACTION, UPDATE_FILTER_REFERENCES_TRIGGER, } from '@kbn/unified-search-plugin/public'; import { ActionExecutionContext } from '@kbn/ui-actions-plugin/public'; +import type { FilterManager } from '@kbn/data-plugin/public'; +import type { ToastsStart } from '@kbn/core-notifications-browser'; +import { getUiActions } from '../../../kibana_services'; import { useConfirmPersistencePrompt } from '../../../hooks/use_confirm_persistence_prompt'; -import { getUiActions, getUrlTracker } from '../../../kibana_services'; import { GetStateReturn } from '../services/discover_state'; +import { useFiltersValidation } from './use_filters_validation'; export const useAdHocDataViews = ({ dataView, savedSearch, - dataViews, stateContainer, - onChangeDataView, + setUrlTracking, + filterManager, + dataViews, + toastNotifications, }: { dataView: DataView; savedSearch: SavedSearch; - dataViews: DataViewsContract; stateContainer: GetStateReturn; - onChangeDataView: (dataViewId: string) => Promise; + setUrlTracking: (dataView: DataView) => void; + dataViews: DataViewsContract; + filterManager: FilterManager; + toastNotifications: ToastsStart; }) => { const [adHocDataViewList, setAdHocDataViewList] = useState( !dataView.isPersisted() ? [dataView] : [] @@ -44,6 +51,11 @@ export const useAdHocDataViews = ({ } }, [dataView]); + /** + * Takes care of checking data view id references in filters + */ + useFiltersValidation({ savedSearch, filterManager, toastNotifications }); + /** * When saving a saved search with an ad hoc data view, a new id needs to be generated for the data view * This is to prevent duplicate ids messing with our system @@ -57,12 +69,11 @@ export const useAdHocDataViews = ({ prev.filter((d) => d.id && dataViewToUpdate.id && d.id !== dataViewToUpdate.id) ); - savedSearch.searchSource.setField('index', newDataView); - - // update filters references const uiActions = await getUiActions(); const trigger = uiActions.getTrigger(UPDATE_FILTER_REFERENCES_TRIGGER); const action = uiActions.getAction(UPDATE_FILTER_REFERENCES_ACTION); + + // execute shouldn't be awaited, this is important for pending history push cancellation action?.execute({ trigger, fromDataView: dataViewToUpdate.id, @@ -70,9 +81,11 @@ export const useAdHocDataViews = ({ usedDataViews: [], } as ActionExecutionContext); + stateContainer.replaceUrlAppState({ index: newDataView.id }); + setUrlTracking(newDataView); return newDataView; }, - [dataViews, savedSearch.searchSource] + [dataViews, setUrlTracking, stateContainer] ); const { openConfirmSavePrompt, updateSavedSearch } = @@ -81,22 +94,16 @@ export const useAdHocDataViews = ({ const currentDataView = savedSearch.searchSource.getField('index')!; if (currentDataView && !currentDataView.isPersisted()) { const createdDataView = await openConfirmSavePrompt(currentDataView); - if (createdDataView) { - savedSearch.searchSource.setField('index', createdDataView); - await onChangeDataView(createdDataView.id!); - // update saved search with saved data view - if (savedSearch.id) { - const currentState = stateContainer.appStateContainer.getState(); - await updateSavedSearch({ savedSearch, dataView: createdDataView, state: currentState }); - } - getUrlTracker().setTrackingEnabled(true); - return createdDataView; + // update saved search with saved data view + if (createdDataView && savedSearch.id) { + const currentState = stateContainer.appStateContainer.getState(); + await updateSavedSearch({ savedSearch, dataView: createdDataView, state: currentState }); } - return undefined; + return createdDataView; } return currentDataView; - }, [stateContainer, onChangeDataView, openConfirmSavePrompt, savedSearch, updateSavedSearch]); + }, [stateContainer, openConfirmSavePrompt, savedSearch, updateSavedSearch]); return { adHocDataViewList, persistDataView, updateAdHocDataViewId }; }; diff --git a/src/plugins/discover/public/application/main/hooks/use_discover_state.test.ts b/src/plugins/discover/public/application/main/hooks/use_discover_state.test.tsx similarity index 100% rename from src/plugins/discover/public/application/main/hooks/use_discover_state.test.ts rename to src/plugins/discover/public/application/main/hooks/use_discover_state.test.tsx diff --git a/src/plugins/discover/public/application/main/hooks/use_discover_state.ts b/src/plugins/discover/public/application/main/hooks/use_discover_state.ts index 1c530f475f0b1..ff448e59917a8 100644 --- a/src/plugins/discover/public/application/main/hooks/use_discover_state.ts +++ b/src/plugins/discover/public/application/main/hooks/use_discover_state.ts @@ -44,7 +44,7 @@ export function useDiscoverState({ setExpandedDoc: (doc?: DataTableRecord) => void; dataViewList: DataViewListItem[]; }) { - const { uiSettings, data, filterManager, dataViews } = services; + const { uiSettings, data, filterManager, dataViews, toastNotifications } = services; const useNewFieldsApi = useMemo(() => !uiSettings.get(SEARCH_FIELDS_FROM_SOURCE), [uiSettings]); const { timefilter } = data.query.timefilter; @@ -126,10 +126,12 @@ export function useDiscoverState({ */ const { adHocDataViewList, persistDataView, updateAdHocDataViewId } = useAdHocDataViews({ dataView, - dataViews, stateContainer, savedSearch, - onChangeDataView, + setUrlTracking, + dataViews, + toastNotifications, + filterManager, }); /** diff --git a/src/plugins/discover/public/application/main/hooks/use_filters_validation.ts b/src/plugins/discover/public/application/main/hooks/use_filters_validation.ts new file mode 100644 index 0000000000000..f093edbd7c65b --- /dev/null +++ b/src/plugins/discover/public/application/main/hooks/use_filters_validation.ts @@ -0,0 +1,56 @@ +/* + * 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 { IToasts, ToastsStart } from '@kbn/core/public'; +import { FilterManager } from '@kbn/data-plugin/public'; +import { i18n } from '@kbn/i18n'; +import { SavedSearch } from '@kbn/saved-search-plugin/public'; +import { useEffect } from 'react'; +import { debounceTime } from 'rxjs'; + +const addInvalidFiltersWarn = (toastNotifications: IToasts) => { + const warningTitle = i18n.translate('discover.invalidFiltersWarnToast.title', { + defaultMessage: 'Different index references', + }); + toastNotifications.addWarning({ + title: warningTitle, + text: i18n.translate('discover.invalidFiltersWarnToast.description', { + defaultMessage: + 'Data view id references in some of the applied filters differ from the current data view.', + }), + 'data-test-subj': 'invalidFiltersWarnToast', + }); +}; + +export const useFiltersValidation = ({ + savedSearch, + filterManager, + toastNotifications, +}: { + savedSearch: SavedSearch; + filterManager: FilterManager; + toastNotifications: ToastsStart; +}) => { + useEffect(() => { + const subscription = filterManager + .getUpdates$() + .pipe(debounceTime(500)) + .subscribe(() => { + const currentFilters = filterManager.getFilters(); + const dataView = savedSearch.searchSource.getField('index'); + const areFiltersInvalid = + dataView && + !dataView.isPersisted() && + !currentFilters.every((current) => current.meta.index === dataView.id); + if (areFiltersInvalid) { + addInvalidFiltersWarn(toastNotifications); + } + }); + return () => subscription.unsubscribe(); + }, [filterManager, savedSearch.searchSource, toastNotifications]); +}; diff --git a/src/plugins/discover/public/application/main/services/discover_app_state_container.ts b/src/plugins/discover/public/application/main/services/discover_app_state_container.ts new file mode 100644 index 0000000000000..4c484698ece0f --- /dev/null +++ b/src/plugins/discover/public/application/main/services/discover_app_state_container.ts @@ -0,0 +1,16 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 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 { + createStateContainerReactHelpers, + ReduxLikeStateContainer, +} from '@kbn/kibana-utils-plugin/common'; +import { AppState } from './discover_state'; + +export const { Provider: DiscoverAppStateProvider, useSelector: useAppStateSelector } = + createStateContainerReactHelpers>(); diff --git a/src/plugins/discover/public/components/discover_grid/discover_grid.tsx b/src/plugins/discover/public/components/discover_grid/discover_grid.tsx index 1987542931676..2da63f982e305 100644 --- a/src/plugins/discover/public/components/discover_grid/discover_grid.tsx +++ b/src/plugins/discover/public/components/discover_grid/discover_grid.tsx @@ -376,7 +376,7 @@ export const DiscoverGrid = ({ }, fieldName, onSave: async () => { - onFieldEdited(); + await onFieldEdited(); }, }); } diff --git a/src/plugins/discover/public/components/doc_table/actions/columns.test.ts b/src/plugins/discover/public/components/doc_table/actions/columns.test.ts index 6e6776b8ac2e4..b8879389b4af0 100644 --- a/src/plugins/discover/public/components/doc_table/actions/columns.test.ts +++ b/src/plugins/discover/public/components/doc_table/actions/columns.test.ts @@ -13,7 +13,7 @@ import { dataViewsMock } from '../../../__mocks__/data_views'; import { Capabilities } from '@kbn/core/types'; import { AppState } from '../../../application/main/services/discover_state'; -function getStateColumnAction(state: {}, setAppState: (state: Partial) => void) { +function getStateColumnAction(state: AppState, setAppState: (state: Partial) => void) { return getStateColumnActions({ capabilities: { discover: { @@ -25,7 +25,8 @@ function getStateColumnAction(state: {}, setAppState: (state: Partial) dataViews: dataViewsMock, useNewFieldsApi: true, setAppState, - state, + columns: state.columns, + sort: state.sort, }); } diff --git a/src/plugins/discover/public/components/doc_table/actions/columns.ts b/src/plugins/discover/public/components/doc_table/actions/columns.ts index 68ff29f717d8a..36b4970b70999 100644 --- a/src/plugins/discover/public/components/doc_table/actions/columns.ts +++ b/src/plugins/discover/public/components/doc_table/actions/columns.ts @@ -9,14 +9,8 @@ import { Capabilities, IUiSettingsClient } from '@kbn/core/public'; import { DataViewsContract } from '@kbn/data-plugin/public'; import { DataView } from '@kbn/data-views-plugin/public'; import { SORT_DEFAULT_ORDER_SETTING } from '../../../../common'; -import { - AppState as DiscoverState, - GetStateReturn as DiscoverGetStateReturn, -} from '../../../application/main/services/discover_state'; -import { - AppState as ContextState, - GetStateReturn as ContextGetStateReturn, -} from '../../../application/context/services/context_state'; +import { GetStateReturn as DiscoverGetStateReturn } from '../../../application/main/services/discover_state'; +import { GetStateReturn as ContextGetStateReturn } from '../../../application/context/services/context_state'; import { popularizeField } from '../../../utils/popularize_field'; /** @@ -68,7 +62,8 @@ export function getStateColumnActions({ dataViews, useNewFieldsApi, setAppState, - state, + columns, + sort, }: { capabilities: Capabilities; config: IUiSettingsClient; @@ -76,39 +71,36 @@ export function getStateColumnActions({ dataViews: DataViewsContract; useNewFieldsApi: boolean; setAppState: DiscoverGetStateReturn['setAppState'] | ContextGetStateReturn['setAppState']; - state: DiscoverState | ContextState; + columns?: string[]; + sort: string[][] | undefined; }) { function onAddColumn(columnName: string) { popularizeField(dataView, columnName, dataViews, capabilities); - const columns = addColumn(state.columns || [], columnName, useNewFieldsApi); + const nextColumns = addColumn(columns || [], columnName, useNewFieldsApi); const defaultOrder = config.get(SORT_DEFAULT_ORDER_SETTING); - const sort = - columnName === '_score' && !state.sort?.length ? [['_score', defaultOrder]] : state.sort; - setAppState({ columns, sort }); + const nextSort = columnName === '_score' && !sort?.length ? [['_score', defaultOrder]] : sort; + setAppState({ columns: nextColumns, sort: nextSort }); } function onRemoveColumn(columnName: string) { popularizeField(dataView, columnName, dataViews, capabilities); - const columns = removeColumn(state.columns || [], columnName, useNewFieldsApi); + const nextColumns = removeColumn(columns || [], columnName, useNewFieldsApi); // The state's sort property is an array of [sortByColumn,sortDirection] - const sort = - state.sort && state.sort.length - ? state.sort.filter((subArr) => subArr[0] !== columnName) - : []; - setAppState({ columns, sort }); + const nextSort = sort && sort.length ? sort.filter((subArr) => subArr[0] !== columnName) : []; + setAppState({ columns: nextColumns, sort: nextSort }); } function onMoveColumn(columnName: string, newIndex: number) { - const columns = moveColumn(state.columns || [], columnName, newIndex); - setAppState({ columns }); + const nextColumns = moveColumn(columns || [], columnName, newIndex); + setAppState({ columns: nextColumns }); } - function onSetColumns(columns: string[], hideTimeColumn: boolean) { - // The next line should gone when classic table will be removed + function onSetColumns(nextColumns: string[], hideTimeColumn: boolean) { + // The next line should be gone when classic table will be removed const actualColumns = - !hideTimeColumn && dataView.timeFieldName && dataView.timeFieldName === columns[0] - ? columns.slice(1) - : columns; + !hideTimeColumn && dataView.timeFieldName && dataView.timeFieldName === nextColumns[0] + ? (nextColumns || []).slice(1) + : nextColumns; setAppState({ columns: actualColumns }); } diff --git a/src/plugins/discover/public/hooks/use_data_grid_columns.ts b/src/plugins/discover/public/hooks/use_data_grid_columns.ts index 91fd8487bb030..530ac62ca8d06 100644 --- a/src/plugins/discover/public/hooks/use_data_grid_columns.ts +++ b/src/plugins/discover/public/hooks/use_data_grid_columns.ts @@ -6,10 +6,11 @@ * Side Public License, v 1. */ -import { useMemo } from 'react'; +import { useEffect, useMemo, useState } from 'react'; import type { DataView, DataViewsContract } from '@kbn/data-views-plugin/public'; import { Capabilities, IUiSettingsClient } from '@kbn/core/public'; +import { isEqual } from 'lodash'; import { AppState as DiscoverState, GetStateReturn as DiscoverGetStateReturn, @@ -39,6 +40,14 @@ export const useColumns = ({ state, useNewFieldsApi, }: UseColumnsProps) => { + const [usedColumns, setUsedColumns] = useState(getColumns(state.columns, useNewFieldsApi)); + useEffect(() => { + const nextColumns = getColumns(state.columns, useNewFieldsApi); + if (isEqual(usedColumns, nextColumns)) { + return; + } + setUsedColumns(nextColumns); + }, [state.columns, useNewFieldsApi, usedColumns]); const { onAddColumn, onRemoveColumn, onSetColumns, onMoveColumn } = useMemo( () => getStateColumnActions({ @@ -47,24 +56,34 @@ export const useColumns = ({ dataView, dataViews, setAppState, - state, useNewFieldsApi, + columns: usedColumns, + sort: state.sort, }), - [capabilities, config, dataView, dataViews, setAppState, state, useNewFieldsApi] + [ + capabilities, + config, + dataView, + dataViews, + setAppState, + state.sort, + useNewFieldsApi, + usedColumns, + ] ); - const columns = useMemo(() => { - if (!state.columns) { - return []; - } - return useNewFieldsApi ? state.columns.filter((col) => col !== '_source') : state.columns; - }, [state, useNewFieldsApi]); - return { - columns, + columns: usedColumns, onAddColumn, onRemoveColumn, onMoveColumn, onSetColumns, }; }; + +function getColumns(columns: string[] | undefined, useNewFieldsApi: boolean) { + if (!columns) { + return []; + } + return useNewFieldsApi ? columns.filter((col) => col !== '_source') : columns; +} diff --git a/src/plugins/discover/public/hooks/use_navigation_props.tsx b/src/plugins/discover/public/hooks/use_navigation_props.tsx index 5cff4fe7b9ec5..cf839bda7c1a4 100644 --- a/src/plugins/discover/public/hooks/use_navigation_props.tsx +++ b/src/plugins/discover/public/hooks/use_navigation_props.tsx @@ -31,7 +31,7 @@ export const getContextHash = (columns: string[], filterManager: FilterManager) const globalFilters = filterManager.getGlobalFilters(); const appFilters = filterManager.getAppFilters(); - const hash = stringify( + return stringify( url.encodeQuery({ _g: rison.encode({ filters: globalFilters || [], @@ -43,8 +43,6 @@ export const getContextHash = (columns: string[], filterManager: FilterManager) }), { encode: false, sort: false } ); - - return hash; }; /** @@ -85,14 +83,13 @@ export const useNavigationProps = ({ () => getCurrentBreadcrumb(history?.location?.search), [history?.location?.search] ); - const contextSearchHash = useMemo( - () => getContextHash(columns, filterManager), - [columns, filterManager] - ); const singleDocHref = addBasePath( `/app/discover#/doc/${dataViewId}/${rowIndex}?id=${encodeURIComponent(rowId)}` ); + + const contextSearchHash = getContextHash(columns, filterManager); + const surDocsHref = addBasePath( `/app/discover#/context/${encodeURIComponent(dataViewId)}/${encodeURIComponent( rowId @@ -101,7 +98,7 @@ export const useNavigationProps = ({ /** * When history can be accessed via hooks, - * it is discover main or context route. + * it's used by discover main or context route. */ if (!!history) { const isContextRoute = matchPath(history.location.pathname, { diff --git a/src/plugins/guided_onboarding/common/types.ts b/src/plugins/guided_onboarding/common/types.ts index 92cc3af1ff1dd..435dd948d9f80 100644 --- a/src/plugins/guided_onboarding/common/types.ts +++ b/src/plugins/guided_onboarding/common/types.ts @@ -27,9 +27,10 @@ export type GuideStatus = 'in_progress' | 'ready_to_complete' | 'complete'; * inactive: Step has not started * active: Step is ready to start (i.e., the guide has been started) * in_progress: Step has been started and is in progress + * ready_to_complete: Step can be manually completed * complete: Step has been completed */ -export type StepStatus = 'inactive' | 'active' | 'in_progress' | 'complete'; +export type StepStatus = 'inactive' | 'active' | 'in_progress' | 'ready_to_complete' | 'complete'; export interface GuideStep { id: GuideStepIds; diff --git a/src/plugins/guided_onboarding/public/components/guide_button.tsx b/src/plugins/guided_onboarding/public/components/guide_button.tsx new file mode 100644 index 0000000000000..b4b50d78942ea --- /dev/null +++ b/src/plugins/guided_onboarding/public/components/guide_button.tsx @@ -0,0 +1,82 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 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 { EuiButton } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { GuideState } from '../../common/types'; +import { getStepConfig } from '../services/helpers'; +import { GuideButtonPopover } from './guide_button_popover'; + +interface GuideButtonProps { + guideState: GuideState; + toggleGuidePanel: () => void; + isGuidePanelOpen: boolean; +} + +const getStepNumber = (state: GuideState): number | undefined => { + let stepNumber: number | undefined; + + state.steps.forEach((step, stepIndex) => { + // If the step is in_progress or ready_to_complete, show that step number + if (step.status === 'in_progress' || step.status === 'ready_to_complete') { + stepNumber = stepIndex + 1; + } + + // If the step is active, show the previous step number + if (step.status === 'active') { + stepNumber = stepIndex; + } + }); + + return stepNumber; +}; + +export const GuideButton = ({ + guideState, + toggleGuidePanel, + isGuidePanelOpen, +}: GuideButtonProps) => { + const stepNumber = getStepNumber(guideState); + const stepReadyToComplete = guideState.steps.find((step) => step.status === 'ready_to_complete'); + const button = ( + + {Boolean(stepNumber) + ? i18n.translate('guidedOnboarding.guidedSetupStepButtonLabel', { + defaultMessage: 'Setup guide: step {stepNumber}', + values: { + stepNumber, + }, + }) + : i18n.translate('guidedOnboarding.guidedSetupButtonLabel', { + defaultMessage: 'Setup guide', + })} + + ); + if (stepReadyToComplete) { + const stepConfig = getStepConfig(guideState.guideId, stepReadyToComplete.id); + // check if the stepConfig has manualCompletion info + if (stepConfig && stepConfig.manualCompletion) { + return ( + + ); + } + } + return button; +}; diff --git a/src/plugins/guided_onboarding/public/components/guide_button_popover.tsx b/src/plugins/guided_onboarding/public/components/guide_button_popover.tsx new file mode 100644 index 0000000000000..fe341108f089e --- /dev/null +++ b/src/plugins/guided_onboarding/public/components/guide_button_popover.tsx @@ -0,0 +1,55 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 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 { useEffect, useRef, useState } from 'react'; +import { EuiPopover, EuiSpacer, EuiText, EuiTitle } from '@elastic/eui'; +import React from 'react'; + +interface GuideButtonPopoverProps { + button: EuiPopover['button']; + isGuidePanelOpen: boolean; + title?: string; + description?: string; +} +export const GuideButtonPopover = ({ + button, + isGuidePanelOpen, + title, + description, +}: GuideButtonPopoverProps) => { + const isFirstRender = useRef(true); + useEffect(() => { + isFirstRender.current = false; + }, []); + + const [isPopoverShown, setIsPopoverShown] = useState(true); + useEffect(() => { + // close the popover after it was rendered once and the panel is opened + if (isGuidePanelOpen && !isFirstRender.current) { + setIsPopoverShown(false); + } + }, [isGuidePanelOpen]); + return ( + { + /* do nothing, the popover is closed once the panel is opened */ + }} + > + {title && ( + +

{title}

+
+ )} + + {description &&

{description}

}
+
+ ); +}; diff --git a/src/plugins/guided_onboarding/public/components/guide_panel.test.tsx b/src/plugins/guided_onboarding/public/components/guide_panel.test.tsx index 3506c15fcba35..268117f8af570 100644 --- a/src/plugins/guided_onboarding/public/components/guide_panel.test.tsx +++ b/src/plugins/guided_onboarding/public/components/guide_panel.test.tsx @@ -41,6 +41,45 @@ const mockActiveSearchGuideState: GuideState = { ], }; +const mockInProgressSearchGuideState: GuideState = { + ...mockActiveSearchGuideState, + steps: [ + { + id: mockActiveSearchGuideState.steps[0].id, + status: 'in_progress', + }, + mockActiveSearchGuideState.steps[1], + mockActiveSearchGuideState.steps[2], + ], +}; + +const mockReadyToCompleteSearchGuideState: GuideState = { + ...mockActiveSearchGuideState, + steps: [ + { + id: mockActiveSearchGuideState.steps[0].id, + status: 'complete', + }, + { + id: mockActiveSearchGuideState.steps[1].id, + status: 'ready_to_complete', + }, + mockActiveSearchGuideState.steps[2], + ], +}; + +const updateComponentWithState = async ( + component: TestBed['component'], + guideState: GuideState, + isPanelOpen: boolean +) => { + await act(async () => { + await apiService.updateGuideState(guideState, isPanelOpen); + }); + + component.update(); +}; + const getGuidePanel = () => () => { return ; }; @@ -80,12 +119,8 @@ describe('Guided setup', () => { test('should be enabled if there is an active guide', async () => { const { exists, component, find } = testBed; - await act(async () => { - // Enable the "search" guide - await apiService.updateGuideState(mockActiveSearchGuideState, true); - }); - - component.update(); + // Enable the "search" guide + await updateComponentWithState(component, mockActiveSearchGuideState, true); expect(exists('disabledGuideButton')).toBe(false); expect(exists('guideButton')).toBe(true); @@ -95,25 +130,33 @@ describe('Guided setup', () => { test('should show the step number in the button label if a step is active', async () => { const { component, find } = testBed; - const mockInProgressSearchGuideState: GuideState = { - ...mockActiveSearchGuideState, - steps: [ - { - id: mockActiveSearchGuideState.steps[0].id, - status: 'in_progress', - }, - mockActiveSearchGuideState.steps[1], - mockActiveSearchGuideState.steps[2], - ], - }; + await updateComponentWithState(component, mockInProgressSearchGuideState, true); - await act(async () => { - await apiService.updateGuideState(mockInProgressSearchGuideState, true); - }); + expect(find('guideButton').text()).toEqual('Setup guide: step 1'); + }); - component.update(); + test('shows the step number in the button label if a step is ready to complete', async () => { + const { component, find } = testBed; - expect(find('guideButton').text()).toEqual('Setup guide: step 1'); + await updateComponentWithState(component, mockReadyToCompleteSearchGuideState, true); + + expect(find('guideButton').text()).toEqual('Setup guide: step 2'); + }); + + test('shows the manual completion popover if a step is ready to complete', async () => { + const { component, exists } = testBed; + + await updateComponentWithState(component, mockReadyToCompleteSearchGuideState, false); + + expect(exists('manualCompletionPopover')).toBe(true); + }); + + test('shows no manual completion popover if a step is in progress', async () => { + const { component, exists } = testBed; + + await updateComponentWithState(component, mockInProgressSearchGuideState, false); + + expect(exists('manualCompletionPopoverPanel')).toBe(false); }); }); @@ -121,12 +164,7 @@ describe('Guided setup', () => { test('should be enabled if a guide is activated', async () => { const { exists, component, find } = testBed; - await act(async () => { - // Enable the "search" guide - await apiService.updateGuideState(mockActiveSearchGuideState, true); - }); - - component.update(); + await updateComponentWithState(component, mockActiveSearchGuideState, true); expect(exists('guidePanel')).toBe(true); expect(exists('guideProgress')).toBe(false); @@ -136,7 +174,7 @@ describe('Guided setup', () => { test('should show the progress bar if the first step has been completed', async () => { const { component, exists } = testBed; - const mockInProgressSearchGuideState: GuideState = { + const mockCompleteSearchGuideState: GuideState = { ...mockActiveSearchGuideState, steps: [ { @@ -148,11 +186,7 @@ describe('Guided setup', () => { ], }; - await act(async () => { - await apiService.updateGuideState(mockInProgressSearchGuideState, true); - }); - - component.update(); + await updateComponentWithState(component, mockCompleteSearchGuideState, true); expect(exists('guidePanel')).toBe(true); expect(exists('guideProgress')).toBe(true); @@ -181,11 +215,7 @@ describe('Guided setup', () => { ], }; - await act(async () => { - await apiService.updateGuideState(readyToCompleteGuideState, true); - }); - - component.update(); + await updateComponentWithState(component, readyToCompleteGuideState, true); expect(exists('useElasticButton')).toBe(true); }); @@ -194,6 +224,32 @@ describe('Guided setup', () => { test('should show "Start" button label if step has not been started', async () => { const { component, find } = testBed; + await updateComponentWithState(component, mockActiveSearchGuideState, true); + + expect(find('activeStepButtonLabel').text()).toEqual('Start'); + }); + + test('should show "Continue" button label if step is in progress', async () => { + const { component, find } = testBed; + + await updateComponentWithState(component, mockInProgressSearchGuideState, true); + + expect(find('activeStepButtonLabel').text()).toEqual('Continue'); + }); + + test('shows "Mark done" button label if step is ready to complete', async () => { + const { component, find } = testBed; + + await updateComponentWithState(component, mockReadyToCompleteSearchGuideState, true); + + expect(find('activeStepButtonLabel').text()).toEqual('Mark done'); + }); + }); + + describe('Quit guide modal', () => { + beforeEach(async () => { + const { component, find, exists } = testBed; + await act(async () => { // Enable the "search" guide await apiService.updateGuideState(mockActiveSearchGuideState, true); @@ -201,31 +257,41 @@ describe('Guided setup', () => { component.update(); - expect(find('activeStepButtonLabel').text()).toEqual('Start'); + await act(async () => { + find('quitGuideButton').simulate('click'); + }); + + component.update(); + + expect(exists('quitGuideModal')).toBe(true); }); - test('should show "Continue" button label if step is in progress', async () => { - const { component, find } = testBed; + test('quit a guide', async () => { + const { component, find, exists } = testBed; + + await act(async () => { + find('confirmModalConfirmButton').simulate('click'); + }); - const mockInProgressSearchGuideState: GuideState = { - ...mockActiveSearchGuideState, - steps: [ - { - id: mockActiveSearchGuideState.steps[0].id, - status: 'in_progress', - }, - mockActiveSearchGuideState.steps[1], - mockActiveSearchGuideState.steps[2], - ], - }; + component.update(); + + expect(exists('quitGuideModal')).toBe(false); + // For now, the guide button is disabled once a user quits a guide + // This behavior will change once https://github.com/elastic/kibana/issues/141129 is implemented + expect(exists('disabledGuideButton')).toBe(true); + }); + + test('cancels out of the quit guide confirmation modal', async () => { + const { component, find, exists } = testBed; await act(async () => { - await apiService.updateGuideState(mockInProgressSearchGuideState, true); + find('confirmModalCancelButton').simulate('click'); }); component.update(); - expect(find('activeStepButtonLabel').text()).toEqual('Continue'); + expect(exists('quitGuideModal')).toBe(false); + expect(exists('guideButton')).toBe(true); }); }); }); diff --git a/src/plugins/guided_onboarding/public/components/guide_panel.tsx b/src/plugins/guided_onboarding/public/components/guide_panel.tsx index bf57d502918d2..84726825240a3 100644 --- a/src/plugins/guided_onboarding/public/components/guide_panel.tsx +++ b/src/plugins/guided_onboarding/public/components/guide_panel.tsx @@ -26,49 +26,27 @@ import { useEuiTheme, } from '@elastic/eui'; -import { ApplicationStart } from '@kbn/core-application-browser'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; -import { guidesConfig } from '../constants/guides_config'; -import type { GuideState, GuideStepIds } from '../../common/types'; -import type { GuideConfig, StepConfig } from '../types'; + +import { ApplicationStart } from '@kbn/core/public'; + +import type { GuideState, GuideStep as GuideStepStatus } from '../../common/types'; +import type { StepConfig } from '../types'; import type { ApiService } from '../services/api'; +import { getGuideConfig } from '../services/helpers'; import { GuideStep } from './guide_panel_step'; +import { QuitGuideModal } from './quit_guide_modal'; import { getGuidePanelStyles } from './guide_panel.styles'; +import { GuideButton } from './guide_button'; interface GuidePanelProps { api: ApiService; application: ApplicationStart; } -const getConfig = (state?: GuideState): GuideConfig | undefined => { - if (state) { - return guidesConfig[state.guideId]; - } - - return undefined; -}; - -const getStepNumber = (state?: GuideState): number | undefined => { - let stepNumber: number | undefined; - - state?.steps.forEach((step, stepIndex) => { - // If the step is in_progress, show that step number - if (step.status === 'in_progress') { - stepNumber = stepIndex + 1; - } - - // If the step is active, show the previous step number - if (step.status === 'active') { - stepNumber = stepIndex; - } - }); - - return stepNumber; -}; - const getProgress = (state?: GuideState): number => { if (state) { return state.steps.reduce((acc, currentVal) => { @@ -84,6 +62,7 @@ const getProgress = (state?: GuideState): number => { export const GuidePanel = ({ api, application }: GuidePanelProps) => { const { euiTheme } = useEuiTheme(); const [isGuideOpen, setIsGuideOpen] = useState(false); + const [isQuitGuideModalOpen, setIsQuitGuideModalOpen] = useState(false); const [guideState, setGuideState] = useState(undefined); const styles = getGuidePanelStyles(euiTheme); @@ -92,10 +71,26 @@ export const GuidePanel = ({ api, application }: GuidePanelProps) => { setIsGuideOpen((prevIsGuideOpen) => !prevIsGuideOpen); }; - const navigateToStep = async (stepId: GuideStepIds, stepLocation: StepConfig['location']) => { - await api.startGuideStep(guideState!.guideId, stepId); - if (stepLocation) { - application.navigateToApp(stepLocation.appID, { path: stepLocation.path }); + const handleStepButtonClick = async (step: GuideStepStatus, stepConfig: StepConfig) => { + if (guideState) { + const { id, status } = step; + if (status === 'ready_to_complete') { + return await api.completeGuideStep(guideState?.guideId, id); + } + + if (status === 'active') { + await api.startGuideStep(guideState!.guideId, id); + } + if (status === 'active' || status === 'in_progress') { + if (stepConfig.location) { + await application.navigateToApp(stepConfig.location.appID, { + path: stepConfig.location.path, + }); + if (stepConfig.manualCompletion?.readyToCompleteOnNavigation) { + await api.completeGuideStep(guideState.guideId, id); + } + } + } } }; @@ -108,11 +103,20 @@ export const GuidePanel = ({ api, application }: GuidePanelProps) => { await api.completeGuide(guideState!.guideId); }; + const openQuitGuideModal = () => { + // Close the dropdown panel + setIsGuideOpen(false); + // Open the confirmation modal + setIsQuitGuideModalOpen(true); + }; + + const closeQuitGuideModal = () => { + setIsQuitGuideModalOpen(false); + }; + useEffect(() => { const subscription = api.fetchActiveGuideState$().subscribe((newGuideState) => { - if (newGuideState) { - setGuideState(newGuideState); - } + setGuideState(newGuideState); }); return () => subscription.unsubscribe(); }, [api]); @@ -124,7 +128,7 @@ export const GuidePanel = ({ api, application }: GuidePanelProps) => { return () => subscription.unsubscribe(); }, [api]); - const guideConfig = getConfig(guideState); + const guideConfig = getGuideConfig(guideState?.guideId); // TODO handle loading, error state // https://github.com/elastic/kibana/issues/139799, https://github.com/elastic/kibana/issues/139798 @@ -145,23 +149,15 @@ export const GuidePanel = ({ api, application }: GuidePanelProps) => { ); } - const stepNumber = getStepNumber(guideState); const stepsCompleted = getProgress(guideState); return ( <> - - {Boolean(stepNumber) - ? i18n.translate('guidedOnboarding.guidedSetupStepButtonLabel', { - defaultMessage: 'Setup guide: step {stepNumber}', - values: { - stepNumber, - }, - }) - : i18n.translate('guidedOnboarding.guidedSetupButtonLabel', { - defaultMessage: 'Setup guide', - })} - + {isGuideOpen && ( { - {guideConfig?.steps.map((step, index, steps) => { + {guideConfig?.steps.map((step, index) => { const accordionId = htmlIdGenerator(`accordion${index}`)(); const stepState = guideState?.steps[index]; @@ -247,7 +243,7 @@ export const GuidePanel = ({ api, application }: GuidePanelProps) => { stepStatus={stepState.status} stepConfig={step} stepNumber={index + 1} - navigateToStep={navigateToStep} + handleButtonClick={() => handleStepButtonClick(stepState, step)} key={accordionId} /> ); @@ -271,10 +267,9 @@ export const GuidePanel = ({ api, application }: GuidePanelProps) => { - {/* TODO: Implement exit guide modal - https://github.com/elastic/kibana/issues/139804 */} - {}}> + {i18n.translate('guidedOnboarding.dropdownPanel.footer.exitGuideButtonLabel', { - defaultMessage: 'Exit setup guide', + defaultMessage: 'Quit setup guide', })} @@ -325,6 +320,10 @@ export const GuidePanel = ({ api, application }: GuidePanelProps) => { )} + + {isQuitGuideModalOpen && ( + + )} ); }; diff --git a/src/plugins/guided_onboarding/public/components/guide_panel_step.tsx b/src/plugins/guided_onboarding/public/components/guide_panel_step.tsx index c05ad6ec310c7..107babb6ac0d8 100644 --- a/src/plugins/guided_onboarding/public/components/guide_panel_step.tsx +++ b/src/plugins/guided_onboarding/public/components/guide_panel_step.tsx @@ -20,7 +20,8 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import type { StepStatus, GuideStepIds } from '../../common/types'; + +import type { StepStatus } from '../../common/types'; import type { StepConfig } from '../types'; import { getGuidePanelStepStyles } from './guide_panel_step.styles'; @@ -29,7 +30,7 @@ interface GuideStepProps { stepStatus: StepStatus; stepConfig: StepConfig; stepNumber: number; - navigateToStep: (stepId: GuideStepIds, stepLocation: StepConfig['location']) => void; + handleButtonClick: () => void; } export const GuideStep = ({ @@ -37,7 +38,7 @@ export const GuideStep = ({ stepStatus, stepNumber, stepConfig, - navigateToStep, + handleButtonClick, }: GuideStepProps) => { const { euiTheme } = useEuiTheme(); const styles = getGuidePanelStepStyles(euiTheme, stepStatus); @@ -58,6 +59,26 @@ export const GuideStep = ({
); + const isAccordionOpen = + stepStatus === 'in_progress' || stepStatus === 'active' || stepStatus === 'ready_to_complete'; + + const getStepButtonLabel = (): string => { + switch (stepStatus) { + case 'active': + return i18n.translate('guidedOnboarding.dropdownPanel.startStepButtonLabel', { + defaultMessage: 'Start', + }); + case 'in_progress': + return i18n.translate('guidedOnboarding.dropdownPanel.continueStepButtonLabel', { + defaultMessage: 'Continue', + }); + case 'ready_to_complete': + return i18n.translate('guidedOnboarding.dropdownPanel.markDoneStepButtonLabel', { + defaultMessage: 'Mark done', + }); + } + return ''; + }; return (
@@ -68,7 +89,7 @@ export const GuideStep = ({ id={accordionId} buttonContent={stepTitleContent} arrowDisplay="right" - initialIsOpen={stepStatus === 'in_progress' || stepStatus === 'active'} + initialIsOpen={isAccordionOpen} > <> @@ -82,21 +103,15 @@ export const GuideStep = ({ - {(stepStatus === 'in_progress' || stepStatus === 'active') && ( + {isAccordionOpen && ( navigateToStep(stepConfig.id, stepConfig.location)} + onClick={() => handleButtonClick()} fill data-test-subj="activeStepButtonLabel" > - {stepStatus === 'active' - ? i18n.translate('guidedOnboarding.dropdownPanel.startStepButtonLabel', { - defaultMessage: 'Start', - }) - : i18n.translate('guidedOnboarding.dropdownPanel.continueStepButtonLabel', { - defaultMessage: 'Continue', - })} + {getStepButtonLabel()} diff --git a/src/plugins/guided_onboarding/public/components/quit_guide_modal.tsx b/src/plugins/guided_onboarding/public/components/quit_guide_modal.tsx new file mode 100644 index 0000000000000..a7a7e34c311b4 --- /dev/null +++ b/src/plugins/guided_onboarding/public/components/quit_guide_modal.tsx @@ -0,0 +1,58 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 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, { useState } from 'react'; + +import { EuiText, EuiConfirmModal } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { GuideState } from '../../common/types'; +import { apiService } from '../services/api'; + +interface QuitGuideModalProps { + closeModal: () => void; + currentGuide: GuideState; +} + +export const QuitGuideModal = ({ closeModal, currentGuide }: QuitGuideModalProps) => { + const [isDeleting, setIsDeleting] = useState(false); + + const deleteGuide = async () => { + setIsDeleting(true); + await apiService.deactivateGuide(currentGuide); + closeModal(); + }; + + return ( + + +

+ {i18n.translate('guidedOnboarding.quitGuideModal.modalDescription', { + defaultMessage: + 'You can restart anytime by opening the Setup guide from the Help menu.', + })} +

+
+
+ ); +}; diff --git a/src/plugins/guided_onboarding/public/constants/guides_config/observability.ts b/src/plugins/guided_onboarding/public/constants/guides_config/observability.ts index 91b69490131b3..9fedb88af2253 100644 --- a/src/plugins/guided_onboarding/public/constants/guides_config/observability.ts +++ b/src/plugins/guided_onboarding/public/constants/guides_config/observability.ts @@ -9,31 +9,31 @@ import type { GuideConfig } from '../../types'; export const observabilityConfig: GuideConfig = { - title: 'Observe my infrastructure', - description: - 'The foundation of seeing Elastic in action, is adding you own data. Follow links to our documents below to learn more.', + title: 'Observe my Kubernetes infrastructure', + description: `We'll help you quickly gain visibility into your Kubernetes environment using Elastic's out-of-the-box integration. Gain deep insights from your logs, metrics, and traces, and proactively detect issues and take action to resolve issues.`, docs: { - text: 'Observability 101 Documentation', - url: 'example.com', + text: 'Kubernetes documentation', + url: 'example.com', // TODO update link to correct docs page }, steps: [ { id: 'add_data', title: 'Add data', - descriptionList: [ - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.', - 'Nullam ligula enim, malesuada a finibus vel, cursus sed risus.', - 'Vivamus pretium, elit dictum lacinia aliquet, libero nibh dictum enim, a rhoncus leo magna in sapien.', - ], + integration: 'kubernetes', + descriptionList: ['Start by adding your data by setting up the Kubernetes integration.'], + location: { + appID: 'integrations', + path: '/detail/kubernetes/overview', + }, }, { id: 'view_dashboard', - title: 'View Kubernetes metrics', - descriptionList: [ - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.', - 'Nullam ligula enim, malesuada a finibus vel, cursus sed risus.', - 'Vivamus pretium, elit dictum lacinia aliquet, libero nibh dictum enim, a rhoncus leo magna in sapien.', - ], + title: 'Explore Kubernetes metrics', + descriptionList: ['Stream, visualize, and analyze your Kubernetes infrastructure metrics.'], + location: { + appID: 'dashboards', + path: '#/view/kubernetes-e0195ce0-bcaf-11ec-b64f-7dd6e8e82013', + }, }, { id: 'tour_observability', diff --git a/src/plugins/guided_onboarding/public/constants/guides_config/search.ts b/src/plugins/guided_onboarding/public/constants/guides_config/search.ts index 57d81fdfe1301..3c083a3bd96c1 100644 --- a/src/plugins/guided_onboarding/public/constants/guides_config/search.ts +++ b/src/plugins/guided_onboarding/public/constants/guides_config/search.ts @@ -25,8 +25,8 @@ export const searchConfig: GuideConfig = { 'Vivamus pretium, elit dictum lacinia aliquet, libero nibh dictum enim, a rhoncus leo magna in sapien.', ], location: { - appID: 'guidedOnboardingExample', - path: 'stepOne', + appID: 'enterpriseSearch', + path: '', }, }, { @@ -41,6 +41,12 @@ export const searchConfig: GuideConfig = { appID: 'guidedOnboardingExample', path: 'stepTwo', }, + manualCompletion: { + title: 'Manual completion step title', + description: + 'Mark the step complete by opening the panel and clicking the button "Mark done"', + readyToCompleteOnNavigation: true, + }, }, { id: 'search_experience', diff --git a/src/plugins/guided_onboarding/public/constants/guides_config/security.ts b/src/plugins/guided_onboarding/public/constants/guides_config/security.ts index 8eafa3b51c408..e67e318a61f01 100644 --- a/src/plugins/guided_onboarding/public/constants/guides_config/security.ts +++ b/src/plugins/guided_onboarding/public/constants/guides_config/security.ts @@ -35,6 +35,11 @@ export const securityConfig: GuideConfig = { 'Nullam ligula enim, malesuada a finibus vel, cursus sed risus.', 'Vivamus pretium, elit dictum lacinia aliquet, libero nibh dictum enim, a rhoncus leo magna in sapien.', ], + manualCompletion: { + title: 'Manual completion step title', + description: + 'Mark the step complete by opening the panel and clicking the button "Mark done"', + }, }, { id: 'alertsCases', diff --git a/src/plugins/guided_onboarding/public/services/api.mocks.ts b/src/plugins/guided_onboarding/public/services/api.mocks.ts index 19dd67c7d7b1b..ed2985a1dd74a 100644 --- a/src/plugins/guided_onboarding/public/services/api.mocks.ts +++ b/src/plugins/guided_onboarding/public/services/api.mocks.ts @@ -28,26 +28,6 @@ export const searchAddDataActiveState: GuideState = { ], }; -export const searchAddDataInProgressState: GuideState = { - isActive: true, - status: 'in_progress', - steps: [ - { - id: 'add_data', - status: 'in_progress', - }, - { - id: 'browse_docs', - status: 'inactive', - }, - { - id: 'search_experience', - status: 'inactive', - }, - ], - guideId: 'search', -}; - export const securityAddDataInProgressState: GuideState = { guideId: 'security', status: 'in_progress', @@ -61,10 +41,14 @@ export const securityAddDataInProgressState: GuideState = { id: 'rules', status: 'inactive', }, + { + id: 'alertsCases', + status: 'inactive', + }, ], }; -export const securityRulesActivesState: GuideState = { +export const securityRulesActiveState: GuideState = { guideId: 'security', isActive: true, status: 'in_progress', @@ -77,6 +61,10 @@ export const securityRulesActivesState: GuideState = { id: 'rules', status: 'active', }, + { + id: 'alertsCases', + status: 'inactive', + }, ], }; @@ -93,5 +81,9 @@ export const noGuideActiveState: GuideState = { id: 'rules', status: 'inactive', }, + { + id: 'alertsCases', + status: 'inactive', + }, ], }; diff --git a/src/plugins/guided_onboarding/public/services/api.test.ts b/src/plugins/guided_onboarding/public/services/api.test.ts index fad2a01d79891..8765af0fb07f6 100644 --- a/src/plugins/guided_onboarding/public/services/api.test.ts +++ b/src/plugins/guided_onboarding/public/services/api.test.ts @@ -18,7 +18,7 @@ import { noGuideActiveState, searchAddDataActiveState, securityAddDataInProgressState, - securityRulesActivesState, + securityRulesActiveState, } from './api.mocks'; const searchGuide = 'search'; @@ -72,6 +72,20 @@ describe('GuidedOnboarding ApiService', () => { }); }); + describe('deactivateGuide', () => { + it('deactivates an existing guide', async () => { + await apiService.deactivateGuide(searchAddDataActiveState); + + expect(httpClient.put).toHaveBeenCalledTimes(1); + expect(httpClient.put).toHaveBeenCalledWith(`${API_BASE_PATH}/state`, { + body: JSON.stringify({ + ...searchAddDataActiveState, + isActive: false, + }), + }); + }); + }); + describe('updateGuideState', () => { it('sends a request to the put API', async () => { const updatedState: GuideState = { @@ -301,17 +315,58 @@ describe('GuidedOnboarding ApiService', () => { }); }); + it(`marks the step as 'ready_to_complete' if it's configured for manual completion`, async () => { + const securityRulesInProgressState = { + ...securityRulesActiveState, + steps: [ + securityRulesActiveState.steps[0], + { + id: securityRulesActiveState.steps[1].id, + status: 'in_progress', + }, + securityRulesActiveState.steps[2], + ], + }; + httpClient.get.mockResolvedValue({ + state: [securityRulesInProgressState], + }); + apiService.setup(httpClient); + + await apiService.completeGuideStep('security', 'rules'); + + expect(httpClient.put).toHaveBeenCalledTimes(1); + // Verify the completed step now has a "ready_to_complete" status, and the subsequent step is "inactive" + expect(httpClient.put).toHaveBeenLastCalledWith(`${API_BASE_PATH}/state`, { + body: JSON.stringify({ + ...securityRulesInProgressState, + steps: [ + securityRulesInProgressState.steps[0], + { + id: securityRulesInProgressState.steps[1].id, + status: 'ready_to_complete', + }, + { + id: securityRulesInProgressState.steps[2].id, + status: 'inactive', + }, + ], + }), + }); + }); + it('returns undefined if the selected guide is not active', async () => { const startState = await apiService.completeGuideStep('observability', 'add_data'); // not active expect(startState).not.toBeDefined(); }); it('does nothing if the step is not in progress', async () => { - await apiService.updateGuideState(searchAddDataActiveState, false); + httpClient.get.mockResolvedValue({ + state: [searchAddDataActiveState], + }); + apiService.setup(httpClient); await apiService.completeGuideStep(searchGuide, firstStep); - // Expect only 1 call from updateGuideState() - expect(httpClient.put).toHaveBeenCalledTimes(1); + expect(httpClient.put).toHaveBeenCalledTimes(0); }); }); @@ -370,7 +425,7 @@ describe('GuidedOnboarding ApiService', () => { expect(httpClient.put).toHaveBeenCalledTimes(1); // this assertion depends on the guides config expect(httpClient.put).toHaveBeenCalledWith(`${API_BASE_PATH}/state`, { - body: JSON.stringify(securityRulesActivesState), + body: JSON.stringify(securityRulesActiveState), }); }); diff --git a/src/plugins/guided_onboarding/public/services/api.ts b/src/plugins/guided_onboarding/public/services/api.ts index 9ffe13bbbb63f..7895f9f2a7f24 100644 --- a/src/plugins/guided_onboarding/public/services/api.ts +++ b/src/plugins/guided_onboarding/public/services/api.ts @@ -13,8 +13,12 @@ import { GuidedOnboardingApi } from '../types'; import { getGuideConfig, getInProgressStepId, + getStepConfig, + getUpdatedSteps, isIntegrationInGuideStep, isLastStep, + isStepInProgress, + isStepReadyToComplete, } from './helpers'; import { API_BASE_PATH } from '../../common/constants'; import type { GuideState, GuideId, GuideStep, GuideStepIds } from '../../common/types'; @@ -95,7 +99,8 @@ export class ApiService implements GuidedOnboardingApi { const response = await this.client.put<{ state: GuideState }>(`${API_BASE_PATH}/state`, { body: JSON.stringify(newState), }); - this.onboardingGuideState$.next(newState); + // If the guide has been deactivated, we return undefined + this.onboardingGuideState$.next(newState.isActive ? newState : undefined); this.isGuidePanelOpen$.next(panelState); return response; } catch (error) { @@ -152,6 +157,22 @@ export class ApiService implements GuidedOnboardingApi { } } + /** + * Marks a guide as inactive + * This is useful for the dropdown panel, when a user quits a guide + * @param {GuideState} guide (optional) the selected guide state, if it exists (i.e., if a user is continuing a guide) + * @return {Promise} a promise with the updated guide state + */ + public async deactivateGuide(guide: GuideState): Promise<{ state: GuideState } | undefined> { + return await this.updateGuideState( + { + ...guide, + isActive: false, + }, + false + ); + } + /** * Completes a guide * Updates the overall guide status to 'complete', and marks it as inactive @@ -193,16 +214,7 @@ export class ApiService implements GuidedOnboardingApi { */ public isGuideStepActive$(guideId: GuideId, stepId: GuideStepIds): Observable { return this.fetchActiveGuideState$().pipe( - map((activeGuideState) => { - // Return false right away if the guide itself is not active - if (activeGuideState?.guideId !== guideId) { - return false; - } - - // If the guide is active, next check the step - const selectedStep = activeGuideState.steps.find((step) => step.id === stepId); - return selectedStep ? selectedStep.status === 'in_progress' : false; - }) + map((activeGuideState) => isStepInProgress(activeGuideState, guideId, stepId)) ); } @@ -265,34 +277,20 @@ export class ApiService implements GuidedOnboardingApi { return undefined; } - const currentStepIndex = guideState.steps.findIndex((step) => step.id === stepId); - const currentStep = guideState.steps[currentStepIndex]; - const isCurrentStepInProgress = currentStep ? currentStep.status === 'in_progress' : false; - - if (isCurrentStepInProgress) { - const updatedSteps: GuideStep[] = guideState.steps.map((step, stepIndex) => { - const isCurrentStep = step.id === currentStep!.id; - const isNextStep = stepIndex === currentStepIndex + 1; - - // Mark the current step as complete - if (isCurrentStep) { - return { - id: step.id, - status: 'complete', - }; - } + const isCurrentStepInProgress = isStepInProgress(guideState, guideId, stepId); + const isCurrentStepReadyToComplete = isStepReadyToComplete(guideState, guideId, stepId); - // Update the next step to active status - if (isNextStep) { - return { - id: step.id, - status: 'active', - }; - } + const stepConfig = getStepConfig(guideState.guideId, stepId); + const isManualCompletion = stepConfig ? !!stepConfig.manualCompletion : false; - // All other steps return as-is - return step; - }); + if (isCurrentStepInProgress || isCurrentStepReadyToComplete) { + const updatedSteps = getUpdatedSteps( + guideState, + stepId, + // if current step is in progress and configured for manual completion, + // set the status to ready_to_complete + isManualCompletion && isCurrentStepInProgress + ); const currentGuide: GuideState = { guideId, @@ -301,7 +299,13 @@ export class ApiService implements GuidedOnboardingApi { steps: updatedSteps, }; - return await this.updateGuideState(currentGuide, true); + return await this.updateGuideState( + currentGuide, + // the panel is opened when the step is being set to complete. + // that happens when the step is not configured for manual completion + // or it's already ready_to_complete + !isManualCompletion || isCurrentStepReadyToComplete + ); } return undefined; diff --git a/src/plugins/guided_onboarding/public/services/helpers.test.ts b/src/plugins/guided_onboarding/public/services/helpers.test.ts index 586566fe9488b..9dc7519a02019 100644 --- a/src/plugins/guided_onboarding/public/services/helpers.test.ts +++ b/src/plugins/guided_onboarding/public/services/helpers.test.ts @@ -11,7 +11,7 @@ import { isIntegrationInGuideStep, isLastStep } from './helpers'; import { noGuideActiveState, securityAddDataInProgressState, - securityRulesActivesState, + securityRulesActiveState, } from './api.mocks'; const searchGuide = 'search'; @@ -42,7 +42,7 @@ describe('GuidedOnboarding ApiService helpers', () => { expect(result).toBe(false); }); it('returns false if no integration is defined in the guide step', () => { - const result = isIntegrationInGuideStep(securityRulesActivesState, 'endpoint'); + const result = isIntegrationInGuideStep(securityRulesActiveState, 'endpoint'); expect(result).toBe(false); }); it('returns false if no guide is active', () => { diff --git a/src/plugins/guided_onboarding/public/services/helpers.ts b/src/plugins/guided_onboarding/public/services/helpers.ts index 0e738646c558d..30fbd5051215b 100644 --- a/src/plugins/guided_onboarding/public/services/helpers.ts +++ b/src/plugins/guided_onboarding/public/services/helpers.ts @@ -9,24 +9,30 @@ import type { GuideId, GuideState, GuideStepIds } from '../../common/types'; import { guidesConfig } from '../constants/guides_config'; import { GuideConfig, StepConfig } from '../types'; +import { GuideStep } from '../../common/types'; -export const getGuideConfig = (guideID?: string): GuideConfig | undefined => { - if (guideID && Object.keys(guidesConfig).includes(guideID)) { - return guidesConfig[guideID as GuideId]; +export const getGuideConfig = (guideId?: GuideId): GuideConfig | undefined => { + if (guideId && Object.keys(guidesConfig).includes(guideId)) { + return guidesConfig[guideId]; } }; -const getStepIndex = (guideID: string, stepID: string): number => { - const guide = getGuideConfig(guideID); +export const getStepConfig = (guideId: GuideId, stepId: GuideStepIds): StepConfig | undefined => { + const guideConfig = getGuideConfig(guideId); + return guideConfig?.steps.find((step) => step.id === stepId); +}; + +const getStepIndex = (guideId: GuideId, stepId: GuideStepIds): number => { + const guide = getGuideConfig(guideId); if (guide) { - return guide.steps.findIndex((step: StepConfig) => step.id === stepID); + return guide.steps.findIndex((step: StepConfig) => step.id === stepId); } return -1; }; -export const isLastStep = (guideID: string, stepID: string): boolean => { - const guide = getGuideConfig(guideID); - const activeStepIndex = getStepIndex(guideID, stepID); +export const isLastStep = (guideId: GuideId, stepId: GuideStepIds): boolean => { + const guide = getGuideConfig(guideId); + const activeStepIndex = getStepIndex(guideId, stepId); const stepsNumber = guide?.steps.length || 0; if (stepsNumber > 0) { return activeStepIndex === stepsNumber - 1; @@ -56,3 +62,70 @@ export const isIntegrationInGuideStep = (state: GuideState, integration?: string } return false; }; + +const isGuideActive = (guideState: GuideState | undefined, guideId: GuideId): boolean => { + // false if guideState is undefined or the guide is not active + return !!(guideState && guideState.isActive && guideState.guideId === guideId); +}; + +export const isStepInProgress = ( + guideState: GuideState | undefined, + guideId: GuideId, + stepId: GuideStepIds +): boolean => { + if (!isGuideActive(guideState, guideId)) { + return false; + } + + // false if the step is not 'in_progress' + const selectedStep = guideState!.steps.find((step) => step.id === stepId); + return selectedStep ? selectedStep.status === 'in_progress' : false; +}; + +export const isStepReadyToComplete = ( + guideState: GuideState | undefined, + guideId: GuideId, + stepId: GuideStepIds +): boolean => { + if (!isGuideActive(guideState, guideId)) { + return false; + } + + // false if the step is not 'ready_to_complete' + const selectedStep = guideState!.steps.find((step) => step.id === stepId); + return selectedStep ? selectedStep.status === 'ready_to_complete' : false; +}; + +export const getUpdatedSteps = ( + guideState: GuideState, + stepId: GuideStepIds, + setToReadyToComplete?: boolean +): GuideStep[] => { + const currentStepIndex = guideState.steps.findIndex((step) => step.id === stepId); + const currentStep = guideState.steps[currentStepIndex]; + return guideState.steps.map((step, stepIndex) => { + const isCurrentStep = step.id === currentStep!.id; + const isNextStep = stepIndex === currentStepIndex + 1; + + if (isCurrentStep) { + return { + id: step.id, + status: setToReadyToComplete ? 'ready_to_complete' : 'complete', + }; + } + + // if the current step is being updated to 'ready_to_complete, the next step stays inactive + // otherwise update the next step to active status + if (isNextStep) { + return setToReadyToComplete + ? step + : { + id: step.id, + status: 'active', + }; + } + + // All other steps return as-is + return step; + }); +}; diff --git a/src/plugins/guided_onboarding/public/types.ts b/src/plugins/guided_onboarding/public/types.ts index ba7271756cbb7..0ca4a5801fb15 100755 --- a/src/plugins/guided_onboarding/public/types.ts +++ b/src/plugins/guided_onboarding/public/types.ts @@ -65,6 +65,11 @@ export interface StepConfig { }; status?: StepStatus; integration?: string; + manualCompletion?: { + title: string; + description: string; + readyToCompleteOnNavigation?: boolean; + }; } export interface GuideConfig { title: string; diff --git a/src/plugins/guided_onboarding/server/routes/index.ts b/src/plugins/guided_onboarding/server/routes/index.ts index cce5aad08b1e5..adc65d0bf6866 100755 --- a/src/plugins/guided_onboarding/server/routes/index.ts +++ b/src/plugins/guided_onboarding/server/routes/index.ts @@ -8,6 +8,7 @@ import { schema } from '@kbn/config-schema'; import type { IRouter, SavedObjectsClient } from '@kbn/core/server'; +import { API_BASE_PATH } from '../../common/constants'; import type { GuideState } from '../../common/types'; import { guidedSetupSavedObjectsType } from '../saved_objects'; @@ -35,7 +36,7 @@ export function defineRoutes(router: IRouter) { // Fetch all guides state; optionally pass the query param ?active=true to only return the active guide router.get( { - path: '/api/guided_onboarding/state', + path: `${API_BASE_PATH}/state`, validate: { query: schema.object({ active: schema.maybe(schema.boolean()), @@ -69,7 +70,7 @@ export function defineRoutes(router: IRouter) { // will also check any existing active guides and update them to an "inactive" state router.put( { - path: '/api/guided_onboarding/state', + path: `${API_BASE_PATH}/state`, validate: { body: schema.object({ status: schema.string(), diff --git a/src/plugins/telemetry_management_section/public/components/__snapshots__/telemetry_management_section.test.tsx.snap b/src/plugins/telemetry_management_section/public/components/__snapshots__/telemetry_management_section.test.tsx.snap index f590a5c82a79b..a341fcd17b76d 100644 --- a/src/plugins/telemetry_management_section/public/components/__snapshots__/telemetry_management_section.test.tsx.snap +++ b/src/plugins/telemetry_management_section/public/components/__snapshots__/telemetry_management_section.test.tsx.snap @@ -24,23 +24,21 @@ exports[`TelemetryManagementSectionComponent renders as expected 1`] = ` color="primary" iconType="spacesApp" title={ -

- - - , - } + + + , } - /> -

+ } + /> } /> { color="primary" iconType="spacesApp" title={ -

- - - - ), - }} - /> -

+ + + + ), + }} + /> } /> ); diff --git a/src/plugins/vis_types/gauge/kibana.json b/src/plugins/vis_types/gauge/kibana.json index 5eb2794452de9..428ee970c4e7f 100755 --- a/src/plugins/vis_types/gauge/kibana.json +++ b/src/plugins/vis_types/gauge/kibana.json @@ -4,13 +4,26 @@ "kibanaVersion": "kibana", "server": true, "ui": true, - "requiredPlugins": ["charts", "data", "expressions", "visualizations"], - "requiredBundles": ["visDefaultEditor"], - "optionalPlugins": ["expressionGauge"], - "extraPublicDirs": ["common/index"], + "requiredPlugins": [ + "charts", + "data", + "expressions", + "visualizations", + "dataViews" + ], + "requiredBundles": [ + "visDefaultEditor", + "kibanaUtils" + ], + "optionalPlugins": [ + "expressionGauge" + ], + "extraPublicDirs": [ + "common/index" + ], "owner": { "name": "Vis Editors", "githubTeam": "kibana-vis-editors" }, "description": "Contains the gauge chart implementation using the elastic-charts library. The goal is to eventually deprecate the old implementation and keep only this. Until then, the library used is defined by the Legacy charts library advanced setting." -} +} \ No newline at end of file diff --git a/src/plugins/vis_types/gauge/public/convert_to_lens/configurations/gauge.test.ts b/src/plugins/vis_types/gauge/public/convert_to_lens/configurations/gauge.test.ts new file mode 100644 index 0000000000000..0b2bab509341d --- /dev/null +++ b/src/plugins/vis_types/gauge/public/convert_to_lens/configurations/gauge.test.ts @@ -0,0 +1,83 @@ +/* + * 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 { ColorSchemas } from '@kbn/charts-plugin/common'; +import { CustomPaletteParams, PaletteOutput } from '@kbn/coloring'; +import { getConfiguration } from './gauge'; +import { GaugeVisParams } from '../../types'; + +const params: GaugeVisParams = { + addTooltip: false, + addLegend: false, + isDisplayWarning: true, + gauge: { + type: 'meter', + orientation: 'vertical', + alignment: 'automatic', + gaugeType: 'Arc', + scale: { + color: 'rgba(105,112,125,0.2)', + labels: false, + show: false, + }, + gaugeStyle: 'Full', + extendRange: false, + backStyle: 'Full', + percentageMode: false, + percentageFormatPattern: '', + colorSchema: ColorSchemas.Greys, + colorsRange: [ + { type: 'range', from: 0, to: 100 }, + { type: 'range', from: 100, to: 200 }, + ], + labels: {}, + invertColors: false, + style: { + bgFill: '', + bgColor: false, + labelColor: false, + subText: '', + fontSize: 10, + }, + }, + type: 'gauge', +}; + +describe('getConfiguration', () => { + const palette = { + name: 'custom', + params: { name: 'custom' }, + type: 'palette', + } as PaletteOutput; + + test('shourd return correct configuration', () => { + const layerId = 'layer-id'; + const metricAccessor = 'metric-id'; + const minAccessor = 'min-accessor'; + const maxAccessor = 'max-accessor'; + expect( + getConfiguration(layerId, params, palette, { + metricAccessor, + minAccessor, + maxAccessor, + }) + ).toEqual({ + colorMode: 'palette', + labelMajorMode: 'none', + labelMinor: undefined, + layerId: 'layer-id', + layerType: 'data', + maxAccessor: 'max-accessor', + metricAccessor: 'metric-id', + minAccessor: 'min-accessor', + palette: { name: 'custom', params: { name: 'custom' }, type: 'palette' }, + shape: 'horizontalBullet', + ticksPosition: 'bands', + }); + }); +}); diff --git a/src/plugins/vis_types/gauge/public/convert_to_lens/configurations/gauge.ts b/src/plugins/vis_types/gauge/public/convert_to_lens/configurations/gauge.ts new file mode 100644 index 0000000000000..9a5483d038c2e --- /dev/null +++ b/src/plugins/vis_types/gauge/public/convert_to_lens/configurations/gauge.ts @@ -0,0 +1,41 @@ +/* + * 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 { CustomPaletteParams, PaletteOutput } from '@kbn/coloring'; +import { GaugeVisConfiguration } from '@kbn/visualizations-plugin/common'; +import { GaugeVisParams } from '../../types'; + +export const getConfiguration = ( + layerId: string, + params: GaugeVisParams, + palette: PaletteOutput | undefined, + { + metricAccessor, + minAccessor, + maxAccessor, + }: { + metricAccessor: string; + minAccessor: string; + maxAccessor: string; + } +): GaugeVisConfiguration => { + const showLabels = Boolean(params.gauge.labels.show); + return { + layerId, + layerType: 'data', + palette, + metricAccessor, + minAccessor, + maxAccessor, + shape: 'horizontalBullet', + ticksPosition: 'bands', + labelMajorMode: showLabels ? 'auto' : 'none', + colorMode: palette ? 'palette' : 'none', + labelMinor: showLabels ? params.gauge.style.subText : undefined, + }; +}; diff --git a/src/plugins/vis_types/gauge/public/convert_to_lens/configurations/goal.test.ts b/src/plugins/vis_types/gauge/public/convert_to_lens/configurations/goal.test.ts new file mode 100644 index 0000000000000..6f472ca29af46 --- /dev/null +++ b/src/plugins/vis_types/gauge/public/convert_to_lens/configurations/goal.test.ts @@ -0,0 +1,84 @@ +/* + * 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 { ColorSchemas } from '@kbn/charts-plugin/common'; +import { CustomPaletteParams, PaletteOutput } from '@kbn/coloring'; +import { GaugeVisParams } from '../../types'; +import { getConfiguration } from './goal'; + +const params: GaugeVisParams = { + addTooltip: false, + addLegend: false, + isDisplayWarning: true, + gauge: { + type: 'meter', + orientation: 'vertical', + alignment: 'automatic', + gaugeType: 'Arc', + scale: { + color: 'rgba(105,112,125,0.2)', + labels: false, + show: false, + }, + gaugeStyle: 'Full', + extendRange: false, + backStyle: 'Full', + percentageMode: false, + percentageFormatPattern: '', + colorSchema: ColorSchemas.Greys, + colorsRange: [ + { type: 'range', from: 0, to: 100 }, + { type: 'range', from: 100, to: 200 }, + ], + labels: {}, + invertColors: false, + style: { + bgFill: '', + bgColor: false, + labelColor: false, + subText: '', + fontSize: 10, + }, + }, + type: 'gauge', +}; + +describe('getConfiguration', () => { + const palette = { + name: 'custom', + params: { name: 'custom' }, + type: 'palette', + } as PaletteOutput; + + test('shourd return correct configuration', () => { + const layerId = 'layer-id'; + const metricAccessor = 'metric-id'; + const breakdownByAccessor = 'bucket-id'; + const metrics = [metricAccessor]; + const buckets = { all: [breakdownByAccessor], customBuckets: {} }; + const maxAccessor = 'max-accessor-id'; + const collapseFn = 'sum'; + expect( + getConfiguration(layerId, params, palette, { + metrics, + buckets, + maxAccessor, + columnsWithoutReferenced: [], + bucketCollapseFn: { [collapseFn]: [breakdownByAccessor] }, + }) + ).toEqual({ + breakdownByAccessor, + collapseFn, + layerId, + layerType: 'data', + maxAccessor, + metricAccessor, + palette, + }); + }); +}); diff --git a/src/plugins/vis_types/gauge/public/convert_to_lens/configurations/goal.ts b/src/plugins/vis_types/gauge/public/convert_to_lens/configurations/goal.ts new file mode 100644 index 0000000000000..ec56280fa25cc --- /dev/null +++ b/src/plugins/vis_types/gauge/public/convert_to_lens/configurations/goal.ts @@ -0,0 +1,51 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 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 { CustomPaletteParams, PaletteOutput } from '@kbn/coloring'; +import { Column, MetricVisConfiguration } from '@kbn/visualizations-plugin/common'; +import { GaugeVisParams } from '../../types'; + +export const getConfiguration = ( + layerId: string, + { gauge }: GaugeVisParams, + palette: PaletteOutput | undefined, + { + metrics, + buckets, + maxAccessor, + columnsWithoutReferenced, + bucketCollapseFn, + }: { + metrics: string[]; + buckets: { + all: string[]; + customBuckets: Record; + }; + maxAccessor: string; + columnsWithoutReferenced: Column[]; + bucketCollapseFn?: Record; + } +): MetricVisConfiguration => { + const [metricAccessor] = metrics; + const [breakdownByAccessor] = buckets.all; + const collapseFn = bucketCollapseFn + ? Object.keys(bucketCollapseFn).find((key) => + bucketCollapseFn[key].includes(breakdownByAccessor) + ) + : undefined; + return { + layerId, + layerType: 'data', + palette, + metricAccessor, + breakdownByAccessor, + maxAccessor, + collapseFn, + subtitle: gauge.labels.show && gauge.style.subText ? gauge.style.subText : undefined, + }; +}; diff --git a/src/plugins/vis_types/gauge/public/convert_to_lens/gauge.test.ts b/src/plugins/vis_types/gauge/public/convert_to_lens/gauge.test.ts new file mode 100644 index 0000000000000..0da750bfdcef0 --- /dev/null +++ b/src/plugins/vis_types/gauge/public/convert_to_lens/gauge.test.ts @@ -0,0 +1,165 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 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 { ColorSchemas } from '@kbn/charts-plugin/common'; +import { Vis } from '@kbn/visualizations-plugin/public'; +import { convertToLens } from './gauge'; +import { GaugeVisParams } from '../types'; + +const mockGetColumnsFromVis = jest.fn(); +const mockGetPercentageColumnFormulaColumn = jest.fn(); +const mockGetConfiguration = jest.fn().mockReturnValue({}); +const mockGetPercentageModeConfig = jest.fn(); +const mockGetPalette = jest.fn(); +const mockCreateStaticValueColumn = jest.fn(); + +jest.mock('../services', () => ({ + getDataViewsStart: jest.fn(() => ({ get: () => ({}), getDefault: () => ({}) })), +})); + +jest.mock('@kbn/visualizations-plugin/public', () => ({ + convertToLensModule: Promise.resolve({ + getColumnsFromVis: jest.fn(() => mockGetColumnsFromVis()), + getPercentageColumnFormulaColumn: jest.fn(() => mockGetPercentageColumnFormulaColumn()), + getPercentageModeConfig: jest.fn(() => mockGetPercentageModeConfig()), + getPalette: jest.fn(() => mockGetPalette()), + createStaticValueColumn: jest.fn(() => mockCreateStaticValueColumn()), + }), + getDataViewByIndexPatternId: jest.fn(() => ({ id: 'index-pattern' })), +})); + +jest.mock('./configurations/gauge', () => ({ + getConfiguration: jest.fn(() => mockGetConfiguration()), +})); + +const params: GaugeVisParams = { + addTooltip: false, + addLegend: false, + isDisplayWarning: true, + gauge: { + type: 'meter', + orientation: 'vertical', + alignment: 'automatic', + gaugeType: 'Arc', + scale: { + color: 'rgba(105,112,125,0.2)', + labels: false, + show: false, + }, + gaugeStyle: 'Full', + extendRange: false, + backStyle: 'Full', + percentageMode: false, + percentageFormatPattern: '', + colorSchema: ColorSchemas.Greys, + colorsRange: [], + labels: {}, + invertColors: false, + style: { + bgFill: '', + bgColor: false, + labelColor: false, + subText: '', + fontSize: 10, + }, + }, + type: 'gauge', +}; + +const vis = { + isHierarchical: () => false, + type: {}, + params, + data: {}, +} as unknown as Vis; + +const timefilter = { + getAbsoluteTime: () => {}, +} as any; + +describe('convertToLens', () => { + beforeEach(() => { + mockGetPercentageModeConfig.mockReturnValue({ + isPercentageMode: false, + min: 0, + max: 1000, + }); + mockCreateStaticValueColumn.mockReturnValue({}); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + test('should return null if getColumnsFromVis returns null', async () => { + mockGetColumnsFromVis.mockReturnValue(null); + const result = await convertToLens(vis, timefilter); + expect(mockGetColumnsFromVis).toBeCalledTimes(1); + expect(result).toBeNull(); + }); + + test('should return null if metrics count is more than 1', async () => { + mockGetColumnsFromVis.mockReturnValue([ + { + metrics: ['1', '2'], + buckets: { all: [] }, + columns: [{ columnId: '2' }, { columnId: '1' }], + }, + ]); + const result = await convertToLens(vis, timefilter); + expect(mockGetColumnsFromVis).toBeCalledTimes(1); + expect(result).toBeNull(); + }); + + test('should return null if metric column data type is different from number', async () => { + mockGetColumnsFromVis.mockReturnValue([ + { + metrics: ['1'], + buckets: { all: [] }, + columns: [{ columnId: '2' }, { columnId: '1', dataType: 'string' }], + }, + ]); + const result = await convertToLens(vis, timefilter); + expect(mockGetColumnsFromVis).toBeCalledTimes(1); + expect(result).toBeNull(); + }); + test('should return correct state for valid vis', async () => { + const config = { + layerType: 'data', + }; + + mockGetColumnsFromVis.mockReturnValue([ + { + metrics: ['1'], + buckets: { all: [] }, + columns: [{ columnId: '1', dataType: 'number' }], + columnsWithoutReferenced: [ + { columnId: '1', meta: { aggId: 'agg-1' } }, + { columnId: '2', meta: { aggId: 'agg-2' } }, + ], + }, + ]); + mockGetConfiguration.mockReturnValue(config); + + const result = await convertToLens(vis, timefilter); + expect(mockGetColumnsFromVis).toBeCalledTimes(1); + expect(mockGetConfiguration).toBeCalledTimes(1); + expect(mockGetPalette).toBeCalledTimes(1); + expect(mockCreateStaticValueColumn).toBeCalledTimes(2); + expect(result?.type).toEqual('lnsGauge'); + expect(result?.layers.length).toEqual(1); + expect(result?.layers[0]).toEqual( + expect.objectContaining({ + columnOrder: [], + columns: [{ columnId: '1', dataType: 'number' }, {}, {}], + indexPatternId: 'index-pattern', + }) + ); + expect(result?.configuration).toEqual(config); + }); +}); diff --git a/src/plugins/vis_types/gauge/public/convert_to_lens/gauge.ts b/src/plugins/vis_types/gauge/public/convert_to_lens/gauge.ts new file mode 100644 index 0000000000000..080d5e84561a9 --- /dev/null +++ b/src/plugins/vis_types/gauge/public/convert_to_lens/gauge.ts @@ -0,0 +1,115 @@ +/* + * 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 uuid from 'uuid'; +import { + Column, + ColumnWithMeta, + PercentageModeConfigWithMinMax, +} from '@kbn/visualizations-plugin/common'; +import { + convertToLensModule, + getDataViewByIndexPatternId, +} from '@kbn/visualizations-plugin/public'; +import { getDataViewsStart } from '../services'; +import { ConvertGaugeVisToLensVisualization } from './types'; + +export const isColumnWithMeta = (column: Column): column is ColumnWithMeta => { + if ((column as ColumnWithMeta).meta) { + return true; + } + return false; +}; + +export const excludeMetaFromColumn = (column: Column) => { + if (isColumnWithMeta(column)) { + const { meta, ...rest } = column; + return rest; + } + return column; +}; + +export const convertToLens: ConvertGaugeVisToLensVisualization = async (vis, timefilter) => { + if (!timefilter) { + return null; + } + + const dataViews = getDataViewsStart(); + const dataView = await getDataViewByIndexPatternId(vis.data.indexPattern?.id, dataViews); + + if (!dataView) { + return null; + } + + const [ + { getColumnsFromVis, createStaticValueColumn, getPalette, getPercentageModeConfig }, + { getConfiguration }, + ] = await Promise.all([convertToLensModule, import('./configurations/gauge')]); + + const percentageModeConfig = getPercentageModeConfig(vis.params.gauge, false); + + const layers = getColumnsFromVis( + vis, + timefilter, + dataView, + { + unsupported: ['group'], + }, + { dropEmptyRowsInDateHistogram: true, ...percentageModeConfig } + ); + + if (layers === null) { + return null; + } + + const [layerConfig] = layers; + + // for now, multiple metrics are not supported + if (layerConfig.metrics.length > 1 || layerConfig.buckets.all.length) { + return null; + } + + if (layerConfig.metrics[0]) { + const metric = layerConfig.columns.find(({ columnId }) => columnId === layerConfig.metrics[0]); + if (metric?.dataType !== 'number') { + return null; + } + } + + const layerId = uuid(); + const indexPatternId = dataView.id!; + + const metricAccessor = layerConfig.metrics[0]; + const { min, max, isPercentageMode } = percentageModeConfig as PercentageModeConfigWithMinMax; + const minColumn = createStaticValueColumn(isPercentageMode ? 0 : min); + const maxColumn = createStaticValueColumn(isPercentageMode ? 1 : max); + const columns = [...layerConfig.columns, minColumn, maxColumn]; + + return { + type: 'lnsGauge', + layers: [ + { + indexPatternId, + layerId, + columns: columns.map(excludeMetaFromColumn), + columnOrder: [], + }, + ], + configuration: getConfiguration( + layerId, + vis.params, + getPalette(vis.params.gauge, percentageModeConfig, true), + { + metricAccessor, + minAccessor: minColumn.columnId, + maxAccessor: maxColumn.columnId, + } + ), + indexPatternIds: [indexPatternId], + }; +}; diff --git a/src/plugins/vis_types/gauge/public/convert_to_lens/goal.test.ts b/src/plugins/vis_types/gauge/public/convert_to_lens/goal.test.ts new file mode 100644 index 0000000000000..88566694f55bf --- /dev/null +++ b/src/plugins/vis_types/gauge/public/convert_to_lens/goal.test.ts @@ -0,0 +1,176 @@ +/* + * 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 { ColorSchemas } from '@kbn/charts-plugin/common'; +import { Vis } from '@kbn/visualizations-plugin/public'; +import { convertToLens } from './goal'; +import { GaugeVisParams } from '../types'; + +const mockGetColumnsFromVis = jest.fn(); +const mockGetPercentageColumnFormulaColumn = jest.fn(); +const mockGetConfiguration = jest.fn().mockReturnValue({}); +const mockGetPercentageModeConfig = jest.fn(); +const mockGetPalette = jest.fn(); +const mockCreateStaticValueColumn = jest.fn(); + +jest.mock('../services', () => ({ + getDataViewsStart: jest.fn(() => ({ get: () => ({}), getDefault: () => ({}) })), +})); + +jest.mock('@kbn/visualizations-plugin/public', () => ({ + convertToLensModule: Promise.resolve({ + getColumnsFromVis: jest.fn(() => mockGetColumnsFromVis()), + getPercentageColumnFormulaColumn: jest.fn(() => mockGetPercentageColumnFormulaColumn()), + getPercentageModeConfig: jest.fn(() => mockGetPercentageModeConfig()), + getPalette: jest.fn(() => mockGetPalette()), + createStaticValueColumn: jest.fn(() => mockCreateStaticValueColumn()), + }), + getDataViewByIndexPatternId: jest.fn(() => ({ id: 'index-pattern' })), +})); + +jest.mock('./configurations/goal', () => ({ + getConfiguration: jest.fn(() => mockGetConfiguration()), +})); + +const params: GaugeVisParams = { + addTooltip: false, + addLegend: false, + isDisplayWarning: true, + gauge: { + type: 'meter', + orientation: 'vertical', + alignment: 'automatic', + gaugeType: 'Arc', + scale: { + color: 'rgba(105,112,125,0.2)', + labels: false, + show: false, + }, + gaugeStyle: 'Full', + extendRange: false, + backStyle: 'Full', + percentageMode: false, + percentageFormatPattern: '', + colorSchema: ColorSchemas.Greys, + colorsRange: [], + labels: {}, + invertColors: false, + style: { + bgFill: '', + bgColor: false, + labelColor: false, + subText: '', + fontSize: 10, + }, + }, + type: 'gauge', +}; + +const vis = { + isHierarchical: () => false, + type: {}, + params, + data: {}, +} as unknown as Vis; + +const timefilter = { + getAbsoluteTime: () => {}, +} as any; + +describe('convertToLens', () => { + beforeEach(() => { + mockGetPercentageModeConfig.mockReturnValue({ + isPercentageMode: false, + min: 0, + max: 100, + }); + mockCreateStaticValueColumn.mockReturnValue({}); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + test('should return null if getColumnsFromVis returns null', async () => { + mockGetColumnsFromVis.mockReturnValue(null); + const result = await convertToLens(vis, timefilter); + expect(mockGetColumnsFromVis).toBeCalledTimes(1); + expect(result).toBeNull(); + }); + + test('should return null if metrics count is more than 1', async () => { + mockGetColumnsFromVis.mockReturnValue([ + { + metrics: ['1', '2'], + columns: [{ columnId: '2' }, { columnId: '1' }], + }, + ]); + const result = await convertToLens(vis, timefilter); + expect(mockGetColumnsFromVis).toBeCalledTimes(1); + expect(result).toBeNull(); + }); + test('should return null if buckets count is more than 1', async () => { + mockGetColumnsFromVis.mockReturnValue([ + { + metrics: [], + buckets: { all: ['1', '2'] }, + columns: [{ columnId: '2' }, { columnId: '1' }], + }, + ]); + const result = await convertToLens(vis, timefilter); + expect(mockGetColumnsFromVis).toBeCalledTimes(1); + expect(result).toBeNull(); + }); + + test('should return null if metric column data type is different from number', async () => { + mockGetColumnsFromVis.mockReturnValue([ + { + metrics: ['1'], + buckets: { all: ['2'] }, + columns: [{ columnId: '2' }, { columnId: '1', dataType: 'string' }], + }, + ]); + const result = await convertToLens(vis, timefilter); + expect(mockGetColumnsFromVis).toBeCalledTimes(1); + expect(result).toBeNull(); + }); + test('should return correct state for valid vis', async () => { + const config = { + layerType: 'data', + metricAccessor: '1', + }; + + mockGetColumnsFromVis.mockReturnValue([ + { + metrics: ['1'], + buckets: { all: ['2'] }, + columns: [{ columnId: '2' }, { columnId: '1', dataType: 'number' }], + columnsWithoutReferenced: [ + { columnId: '1', meta: { aggId: 'agg-1' } }, + { columnId: '2', meta: { aggId: 'agg-2' } }, + ], + }, + ]); + mockGetConfiguration.mockReturnValue(config); + + const result = await convertToLens(vis, timefilter); + expect(mockGetColumnsFromVis).toBeCalledTimes(1); + expect(mockGetConfiguration).toBeCalledTimes(1); + expect(mockGetPalette).toBeCalledTimes(1); + expect(result?.type).toEqual('lnsMetric'); + expect(result?.layers.length).toEqual(1); + expect(result?.layers[0]).toEqual( + expect.objectContaining({ + columnOrder: [], + columns: [{ columnId: '2' }, { columnId: '1', dataType: 'number' }, {}], + indexPatternId: 'index-pattern', + }) + ); + expect(result?.configuration).toEqual(config); + }); +}); diff --git a/src/plugins/vis_types/gauge/public/convert_to_lens/goal.ts b/src/plugins/vis_types/gauge/public/convert_to_lens/goal.ts new file mode 100644 index 0000000000000..624ce45b3e848 --- /dev/null +++ b/src/plugins/vis_types/gauge/public/convert_to_lens/goal.ts @@ -0,0 +1,111 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 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 uuid from 'uuid'; +import { + Column, + ColumnWithMeta, + PercentageModeConfigWithMinMax, +} from '@kbn/visualizations-plugin/common'; +import { + convertToLensModule, + getDataViewByIndexPatternId, +} from '@kbn/visualizations-plugin/public'; +import { getDataViewsStart } from '../services'; +import { ConvertGoalVisToLensVisualization } from './types'; + +export const isColumnWithMeta = (column: Column): column is ColumnWithMeta => { + if ((column as ColumnWithMeta).meta) { + return true; + } + return false; +}; + +export const excludeMetaFromColumn = (column: Column) => { + if (isColumnWithMeta(column)) { + const { meta, ...rest } = column; + return rest; + } + return column; +}; + +export const convertToLens: ConvertGoalVisToLensVisualization = async (vis, timefilter) => { + if (!timefilter) { + return null; + } + + const dataViews = getDataViewsStart(); + const dataView = await getDataViewByIndexPatternId(vis.data.indexPattern?.id, dataViews); + + if (!dataView) { + return null; + } + + const [ + { getColumnsFromVis, getPalette, getPercentageModeConfig, createStaticValueColumn }, + { getConfiguration }, + ] = await Promise.all([convertToLensModule, import('./configurations/goal')]); + + const percentageModeConfig = getPercentageModeConfig(vis.params.gauge, false); + + const layers = getColumnsFromVis( + vis, + timefilter, + dataView, + { + splits: ['group'], + }, + { dropEmptyRowsInDateHistogram: true, ...percentageModeConfig } + ); + + if (layers === null) { + return null; + } + + const [layerConfig] = layers; + + // for now, multiple metrics are not supported + if (layerConfig.metrics.length > 1 || layerConfig.buckets.all.length > 1) { + return null; + } + + if (layerConfig.metrics[0]) { + const metric = layerConfig.columns.find(({ columnId }) => columnId === layerConfig.metrics[0]); + if (metric?.dataType !== 'number') { + return null; + } + } + const { isPercentageMode, max } = percentageModeConfig as PercentageModeConfigWithMinMax; + const maxColumn = createStaticValueColumn(isPercentageMode ? 1 : max); + + const columns = [...layerConfig.columns, maxColumn]; + const layerId = uuid(); + const indexPatternId = dataView.id!; + + return { + type: 'lnsMetric', + layers: [ + { + indexPatternId, + layerId, + columns: columns.map(excludeMetaFromColumn), + columnOrder: [], + }, + ], + configuration: getConfiguration( + layerId, + vis.params, + getPalette(vis.params.gauge, percentageModeConfig, true), + { + ...layerConfig, + maxAccessor: maxColumn.columnId, + } + ), + indexPatternIds: [indexPatternId], + }; +}; diff --git a/src/plugins/vis_types/gauge/public/convert_to_lens/index.ts b/src/plugins/vis_types/gauge/public/convert_to_lens/index.ts new file mode 100644 index 0000000000000..6bbf661086a54 --- /dev/null +++ b/src/plugins/vis_types/gauge/public/convert_to_lens/index.ts @@ -0,0 +1,10 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 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. + */ + +export { convertToLens as convertGaugeToLens } from './gauge'; +export { convertToLens as convertGoalToLens } from './goal'; diff --git a/src/plugins/vis_types/gauge/public/convert_to_lens/types.ts b/src/plugins/vis_types/gauge/public/convert_to_lens/types.ts new file mode 100644 index 0000000000000..522c2931e3c0e --- /dev/null +++ b/src/plugins/vis_types/gauge/public/convert_to_lens/types.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 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 { TimefilterContract } from '@kbn/data-plugin/public'; +import { + NavigateToLensContext, + GaugeVisConfiguration, + MetricVisConfiguration, +} from '@kbn/visualizations-plugin/common'; +import { Vis } from '@kbn/visualizations-plugin/public'; +import { GaugeVisParams } from '../types'; + +export type ConvertGaugeVisToLensVisualization = ( + vis: Vis, + timefilter?: TimefilterContract +) => Promise | null>; + +export type ConvertGoalVisToLensVisualization = ( + vis: Vis, + timefilter?: TimefilterContract +) => Promise | null>; diff --git a/src/plugins/vis_types/gauge/public/plugin.ts b/src/plugins/vis_types/gauge/public/plugin.ts index 1db42c7cc01df..16e7a0a818487 100755 --- a/src/plugins/vis_types/gauge/public/plugin.ts +++ b/src/plugins/vis_types/gauge/public/plugin.ts @@ -6,12 +6,14 @@ * Side Public License, v 1. */ +import { CoreSetup, CoreStart } from '@kbn/core/public'; import { VisualizationsSetup } from '@kbn/visualizations-plugin/public'; import { DataPublicPluginStart } from '@kbn/data-plugin/public'; -import { CoreSetup } from '@kbn/core/public'; +import { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public'; import { LEGACY_GAUGE_CHARTS_LIBRARY } from '../common'; import { VisTypeGaugePluginSetup } from './types'; import { gaugeVisType, goalVisType } from './vis_type'; +import { setDataViewsStart } from './services'; /** @internal */ export interface VisTypeGaugeSetupDependencies { @@ -19,13 +21,14 @@ export interface VisTypeGaugeSetupDependencies { } /** @internal */ -export interface VisTypePiePluginStartDependencies { +export interface VisTypeGaugePluginStartDependencies { data: DataPublicPluginStart; + dataViews: DataViewsPublicPluginStart; } export class VisTypeGaugePlugin { public setup( - core: CoreSetup, + core: CoreSetup, { visualizations }: VisTypeGaugeSetupDependencies ): VisTypeGaugePluginSetup { if (!core.uiSettings.get(LEGACY_GAUGE_CHARTS_LIBRARY)) { @@ -37,5 +40,7 @@ export class VisTypeGaugePlugin { return {}; } - public start() {} + public start(core: CoreStart, { dataViews }: VisTypeGaugePluginStartDependencies) { + setDataViewsStart(dataViews); + } } diff --git a/src/plugins/vis_types/gauge/public/services.ts b/src/plugins/vis_types/gauge/public/services.ts new file mode 100644 index 0000000000000..736ad70d49419 --- /dev/null +++ b/src/plugins/vis_types/gauge/public/services.ts @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 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 { createGetterSetter } from '@kbn/kibana-utils-plugin/public'; +import { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public'; + +export const [getDataViewsStart, setDataViewsStart] = + createGetterSetter('dataViews'); diff --git a/src/plugins/vis_types/gauge/public/to_ast.ts b/src/plugins/vis_types/gauge/public/to_ast.ts index 697b9790468a3..8f7576b0b80c4 100644 --- a/src/plugins/vis_types/gauge/public/to_ast.ts +++ b/src/plugins/vis_types/gauge/public/to_ast.ts @@ -6,6 +6,7 @@ * Side Public License, v 1. */ +import { getStopsWithColorsFromRanges } from '@kbn/visualizations-plugin/common/utils'; import { getVisSchemas, SchemaConfig, VisToExpressionAst } from '@kbn/visualizations-plugin/public'; import { buildExpression, buildExpressionFunction } from '@kbn/expressions-plugin/public'; import type { @@ -13,7 +14,6 @@ import type { GaugeShape, } from '@kbn/expression-gauge-plugin/common'; import { GaugeType, GaugeVisParams } from './types'; -import { getStopsWithColorsFromRanges } from './utils'; const prepareDimension = (params: SchemaConfig) => { const visdimension = buildExpressionFunction('visdimension', { accessor: params.accessor }); diff --git a/src/plugins/vis_types/gauge/public/vis_type/gauge.tsx b/src/plugins/vis_types/gauge/public/vis_type/gauge.tsx index b6bdf93a8ea89..d2e722c88717a 100644 --- a/src/plugins/vis_types/gauge/public/vis_type/gauge.tsx +++ b/src/plugins/vis_types/gauge/public/vis_type/gauge.tsx @@ -18,6 +18,7 @@ import { toExpressionAst } from '../to_ast'; import { getGaugeOptions } from '../editor/components'; import { GaugeVisParams } from '../types'; import { SplitTooltip } from './split_tooltip'; +import { convertGaugeToLens } from '../convert_to_lens'; export const getGaugeVisTypeDefinition = ( props: GaugeTypeProps @@ -130,4 +131,10 @@ export const getGaugeVisTypeDefinition = ( ], }, requiresSearch: true, + navigateToLens: async (vis, timefilter) => (vis ? convertGaugeToLens(vis, timefilter) : null), + getExpressionVariables: async (vis, timeFilter) => { + return { + canNavigateToLens: Boolean(vis?.params ? await convertGaugeToLens(vis, timeFilter) : null), + }; + }, }); diff --git a/src/plugins/vis_types/gauge/public/vis_type/goal.tsx b/src/plugins/vis_types/gauge/public/vis_type/goal.tsx index c43e9c8cd46f5..1e63652f5bd5f 100644 --- a/src/plugins/vis_types/gauge/public/vis_type/goal.tsx +++ b/src/plugins/vis_types/gauge/public/vis_type/goal.tsx @@ -17,6 +17,7 @@ import { getGaugeOptions } from '../editor/components'; import { toExpressionAst } from '../to_ast'; import { GaugeVisParams, GaugeType, GaugeTypeProps } from '../types'; import { SplitTooltip } from './split_tooltip'; +import { convertGoalToLens } from '../convert_to_lens'; export const getGoalVisTypeDefinition = ( props: GaugeTypeProps @@ -122,4 +123,10 @@ export const getGoalVisTypeDefinition = ( ], }, requiresSearch: true, + navigateToLens: async (vis, timefilter) => (vis ? convertGoalToLens(vis, timefilter) : null), + getExpressionVariables: async (vis, timeFilter) => { + return { + canNavigateToLens: Boolean(vis?.params ? await convertGoalToLens(vis, timeFilter) : null), + }; + }, }); diff --git a/src/plugins/vis_types/metric/public/convert_to_lens/configurations/index.test.ts b/src/plugins/vis_types/metric/public/convert_to_lens/configurations/index.test.ts index 97fb145e74a2f..5ccfb169c91ae 100644 --- a/src/plugins/vis_types/metric/public/convert_to_lens/configurations/index.test.ts +++ b/src/plugins/vis_types/metric/public/convert_to_lens/configurations/index.test.ts @@ -7,15 +7,10 @@ */ import { ColorSchemas } from '@kbn/charts-plugin/common'; -import { getConfiguration, getPercentageModeConfig } from '.'; +import { CustomPaletteParams, PaletteOutput } from '@kbn/coloring'; +import { getConfiguration } from '.'; import { VisParams } from '../../types'; -const mockGetPalette = jest.fn(); - -jest.mock('./palette', () => ({ - getPalette: jest.fn(() => mockGetPalette()), -})); - const params: VisParams = { addTooltip: false, addLegend: false, @@ -38,25 +33,12 @@ const params: VisParams = { type: 'metric', }; -describe('getPercentageModeConfig', () => { - test('should return falsy percentage mode if percentage mode is off', () => { - expect(getPercentageModeConfig(params)).toEqual({ isPercentageMode: false }); - }); - - test('should return percentage mode config', () => { - expect( - getPercentageModeConfig({ ...params, metric: { ...params.metric, percentageMode: true } }) - ).toEqual({ isPercentageMode: true, min: 0, max: 300 }); - }); -}); - describe('getConfiguration', () => { - const palette = { name: 'custom', params: { name: 'custom' }, type: 'palette' }; - - beforeEach(() => { - jest.clearAllMocks(); - mockGetPalette.mockReturnValue(palette); - }); + const palette = { + name: 'custom', + params: { name: 'custom' }, + type: 'palette', + } as PaletteOutput; test('shourd return correct configuration', () => { const layerId = 'layer-id'; @@ -64,11 +46,11 @@ describe('getConfiguration', () => { const bucket = 'bucket-id'; const collapseFn = 'sum'; expect( - getConfiguration(layerId, params, { + getConfiguration(layerId, params, palette, { metrics: [metric], - buckets: [bucket], + buckets: { all: [bucket], customBuckets: { metric: bucket } }, columnsWithoutReferenced: [], - bucketCollapseFn: { [metric]: collapseFn }, + bucketCollapseFn: { [collapseFn]: [bucket] }, }) ).toEqual({ breakdownByAccessor: bucket, @@ -78,6 +60,5 @@ describe('getConfiguration', () => { metricAccessor: metric, palette, }); - expect(mockGetPalette).toBeCalledTimes(1); }); }); diff --git a/src/plugins/vis_types/metric/public/convert_to_lens/configurations/index.ts b/src/plugins/vis_types/metric/public/convert_to_lens/configurations/index.ts index 39e001c1b87b8..7b1b42a0211f5 100644 --- a/src/plugins/vis_types/metric/public/convert_to_lens/configurations/index.ts +++ b/src/plugins/vis_types/metric/public/convert_to_lens/configurations/index.ts @@ -6,26 +6,14 @@ * Side Public License, v 1. */ +import { CustomPaletteParams, PaletteOutput } from '@kbn/coloring'; import { Column, MetricVisConfiguration } from '@kbn/visualizations-plugin/common'; -import { PercentageModeConfig } from '@kbn/visualizations-plugin/common/convert_to_lens'; import { VisParams } from '../../types'; -import { getPalette } from './palette'; - -export const getPercentageModeConfig = (params: VisParams): PercentageModeConfig => { - if (!params.metric.percentageMode) { - return { isPercentageMode: false }; - } - const { colorsRange } = params.metric; - return { - isPercentageMode: true, - min: colorsRange[0].from, - max: colorsRange[colorsRange.length - 1].to, - }; -}; export const getConfiguration = ( layerId: string, params: VisParams, + palette: PaletteOutput | undefined, { metrics, buckets, @@ -33,19 +21,27 @@ export const getConfiguration = ( bucketCollapseFn, }: { metrics: string[]; - buckets: string[]; + buckets: { + all: string[]; + customBuckets: Record; + }; columnsWithoutReferenced: Column[]; - bucketCollapseFn?: Record; + bucketCollapseFn?: Record; } ): MetricVisConfiguration => { const [metricAccessor] = metrics; - const [breakdownByAccessor] = buckets; + const [breakdownByAccessor] = buckets.all; + const collapseFn = bucketCollapseFn + ? Object.keys(bucketCollapseFn).find((key) => + bucketCollapseFn[key].includes(breakdownByAccessor) + ) + : undefined; return { layerId, layerType: 'data', - palette: getPalette(params), + palette: params.metric.metricColorMode !== 'None' ? palette : undefined, metricAccessor, breakdownByAccessor, - collapseFn: Object.values(bucketCollapseFn ?? {})[0], + collapseFn, }; }; diff --git a/src/plugins/vis_types/metric/public/convert_to_lens/configurations/palette.test.ts b/src/plugins/vis_types/metric/public/convert_to_lens/configurations/palette.test.ts deleted file mode 100644 index 7458a78b7b554..0000000000000 --- a/src/plugins/vis_types/metric/public/convert_to_lens/configurations/palette.test.ts +++ /dev/null @@ -1,79 +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 { ColorSchemas } from '@kbn/charts-plugin/common'; -import { VisParams } from '../../types'; -import { getPalette } from './palette'; - -describe('getPalette', () => { - const params: VisParams = { - addTooltip: false, - addLegend: false, - dimensions: {} as VisParams['dimensions'], - metric: { - percentageMode: false, - percentageFormatPattern: '', - useRanges: true, - colorSchema: ColorSchemas.Greys, - metricColorMode: 'Labels', - colorsRange: [ - { type: 'range', from: 0, to: 100 }, - { type: 'range', from: 100, to: 200 }, - { type: 'range', from: 200, to: 300 }, - ], - labels: {}, - invertColors: false, - style: {} as VisParams['metric']['style'], - }, - type: 'metric', - }; - - test('should return undefined if metricColorMode is `None`', () => { - const metricColorMode = 'None'; - const paramsWithNoneMetricColorMode: VisParams = { - ...params, - metric: { ...params.metric, metricColorMode }, - }; - expect(getPalette(paramsWithNoneMetricColorMode)).toBeUndefined(); - }); - - test('should return undefined if empty color ranges were passed', () => { - const paramsWithNoneMetricColorMode: VisParams = { - ...params, - metric: { ...params.metric, colorsRange: [] }, - }; - expect(getPalette(paramsWithNoneMetricColorMode)).toBeUndefined(); - }); - - test('should return correct palette', () => { - expect(getPalette(params)).toEqual({ - name: 'custom', - params: { - colorStops: [ - { color: '#FFFFFF', stop: 0 }, - { color: '#979797', stop: 100 }, - { color: '#000000', stop: 200 }, - ], - continuity: 'none', - maxSteps: 5, - name: 'custom', - progression: 'fixed', - rangeMax: 300, - rangeMin: 0, - rangeType: 'number', - reverse: false, - stops: [ - { color: '#FFFFFF', stop: 100 }, - { color: '#979797', stop: 200 }, - { color: '#000000', stop: 300 }, - ], - }, - type: 'palette', - }); - }); -}); diff --git a/src/plugins/vis_types/metric/public/convert_to_lens/configurations/palette.ts b/src/plugins/vis_types/metric/public/convert_to_lens/configurations/palette.ts deleted file mode 100644 index 360de60199efa..0000000000000 --- a/src/plugins/vis_types/metric/public/convert_to_lens/configurations/palette.ts +++ /dev/null @@ -1,65 +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 color from 'color'; -import { CustomPaletteParams, PaletteOutput } from '@kbn/coloring'; -import { VisParams } from '../../types'; -import { getStopsWithColorsFromRanges } from '../../utils'; -import { PaletteConfig } from '../../utils/palette'; - -type ColorStopsWithMinMax = Pick< - CustomPaletteParams, - 'colorStops' | 'stops' | 'steps' | 'rangeMax' | 'rangeMin' | 'continuity' ->; - -const buildPaletteParams = ({ color: colors, stop }: PaletteConfig): ColorStopsWithMinMax => { - const colorsWithoutStartColor = colors.slice(1, colors.length); - return { - rangeMin: stop[0], - rangeMax: stop[stop.length - 1], - continuity: 'none', - colorStops: colorsWithoutStartColor.map((c, index) => ({ - color: color(c!).hex(), - stop: stop[index], - })), - stops: colorsWithoutStartColor.map((c, index) => ({ - color: color(c!).hex(), - stop: stop[index + 1], - })), - }; -}; - -const buildCustomPalette = ( - colorStopsWithMinMax: ColorStopsWithMinMax -): PaletteOutput => { - return { - name: 'custom', - params: { - maxSteps: 5, - name: 'custom', - progression: 'fixed', - rangeMax: Infinity, - rangeMin: -Infinity, - rangeType: 'number', - reverse: false, - ...colorStopsWithMinMax, - }, - type: 'palette', - }; -}; - -export const getPalette = (params: VisParams): PaletteOutput | undefined => { - const { colorSchema, colorsRange, invertColors, metricColorMode } = params.metric; - - if (metricColorMode === 'None' || !(colorsRange && colorsRange.length)) { - return; - } - - const stopsWithColors = getStopsWithColorsFromRanges(colorsRange, colorSchema, invertColors); - return buildCustomPalette(buildPaletteParams(stopsWithColors)); -}; diff --git a/src/plugins/vis_types/metric/public/convert_to_lens/index.test.ts b/src/plugins/vis_types/metric/public/convert_to_lens/index.test.ts index 015b19157e91a..b3ad4ccf6be59 100644 --- a/src/plugins/vis_types/metric/public/convert_to_lens/index.test.ts +++ b/src/plugins/vis_types/metric/public/convert_to_lens/index.test.ts @@ -15,6 +15,7 @@ const mockGetColumnsFromVis = jest.fn(); const mockGetPercentageColumnFormulaColumn = jest.fn(); const mockGetConfiguration = jest.fn().mockReturnValue({}); const mockGetPercentageModeConfig = jest.fn(); +const mockGetPalette = jest.fn(); jest.mock('../services', () => ({ getDataViewsStart: jest.fn(() => ({ get: () => ({}), getDefault: () => ({}) })), @@ -24,13 +25,14 @@ jest.mock('@kbn/visualizations-plugin/public', () => ({ convertToLensModule: Promise.resolve({ getColumnsFromVis: jest.fn(() => mockGetColumnsFromVis()), getPercentageColumnFormulaColumn: jest.fn(() => mockGetPercentageColumnFormulaColumn()), + getPercentageModeConfig: jest.fn(() => mockGetPercentageModeConfig()), + getPalette: jest.fn(() => mockGetPalette()), }), getDataViewByIndexPatternId: jest.fn(() => ({ id: 'index-pattern' })), })); jest.mock('./configurations', () => ({ getConfiguration: jest.fn(() => mockGetConfiguration()), - getPercentageModeConfig: jest.fn(() => mockGetPercentageModeConfig()), })); const params: VisParams = { @@ -81,31 +83,37 @@ describe('convertToLens', () => { }); test('should return null if metrics count is more than 1', async () => { - mockGetColumnsFromVis.mockReturnValue({ - metrics: ['1', '2'], - columns: [{ columnId: '2' }, { columnId: '1' }], - }); + mockGetColumnsFromVis.mockReturnValue([ + { + metrics: ['1', '2'], + columns: [{ columnId: '2' }, { columnId: '1' }], + }, + ]); const result = await convertToLens(vis, timefilter); expect(mockGetColumnsFromVis).toBeCalledTimes(1); expect(result).toBeNull(); }); test('should return null if buckets count is more than 1', async () => { - mockGetColumnsFromVis.mockReturnValue({ - metrics: [], - buckets: ['1', '2'], - columns: [{ columnId: '2' }, { columnId: '1' }], - }); + mockGetColumnsFromVis.mockReturnValue([ + { + metrics: [], + buckets: { all: ['1', '2'] }, + columns: [{ columnId: '2' }, { columnId: '1' }], + }, + ]); const result = await convertToLens(vis, timefilter); expect(mockGetColumnsFromVis).toBeCalledTimes(1); expect(result).toBeNull(); }); test('should return null if metric column data type is different from number', async () => { - mockGetColumnsFromVis.mockReturnValue({ - metrics: ['1'], - buckets: ['2'], - columns: [{ columnId: '2' }, { columnId: '1', dataType: 'string' }], - }); + mockGetColumnsFromVis.mockReturnValue([ + { + metrics: ['1'], + buckets: { all: ['2'] }, + columns: [{ columnId: '2' }, { columnId: '1', dataType: 'string' }], + }, + ]); const result = await convertToLens(vis, timefilter); expect(mockGetColumnsFromVis).toBeCalledTimes(1); expect(result).toBeNull(); @@ -116,21 +124,23 @@ describe('convertToLens', () => { metricAccessor: '1', }; - mockGetColumnsFromVis.mockReturnValue({ - metrics: ['1'], - buckets: ['2'], - columns: [{ columnId: '2' }, { columnId: '1', dataType: 'number' }], - columnsWithoutReferenced: [ - { columnId: '1', meta: { aggId: 'agg-1' } }, - { columnId: '2', meta: { aggId: 'agg-2' } }, - ], - }); + mockGetColumnsFromVis.mockReturnValue([ + { + metrics: ['1'], + buckets: { all: ['2'] }, + columns: [{ columnId: '2' }, { columnId: '1', dataType: 'number' }], + columnsWithoutReferenced: [ + { columnId: '1', meta: { aggId: 'agg-1' } }, + { columnId: '2', meta: { aggId: 'agg-2' } }, + ], + }, + ]); mockGetConfiguration.mockReturnValue(config); const result = await convertToLens(vis, timefilter); expect(mockGetColumnsFromVis).toBeCalledTimes(1); expect(mockGetConfiguration).toBeCalledTimes(1); - + expect(mockGetPalette).toBeCalledTimes(1); expect(result?.type).toEqual('lnsMetric'); expect(result?.layers.length).toEqual(1); expect(result?.layers[0]).toEqual( diff --git a/src/plugins/vis_types/metric/public/convert_to_lens/index.ts b/src/plugins/vis_types/metric/public/convert_to_lens/index.ts index 7675cbcc1d714..5b9cb985a2799 100644 --- a/src/plugins/vis_types/metric/public/convert_to_lens/index.ts +++ b/src/plugins/vis_types/metric/public/convert_to_lens/index.ts @@ -6,12 +6,12 @@ * Side Public License, v 1. */ +import uuid from 'uuid'; import { Column, ColumnWithMeta } from '@kbn/visualizations-plugin/common'; import { convertToLensModule, getDataViewByIndexPatternId, } from '@kbn/visualizations-plugin/public'; -import uuid from 'uuid'; import { getDataViewsStart } from '../services'; import { ConvertMetricVisToLensVisualization } from './types'; @@ -42,32 +42,33 @@ export const convertToLens: ConvertMetricVisToLensVisualization = async (vis, ti return null; } - const [{ getColumnsFromVis }, { getConfiguration, getPercentageModeConfig }] = await Promise.all([ - convertToLensModule, - import('./configurations'), - ]); + const [{ getColumnsFromVis, getPalette, getPercentageModeConfig }, { getConfiguration }] = + await Promise.all([convertToLensModule, import('./configurations')]); - const result = getColumnsFromVis( + const percentageModeConfig = getPercentageModeConfig(vis.params.metric); + const layers = getColumnsFromVis( vis, timefilter, dataView, { splits: ['group'], }, - { dropEmptyRowsInDateHistogram: true, ...getPercentageModeConfig(vis.params) } + { dropEmptyRowsInDateHistogram: true, ...percentageModeConfig } ); - if (result === null) { + if (layers === null) { return null; } + const [layerConfig] = layers; + // for now, multiple metrics are not supported - if (result.metrics.length > 1 || result.buckets.length > 1) { + if (layerConfig.metrics.length > 1 || layerConfig.buckets.all.length > 1) { return null; } - if (result.metrics[0]) { - const metric = result.columns.find(({ columnId }) => columnId === result.metrics[0]); + if (layerConfig.metrics[0]) { + const metric = layerConfig.columns.find(({ columnId }) => columnId === layerConfig.metrics[0]); if (metric?.dataType !== 'number') { return null; } @@ -82,11 +83,16 @@ export const convertToLens: ConvertMetricVisToLensVisualization = async (vis, ti { indexPatternId, layerId, - columns: result.columns.map(excludeMetaFromColumn), + columns: layerConfig.columns.map(excludeMetaFromColumn), columnOrder: [], }, ], - configuration: getConfiguration(layerId, vis.params, result), + configuration: getConfiguration( + layerId, + vis.params, + getPalette(vis.params.metric, percentageModeConfig), + layerConfig + ), indexPatternIds: [indexPatternId], }; }; diff --git a/src/plugins/vis_types/metric/public/to_ast.ts b/src/plugins/vis_types/metric/public/to_ast.ts index 0341d5d7b853b..2f4bed8652c62 100644 --- a/src/plugins/vis_types/metric/public/to_ast.ts +++ b/src/plugins/vis_types/metric/public/to_ast.ts @@ -7,13 +7,13 @@ */ import { get } from 'lodash'; +import { getStopsWithColorsFromRanges } from '@kbn/visualizations-plugin/common/utils'; import { getVisSchemas, SchemaConfig, VisToExpressionAst } from '@kbn/visualizations-plugin/public'; import { buildExpression, buildExpressionFunction } from '@kbn/expressions-plugin/public'; import { inter } from '@kbn/expressions-plugin/common'; import { ColorMode } from '@kbn/charts-plugin/public'; import { VisParams } from './types'; -import { getStopsWithColorsFromRanges } from './utils'; const prepareDimension = (params: SchemaConfig) => { const visdimension = buildExpressionFunction('visdimension', { accessor: params.accessor }); diff --git a/src/plugins/vis_types/metric/public/utils/palette.ts b/src/plugins/vis_types/metric/public/utils/palette.ts deleted file mode 100644 index c17e9ccbce0bb..0000000000000 --- a/src/plugins/vis_types/metric/public/utils/palette.ts +++ /dev/null @@ -1,49 +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 { ColorSchemas, getHeatmapColors } from '@kbn/charts-plugin/common'; -import { Range } from '@kbn/expressions-plugin/common'; - -export interface PaletteConfig { - color: Array; - stop: number[]; -} - -const TRANSPARENT = 'rgb(0, 0, 0, 0)'; - -const getColor = ( - index: number, - elementsCount: number, - colorSchema: ColorSchemas, - invertColors: boolean = false -) => { - const divider = Math.max(elementsCount - 1, 1); - const value = invertColors ? 1 - index / divider : index / divider; - return getHeatmapColors(value, colorSchema); -}; - -export const getStopsWithColorsFromRanges = ( - ranges: Range[], - colorSchema: ColorSchemas, - invertColors: boolean = false -) => { - return ranges.reduce( - (acc, range, index, rangesArr) => { - if ((index && range.from !== rangesArr[index - 1].to) || index === 0) { - acc.color.push(TRANSPARENT); - acc.stop.push(range.from); - } - - acc.color.push(getColor(index, rangesArr.length, colorSchema, invertColors)); - acc.stop.push(range.to); - - return acc; - }, - { color: [], stop: [] } - ); -}; diff --git a/src/plugins/vis_types/pie/public/convert_to_lens/configurations/index.test.ts b/src/plugins/vis_types/pie/public/convert_to_lens/configurations/index.test.ts index 0a10a5bd7c0c0..87ec0d3b57b3f 100644 --- a/src/plugins/vis_types/pie/public/convert_to_lens/configurations/index.test.ts +++ b/src/plugins/vis_types/pie/public/convert_to_lens/configurations/index.test.ts @@ -19,7 +19,7 @@ describe('getConfiguration', () => { expect( getConfiguration('test1', samplePieVis as any, { metrics: ['metric-1'], - buckets: ['bucket-1'], + buckets: { all: ['bucket-1'], customBuckets: {} }, }) ).toEqual({ layers: [ @@ -55,7 +55,7 @@ describe('getConfiguration', () => { { ...samplePieVis, params: { ...samplePieVis.params, legendDisplay: 'hide' } } as any, { metrics: ['metric-1'], - buckets: ['bucket-1'], + buckets: { all: ['bucket-1'], customBuckets: {} }, } ) ).toEqual({ @@ -73,7 +73,7 @@ describe('getConfiguration', () => { { ...samplePieVis, params: { ...samplePieVis.params, legendDisplay: 'show' } } as any, { metrics: ['metric-1'], - buckets: ['bucket-1'], + buckets: { all: ['bucket-1'], customBuckets: {} }, } ) ).toEqual({ @@ -92,7 +92,7 @@ describe('getConfiguration', () => { { ...samplePieVis, params: { ...samplePieVis.params, legendDisplay } } as any, { metrics: ['metric-1'], - buckets: ['bucket-1'], + buckets: { all: ['bucket-1'], customBuckets: {} }, } ) ).toEqual({ diff --git a/src/plugins/vis_types/pie/public/convert_to_lens/configurations/index.ts b/src/plugins/vis_types/pie/public/convert_to_lens/configurations/index.ts index 9a3420581c1fd..d1d1daf9fe009 100644 --- a/src/plugins/vis_types/pie/public/convert_to_lens/configurations/index.ts +++ b/src/plugins/vis_types/pie/public/convert_to_lens/configurations/index.ts @@ -68,12 +68,15 @@ export const getConfiguration = ( buckets, }: { metrics: string[]; - buckets: string[]; + buckets: { + all: string[]; + customBuckets: Record; + }; } ): PartitionVisConfiguration => { return { shape: vis.params.isDonut ? 'donut' : 'pie', - layers: getLayers(layerId, vis, metrics, buckets), + layers: getLayers(layerId, vis, metrics, buckets.all), palette: vis.params.palette, }; }; diff --git a/src/plugins/vis_types/pie/public/convert_to_lens/index.test.ts b/src/plugins/vis_types/pie/public/convert_to_lens/index.test.ts index c1e39d741f84d..bf4dfbd3ffc72 100644 --- a/src/plugins/vis_types/pie/public/convert_to_lens/index.test.ts +++ b/src/plugins/vis_types/pie/public/convert_to_lens/index.test.ts @@ -40,28 +40,34 @@ describe('convertToLens', () => { }); test('should return null if more than three split slice levels', async () => { - mockGetColumnsFromVis.mockReturnValue({ - buckets: ['1', '2', '3', '4'], - }); + mockGetColumnsFromVis.mockReturnValue([ + { + buckets: { all: ['1', '2', '3', '4'] }, + }, + ]); const result = await convertToLens(samplePieVis as any, {} as any); expect(mockGetColumnsFromVis).toBeCalledTimes(1); expect(result).toBeNull(); }); test('should return null if no one split slices', async () => { - mockGetColumnsFromVis.mockReturnValue({ - buckets: [], - }); + mockGetColumnsFromVis.mockReturnValue([ + { + buckets: { all: [] }, + }, + ]); const result = await convertToLens(samplePieVis as any, {} as any); expect(mockGetColumnsFromVis).toBeCalledTimes(1); expect(result).toBeNull(); }); test('should state for valid vis', async () => { - mockGetColumnsFromVis.mockReturnValue({ - buckets: ['2'], - columns: [{ columnId: '2' }, { columnId: '1' }], - }); + mockGetColumnsFromVis.mockReturnValue([ + { + buckets: { all: ['2'] }, + columns: [{ columnId: '2' }, { columnId: '1' }], + }, + ]); const result = await convertToLens(samplePieVis as any, {} as any); expect(mockGetColumnsFromVis).toBeCalledTimes(1); expect(mockGetConfiguration).toBeCalledTimes(1); diff --git a/src/plugins/vis_types/pie/public/convert_to_lens/index.ts b/src/plugins/vis_types/pie/public/convert_to_lens/index.ts index 5b1973507c7df..c7231af7098c8 100644 --- a/src/plugins/vis_types/pie/public/convert_to_lens/index.ts +++ b/src/plugins/vis_types/pie/public/convert_to_lens/index.ts @@ -44,19 +44,21 @@ export const convertToLens: ConvertPieToLensVisualization = async (vis, timefilt } const { getColumnsFromVis } = await convertToLensModule; - const result = getColumnsFromVis(vis, timefilter, dataView, { + const layers = getColumnsFromVis(vis, timefilter, dataView, { buckets: [], splits: ['segment'], unsupported: ['split_row', 'split_column'], }); - if (result === null) { + if (layers === null) { return null; } + const [layerConfig] = layers; + // doesn't support more than three split slice levels // doesn't support pie without at least one split slice - if (result.buckets.length > 3 || !result.buckets.length) { + if (layerConfig.buckets.all.length > 3 || !layerConfig.buckets.all.length) { return null; } @@ -69,11 +71,11 @@ export const convertToLens: ConvertPieToLensVisualization = async (vis, timefilt { indexPatternId, layerId, - columns: result.columns.map(excludeMetaFromColumn), + columns: layerConfig.columns.map(excludeMetaFromColumn), columnOrder: [], }, ], - configuration: getConfiguration(layerId, vis, result), + configuration: getConfiguration(layerId, vis, layerConfig), indexPatternIds: [indexPatternId], }; }; diff --git a/src/plugins/vis_types/pie/public/editor/components/pie.tsx b/src/plugins/vis_types/pie/public/editor/components/pie.tsx index a22f29415d5b5..b1369e4e90929 100644 --- a/src/plugins/vis_types/pie/public/editor/components/pie.tsx +++ b/src/plugins/vis_types/pie/public/editor/components/pie.tsx @@ -160,6 +160,7 @@ const PieOptions = (props: PieOptionsProps) => { paramName="isDonut" value={stateParams.isDonut} setValue={setValue} + data-test-subj="visTypePieIsDonut" /> {props.showElasticChartsOptions && stateParams.isDonut && ( diff --git a/src/plugins/vis_types/table/public/components/table_vis_options.tsx b/src/plugins/vis_types/table/public/components/table_vis_options.tsx index 7023716025b21..9d6b1d9a7454c 100644 --- a/src/plugins/vis_types/table/public/components/table_vis_options.tsx +++ b/src/plugins/vis_types/table/public/components/table_vis_options.tsx @@ -133,6 +133,7 @@ function TableOptions({ paramName="showTotal" value={stateParams.showTotal} setValue={setValue} + data-test-subj="showTotal" /> { expect( getConfiguration('test1', params, { metrics: ['metric-1'], - buckets: ['bucket-1'], + buckets: { all: ['bucket-1'], customBuckets: { 'metric-1': 'bucket-1' } }, columnsWithoutReferenced: [ { columnId: 'metric-1', @@ -48,7 +48,7 @@ describe('getConfiguration', () => { }, }, ], - bucketCollapseFn: { 'bucket-1': 'sum' }, + bucketCollapseFn: { sum: ['bucket-1'] }, }) ).toEqual({ columns: [ diff --git a/src/plugins/vis_types/table/public/convert_to_lens/configurations/index.ts b/src/plugins/vis_types/table/public/convert_to_lens/configurations/index.ts index d98cb917b40ac..5079b25258a75 100644 --- a/src/plugins/vis_types/table/public/convert_to_lens/configurations/index.ts +++ b/src/plugins/vis_types/table/public/convert_to_lens/configurations/index.ts @@ -12,19 +12,21 @@ import { TableVisParams } from '../../../common'; const getColumns = ( params: TableVisParams, metrics: string[], - buckets: string[], columns: Column[], - bucketCollapseFn?: Record + bucketCollapseFn?: Record ) => { const { showTotal, totalFunc } = params; - return columns.map(({ columnId }) => ({ - columnId, - alignment: 'left' as const, - ...(showTotal && metrics.includes(columnId) ? { summaryRow: totalFunc } : {}), - ...(bucketCollapseFn && bucketCollapseFn[columnId] - ? { collapseFn: bucketCollapseFn[columnId] } - : {}), - })); + return columns.map(({ columnId }) => { + const collapseFn = bucketCollapseFn + ? Object.keys(bucketCollapseFn).find((key) => bucketCollapseFn[key].includes(columnId)) + : undefined; + return { + columnId, + alignment: 'left' as const, + ...(showTotal && metrics.includes(columnId) ? { summaryRow: totalFunc } : {}), + ...(collapseFn ? { collapseFn } : {}), + }; + }); }; const getPagination = ({ perPage }: TableVisParams): PagingState => { @@ -54,15 +56,18 @@ export const getConfiguration = ( bucketCollapseFn, }: { metrics: string[]; - buckets: string[]; + buckets: { + all: string[]; + customBuckets: Record; + }; columnsWithoutReferenced: Column[]; - bucketCollapseFn?: Record; + bucketCollapseFn?: Record; } ): TableVisConfiguration => { return { layerId, layerType: 'data', - columns: getColumns(params, metrics, buckets, columnsWithoutReferenced, bucketCollapseFn), + columns: getColumns(params, metrics, columnsWithoutReferenced, bucketCollapseFn), paging: getPagination(params), ...getRowHeight(params), }; diff --git a/src/plugins/vis_types/table/public/convert_to_lens/index.test.ts b/src/plugins/vis_types/table/public/convert_to_lens/index.test.ts index 5c1ad0578be11..f11f18f754eb9 100644 --- a/src/plugins/vis_types/table/public/convert_to_lens/index.test.ts +++ b/src/plugins/vis_types/table/public/convert_to_lens/index.test.ts @@ -63,14 +63,16 @@ describe('convertToLens', () => { }); test('should return null if can not build percentage column', async () => { - mockGetColumnsFromVis.mockReturnValue({ - buckets: ['2'], - columns: [{ columnId: '2' }, { columnId: '1' }], - columnsWithoutReferenced: [ - { columnId: '1', meta: { aggId: 'agg-1' } }, - { columnId: '2', meta: { aggId: 'agg-2' } }, - ], - }); + mockGetColumnsFromVis.mockReturnValue([ + { + buckets: { all: ['2'] }, + columns: [{ columnId: '2' }, { columnId: '1' }], + columnsWithoutReferenced: [ + { columnId: '1', meta: { aggId: 'agg-1' } }, + { columnId: '2', meta: { aggId: 'agg-2' } }, + ], + }, + ]); mockGetVisSchemas.mockReturnValue({ metric: [{ label: 'Count', aggId: 'agg-1' }], }); @@ -83,14 +85,16 @@ describe('convertToLens', () => { }); test('should return correct state for valid vis', async () => { - mockGetColumnsFromVis.mockReturnValue({ - buckets: ['2'], - columns: [{ columnId: '2' }, { columnId: '1' }], - columnsWithoutReferenced: [ - { columnId: '1', meta: { aggId: 'agg-1' } }, - { columnId: '2', meta: { aggId: 'agg-2' } }, - ], - }); + mockGetColumnsFromVis.mockReturnValue([ + { + buckets: { all: ['2'] }, + columns: [{ columnId: '2' }, { columnId: '1' }], + columnsWithoutReferenced: [ + { columnId: '1', meta: { aggId: 'agg-1' } }, + { columnId: '2', meta: { aggId: 'agg-2' } }, + ], + }, + ]); mockGetVisSchemas.mockReturnValue({ metric: [{ label: 'Count', aggId: 'agg-1' }], }); diff --git a/src/plugins/vis_types/table/public/convert_to_lens/index.ts b/src/plugins/vis_types/table/public/convert_to_lens/index.ts index 1b37e36f1d982..e69faccbfd7ec 100644 --- a/src/plugins/vis_types/table/public/convert_to_lens/index.ts +++ b/src/plugins/vis_types/table/public/convert_to_lens/index.ts @@ -46,7 +46,7 @@ export const convertToLens: ConvertTableToLensVisualization = async (vis, timefi } const { getColumnsFromVis, getPercentageColumnFormulaColumn } = await convertToLensModule; - const result = getColumnsFromVis( + const layers = getColumnsFromVis( vis, timefilter, dataView, @@ -57,10 +57,12 @@ export const convertToLens: ConvertTableToLensVisualization = async (vis, timefi { dropEmptyRowsInDateHistogram: true, isPercentageMode: false } ); - if (result === null) { + if (layers === null) { return null; } + const [layerConfig] = layers; + if (vis.params.percentageCol) { const visSchemas = getVisSchemas(vis, { timefilter, @@ -78,12 +80,12 @@ export const convertToLens: ConvertTableToLensVisualization = async (vis, timefi if (!percentageColumn) { return null; } - result.columns.splice( - result.columnsWithoutReferenced.findIndex((c) => c.meta.aggId === metricAgg.aggId) + 1, + layerConfig.columns.splice( + layerConfig.columnsWithoutReferenced.findIndex((c) => c.meta.aggId === metricAgg.aggId) + 1, 0, percentageColumn ); - result.columnsWithoutReferenced.push(percentageColumn); + layerConfig.columnsWithoutReferenced.push(percentageColumn); } const layerId = uuid(); @@ -94,11 +96,11 @@ export const convertToLens: ConvertTableToLensVisualization = async (vis, timefi { indexPatternId, layerId, - columns: result.columns.map(excludeMetaFromColumn), + columns: layerConfig.columns.map(excludeMetaFromColumn), columnOrder: [], }, ], - configuration: getConfiguration(layerId, vis.params, result), + configuration: getConfiguration(layerId, vis.params, layerConfig), indexPatternIds: [indexPatternId], }; }; diff --git a/src/plugins/vis_types/timeseries/public/application/components/aggs/static.js b/src/plugins/vis_types/timeseries/public/application/components/aggs/static.js index 946c2912ae20a..23181594e4c0b 100644 --- a/src/plugins/vis_types/timeseries/public/application/components/aggs/static.js +++ b/src/plugins/vis_types/timeseries/public/application/components/aggs/static.js @@ -76,6 +76,7 @@ export const Static = (props) => { } > handleElementClick(args)} animateData={false} onPointerUpdate={handleCursorUpdate} + pointerUpdateDebounce={0} theme={[ { crosshair: { diff --git a/src/plugins/vis_types/timeseries/public/convert_to_lens/lib/convert/index.ts b/src/plugins/vis_types/timeseries/public/convert_to_lens/lib/convert/index.ts index b1b15339b37a6..dc4005c6649c1 100644 --- a/src/plugins/vis_types/timeseries/public/convert_to_lens/lib/convert/index.ts +++ b/src/plugins/vis_types/timeseries/public/convert_to_lens/lib/convert/index.ts @@ -31,5 +31,6 @@ export { convertToDateHistogramColumn } from './date_histogram'; export { convertToTermsColumn } from './terms'; export { convertToCounterRateColumn } from './counter_rate'; export { convertToStandartDeviationColumn } from './std_deviation'; +export { convertVarianceToFormulaColumn } from './variance'; export * from './types'; diff --git a/src/plugins/vis_types/timeseries/public/convert_to_lens/lib/convert/parent_pipeline.ts b/src/plugins/vis_types/timeseries/public/convert_to_lens/lib/convert/parent_pipeline.ts index 522585c5c568a..2fcba37bf0d03 100644 --- a/src/plugins/vis_types/timeseries/public/convert_to_lens/lib/convert/parent_pipeline.ts +++ b/src/plugins/vis_types/timeseries/public/convert_to_lens/lib/convert/parent_pipeline.ts @@ -237,7 +237,11 @@ const convertMovingAvgOrDerivativeToColumns = ( const [nestedFieldId, _] = subMetricField?.split('[') ?? []; // support nested aggs with formula const additionalSubFunction = metrics.find(({ id }) => id === nestedFieldId); - if (additionalSubFunction || pipelineAgg.name === 'counter_rate') { + if ( + additionalSubFunction || + pipelineAgg.name === 'counter_rate' || + subFunctionMetric.type === 'variance' + ) { const formula = getPipelineSeriesFormula(metric, metrics, subFunctionMetric, { metaValue, reducedTimeRange, diff --git a/src/plugins/vis_types/timeseries/public/convert_to_lens/lib/convert/variance.test.ts b/src/plugins/vis_types/timeseries/public/convert_to_lens/lib/convert/variance.test.ts new file mode 100644 index 0000000000000..e4695f23b742e --- /dev/null +++ b/src/plugins/vis_types/timeseries/public/convert_to_lens/lib/convert/variance.test.ts @@ -0,0 +1,47 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 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 { stubLogstashDataView } from '@kbn/data-views-plugin/common/data_view.stub'; +import { createSeries } from '../__mocks__'; +import { FormulaColumn } from './types'; +import { Metric } from '../../../../common/types'; +import { TSVB_METRIC_TYPES } from '../../../../common/enums'; +import { convertVarianceToFormulaColumn } from './variance'; + +describe('convertVarianceToFormulaColumn', () => { + const series = createSeries(); + const dataView = stubLogstashDataView; + const metric: Metric = { + id: 'some-id', + type: TSVB_METRIC_TYPES.VARIANCE, + }; + const field = dataView.fields[0].name; + + test.each< + [string, Parameters, Partial | null] + >([ + ['null if field is not provided', [{ series, metrics: [metric], dataView }], null], + [ + 'correct formula column', + [{ series, metrics: [{ ...metric, field }], dataView }], + { + meta: { metricId: 'some-id' }, + operationType: 'formula', + params: { + formula: 'pow(standard_deviation(bytes), 2)', + }, + }, + ], + ])('should return %s', (_, input, expected) => { + if (expected === null) { + expect(convertVarianceToFormulaColumn(...input)).toBeNull(); + } else { + expect(convertVarianceToFormulaColumn(...input)).toEqual(expect.objectContaining(expected)); + } + }); +}); diff --git a/src/plugins/vis_types/timeseries/public/convert_to_lens/lib/convert/variance.ts b/src/plugins/vis_types/timeseries/public/convert_to_lens/lib/convert/variance.ts new file mode 100644 index 0000000000000..920317e65c224 --- /dev/null +++ b/src/plugins/vis_types/timeseries/public/convert_to_lens/lib/convert/variance.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 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 { getFormulaEquivalent } from '../metrics'; +import { createFormulaColumn } from './formula'; +import { CommonColumnsConverterArgs } from './types'; + +export const convertVarianceToFormulaColumn = ( + { series, metrics, dataView }: CommonColumnsConverterArgs, + reducedTimeRange?: string +) => { + const metric = metrics[metrics.length - 1]; + + const field = metric.field ? dataView.getFieldByName(metric.field) : undefined; + if (!field) { + return null; + } + + const script = getFormulaEquivalent(metric, metrics, { + reducedTimeRange, + timeShift: series.offset_time, + }); + if (!script) return null; + return createFormulaColumn(script, { series, metric, dataView }); +}; diff --git a/src/plugins/vis_types/timeseries/public/convert_to_lens/lib/metrics/metrics_helpers.test.ts b/src/plugins/vis_types/timeseries/public/convert_to_lens/lib/metrics/metrics_helpers.test.ts index 447312786ee02..944727505f682 100644 --- a/src/plugins/vis_types/timeseries/public/convert_to_lens/lib/metrics/metrics_helpers.test.ts +++ b/src/plugins/vis_types/timeseries/public/convert_to_lens/lib/metrics/metrics_helpers.test.ts @@ -62,6 +62,12 @@ describe('getFormulaEquivalent', () => { mode: 'upper', }; + const variance: Metric = { + id: 'some-random-value', + type: TSVB_METRIC_TYPES.VARIANCE, + field: 'test-1', + }; + const sibblingPipelineMetric: Metric[] = [ { id: 'test-1', @@ -141,6 +147,11 @@ describe('getFormulaEquivalent', () => { [stdDeviationMetricWithUpperMode, [stdDeviationMetricWithUpperMode], {}], 'average(test-1) + 1.5 * standard_deviation(test-1)', ], + [ + 'correct formula if metric is variance', + [variance, [variance], {}], + 'pow(standard_deviation(test-1), 2)', + ], [ 'correct formula if metric is supported', [supportedMetric, [supportedMetric], {}], diff --git a/src/plugins/vis_types/timeseries/public/convert_to_lens/lib/metrics/metrics_helpers.ts b/src/plugins/vis_types/timeseries/public/convert_to_lens/lib/metrics/metrics_helpers.ts index eda3ec437fc8a..8d970f2f7262d 100644 --- a/src/plugins/vis_types/timeseries/public/convert_to_lens/lib/metrics/metrics_helpers.ts +++ b/src/plugins/vis_types/timeseries/public/convert_to_lens/lib/metrics/metrics_helpers.ts @@ -144,6 +144,12 @@ export const getFormulaEquivalent = ( case 'static': { return `${currentMetric.value}`; } + case 'variance': { + return `${aggFormula}(standard_deviation(${currentMetric.field}${addAdditionalArgs({ + reducedTimeRange, + timeShift, + })}), 2)`; + } case 'std_deviation': { if (currentMetric.mode === 'lower') { return `average(${currentMetric.field}${addAdditionalArgs({ diff --git a/src/plugins/vis_types/timeseries/public/convert_to_lens/lib/metrics/supported_metrics.ts b/src/plugins/vis_types/timeseries/public/convert_to_lens/lib/metrics/supported_metrics.ts index 8be4b444be099..debe064940c8e 100644 --- a/src/plugins/vis_types/timeseries/public/convert_to_lens/lib/metrics/supported_metrics.ts +++ b/src/plugins/vis_types/timeseries/public/convert_to_lens/lib/metrics/supported_metrics.ts @@ -55,6 +55,7 @@ interface LocalSupportedMetrics { [TSVB_METRIC_TYPES.STATIC]: Metric; [TSVB_METRIC_TYPES.POSITIVE_RATE]: Metric; [TSVB_METRIC_TYPES.MOVING_AVERAGE]: Metric; + [TSVB_METRIC_TYPES.VARIANCE]: Metric; } type UnsupportedSupportedMetrics = Exclude; @@ -250,6 +251,15 @@ export const SUPPORTED_METRICS: SupportedMetrics = { supportedPanelTypes, supportedTimeRangeModes, }, + variance: { + name: 'formula', + isFormula: true, + formula: 'pow', + isFullReference: false, + isFieldRequired: true, + supportedPanelTypes, + supportedTimeRangeModes, + }, } as const; type SupportedMetricsKeys = keyof LocalSupportedMetrics; diff --git a/src/plugins/vis_types/timeseries/public/convert_to_lens/lib/series/metrics_columns.test.ts b/src/plugins/vis_types/timeseries/public/convert_to_lens/lib/series/metrics_columns.test.ts index 4461072c8df62..58cf955dab83a 100644 --- a/src/plugins/vis_types/timeseries/public/convert_to_lens/lib/series/metrics_columns.test.ts +++ b/src/plugins/vis_types/timeseries/public/convert_to_lens/lib/series/metrics_columns.test.ts @@ -23,6 +23,7 @@ const mockConvertToStaticValueColumn = jest.fn(); const mockConvertStaticValueToFormulaColumn = jest.fn(); const mockConvertToStandartDeviationColumn = jest.fn(); const mockConvertMetricAggregationColumnWithoutSpecialParams = jest.fn(); +const mockConvertVarianceToFormulaColumn = jest.fn(); jest.mock('../convert', () => ({ convertMathToFormulaColumn: jest.fn(() => mockConvertMathToFormulaColumn()), @@ -38,6 +39,7 @@ jest.mock('../convert', () => ({ convertMetricAggregationColumnWithoutSpecialParams: jest.fn(() => mockConvertMetricAggregationColumnWithoutSpecialParams() ), + convertVarianceToFormulaColumn: jest.fn(() => mockConvertVarianceToFormulaColumn()), })); describe('getMetricsColumns', () => { @@ -163,6 +165,11 @@ describe('getMetricsColumns', () => { ], mockConvertToStandartDeviationColumn, ], + [ + 'call convertVarianceToFormulaColumn if metric type is variance', + [createSeries({ metrics: [{ type: TSVB_METRIC_TYPES.VARIANCE, id: '1' }] }), dataView, 1], + mockConvertVarianceToFormulaColumn, + ], [ 'call convertMetricAggregationColumnWithoutSpecialParams if metric type is another supported type', [createSeries({ metrics: [{ type: METRIC_TYPES.AVG, id: '1' }] }), dataView, 1], diff --git a/src/plugins/vis_types/timeseries/public/convert_to_lens/lib/series/metrics_columns.ts b/src/plugins/vis_types/timeseries/public/convert_to_lens/lib/series/metrics_columns.ts index 8f7d4ded0d076..6ec978e4a685a 100644 --- a/src/plugins/vis_types/timeseries/public/convert_to_lens/lib/series/metrics_columns.ts +++ b/src/plugins/vis_types/timeseries/public/convert_to_lens/lib/series/metrics_columns.ts @@ -25,6 +25,7 @@ import { convertMetricAggregationColumnWithoutSpecialParams, convertToCounterRateColumn, convertToStandartDeviationColumn, + convertVarianceToFormulaColumn, } from '../convert'; import { getValidColumns } from './columns'; @@ -120,6 +121,10 @@ export const getMetricsColumns = ( const column = convertToLastValueColumn(columnsConverterArgs, reducedTimeRange); return getValidColumns(column); } + case 'variance': { + const column = convertVarianceToFormulaColumn(columnsConverterArgs, reducedTimeRange); + return getValidColumns(column); + } case 'static': { const column = isStaticValueColumnSupported ? convertToStaticValueColumn(columnsConverterArgs, { diff --git a/src/plugins/vis_types/timeseries/public/request_handler.ts b/src/plugins/vis_types/timeseries/public/request_handler.ts index 4512034d3b124..a3b6d43893c3c 100644 --- a/src/plugins/vis_types/timeseries/public/request_handler.ts +++ b/src/plugins/vis_types/timeseries/public/request_handler.ts @@ -104,6 +104,7 @@ export const metricsRequestHandler = async ({ return visData; } catch (e) { searchTracker?.error(); + throw e; } finally { expressionAbortSignal.removeEventListener('abort', expressionAbortHandler); } diff --git a/src/plugins/vis_types/timeseries/server/lib/vis_data/response_processors/series/math.test.js b/src/plugins/vis_types/timeseries/server/lib/vis_data/response_processors/series/math.test.js index 3ff2ee0cba353..6d2a435a20b68 100644 --- a/src/plugins/vis_types/timeseries/server/lib/vis_data/response_processors/series/math.test.js +++ b/src/plugins/vis_types/timeseries/server/lib/vis_data/response_processors/series/math.test.js @@ -253,7 +253,7 @@ describe('math(resp, panel, series)', () => { )(await mathAgg(resp, panel, series)((results) => results))([]); } catch (e) { expect(e.message).toEqual( - 'Failed to parse expression. Expected "*", "+", "-", "/", end of input, or whitespace but "(" found.' + 'Failed to parse expression. Expected "*", "+", "-", "/", "<", "=", ">", end of input, or whitespace but "(" found.' ); } }); diff --git a/src/plugins/vis_types/xy/kibana.json b/src/plugins/vis_types/xy/kibana.json index fa942c1530142..474a70431fc73 100644 --- a/src/plugins/vis_types/xy/kibana.json +++ b/src/plugins/vis_types/xy/kibana.json @@ -3,7 +3,7 @@ "version": "kibana", "ui": true, "server": true, - "requiredPlugins": ["charts", "visualizations", "data", "expressions"], + "requiredPlugins": ["charts", "visualizations", "data", "expressions", "dataViews"], "requiredBundles": ["kibanaUtils", "visDefaultEditor"], "extraPublicDirs": ["common/index"], "owner": { diff --git a/src/plugins/vis_types/xy/public/convert_to_lens/configurations/index.test.ts b/src/plugins/vis_types/xy/public/convert_to_lens/configurations/index.test.ts new file mode 100644 index 0000000000000..2d8c7da9ba801 --- /dev/null +++ b/src/plugins/vis_types/xy/public/convert_to_lens/configurations/index.test.ts @@ -0,0 +1,160 @@ +/* + * 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 { Column } from '@kbn/visualizations-plugin/common/convert_to_lens'; +import { getConfiguration } from '.'; +import { Layer } from '..'; +import { ChartType } from '../..'; +import { sampleAreaVis } from '../../sample_vis.test.mocks'; +import { ChartMode, InterpolationMode } from '../../types'; + +describe('getConfiguration', () => { + const layers: Layer[] = [ + { + indexPatternId: '', + layerId: 'layer-1', + columns: [ + { columnId: '1', isBucketed: false }, + { columnId: '2', isBucketed: true, isSplit: false, operationType: 'date_histogram' }, + { columnId: '3', isBucketed: true, isSplit: true }, + ] as Column[], + metrics: ['1'], + columnOrder: [], + seriesIdsMap: { 1: '1' }, + collapseFn: 'max', + isReferenceLineLayer: false, + }, + { + indexPatternId: '', + layerId: 'layer-2', + columns: [ + { columnId: '4', isBucketed: false }, + { columnId: '5', isBucketed: true, isSplit: false, operationType: 'date_histogram' }, + ] as Column[], + metrics: ['4'], + columnOrder: [], + seriesIdsMap: { 4: '2' }, + collapseFn: undefined, + isReferenceLineLayer: false, + }, + { + indexPatternId: '', + layerId: 'layer-3', + columns: [{ columnId: '7', isBucketed: false }] as Column[], + columnOrder: [], + metrics: ['7'], + seriesIdsMap: {}, + collapseFn: undefined, + isReferenceLineLayer: true, + }, + ]; + const series = [ + { + show: true, + type: ChartType.Area, + mode: ChartMode.Stacked, + data: { + label: 'Sum of total_quantity', + id: '1', + }, + drawLinesBetweenPoints: true, + showCircles: true, + circlesRadius: 5, + interpolate: InterpolationMode.Linear, + valueAxis: 'ValueAxis-1', + }, + { + show: true, + type: ChartType.Line, + mode: ChartMode.Stacked, + data: { + label: 'Sum of total_quantity 1', + id: '2', + }, + drawLinesBetweenPoints: true, + showCircles: true, + circlesRadius: 5, + interpolate: InterpolationMode.Linear, + valueAxis: 'ValueAxis-1', + }, + ]; + + test('should return correct configuration', () => { + expect(getConfiguration(layers, series, sampleAreaVis as any)).toEqual({ + axisTitlesVisibilitySettings: { x: true, yLeft: true, yRight: true }, + curveType: 'LINEAR', + fillOpacity: 0.5, + fittingFunction: undefined, + gridlinesVisibilitySettings: { x: false, yLeft: false, yRight: true }, + labelsOrientation: { x: -0, yLeft: -0, yRight: -90 }, + layers: [ + { + accessors: ['1'], + collapseFn: 'max', + isHistogram: true, + layerId: 'layer-1', + layerType: 'data', + palette: { name: 'default' }, + seriesType: 'area_stacked', + simpleView: false, + splitAccessor: '3', + xAccessor: '2', + xScaleType: 'ordinal', + yConfig: [{ axisMode: 'left', forAccessor: '1' }], + }, + { + accessors: ['4'], + collapseFn: undefined, + isHistogram: true, + layerId: 'layer-2', + layerType: 'data', + palette: { name: 'default' }, + seriesType: 'area_stacked', + simpleView: false, + splitAccessor: undefined, + xAccessor: '5', + xScaleType: 'ordinal', + yConfig: [{ axisMode: 'left', forAccessor: '4' }], + }, + { + accessors: ['7'], + layerId: 'layer-3', + layerType: 'referenceLine', + yConfig: [ + { + axisMode: 'left', + color: '#E7664C', + forAccessor: '7', + lineStyle: 'solid', + lineWidth: 1, + }, + ], + }, + ], + legend: { + isVisible: true, + legendSize: 'small', + maxLines: 1, + position: 'top', + shouldTruncate: true, + showSingleSeries: true, + }, + tickLabelsVisibilitySettings: { x: true, yLeft: true, yRight: true }, + valueLabels: 'hide', + valuesInLegend: false, + xTitle: undefined, + yLeftExtent: { enforce: true, lowerBound: undefined, mode: 'full', upperBound: undefined }, + yLeftScale: 'linear', + yRightExtent: undefined, + yRightScale: 'linear', + yRightTitle: undefined, + yTitle: 'Sum of total_quantity', + showCurrentTimeMarker: false, + }); + }); +}); diff --git a/src/plugins/vis_types/xy/public/convert_to_lens/configurations/index.ts b/src/plugins/vis_types/xy/public/convert_to_lens/configurations/index.ts new file mode 100644 index 0000000000000..9674c47b33bc5 --- /dev/null +++ b/src/plugins/vis_types/xy/public/convert_to_lens/configurations/index.ts @@ -0,0 +1,282 @@ +/* + * 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 { Position, ScaleType as ECScaleType } from '@elastic/charts'; +import { + SeriesTypes, + Column, + XYConfiguration, + XYDataLayerConfig, + XYReferenceLineLayerConfig, +} from '@kbn/visualizations-plugin/common/convert_to_lens'; +import { Vis } from '@kbn/visualizations-plugin/public'; +import { Layer } from '..'; +import { ChartType } from '../../../common'; +import { + CategoryAxis, + ChartMode, + InterpolationMode, + Scale, + ScaleType, + SeriesParam, + ThresholdLineStyle, + ValueAxis, + VisParams, +} from '../../types'; +import { getCurveType, getMode, getYAxisPosition } from '../../utils/common'; + +function getYScaleType(scale?: Scale): XYConfiguration['yLeftScale'] | undefined { + const type = scale?.type; + if (type === ScaleType.SquareRoot) { + return ECScaleType.Sqrt; + } + + return type; +} + +function getXScaleType(xColumn?: Column) { + if (xColumn?.dataType === 'date') return ECScaleType.Time; + + if (xColumn?.dataType !== 'number') { + return ECScaleType.Ordinal; + } + + return ECScaleType.Linear; +} + +function getLabelOrientation(data?: CategoryAxis, isTimeChart = false) { + // lens doesn't support 75 as rotate option, we should use 45 instead + return -(data?.labels.rotate === 75 ? 45 : data?.labels.rotate ?? (isTimeChart ? 0 : 90)); +} + +function getExtents(axis: ValueAxis, series: SeriesParam[]) { + // for area and bar charts we should include 0 to bounds + const isAssignedToAreaOrBar = series.some( + (s) => s.valueAxis === axis.id && (s.type === 'histogram' || s.type === 'area') + ); + return { + mode: getMode(axis.scale), + lowerBound: + axis.scale.min !== null + ? isAssignedToAreaOrBar && axis.scale.min && axis.scale.min > 0 + ? 0 + : axis.scale.min + : undefined, + upperBound: + axis.scale.max !== null + ? isAssignedToAreaOrBar && axis.scale.max && axis.scale.max < 0 + ? 0 + : axis.scale.max + : undefined, + enforce: true, + }; +} + +function getSeriesType( + type?: ChartType, + mode?: ChartMode, + isHorizontal?: boolean, + isPercentage?: boolean +): XYDataLayerConfig['seriesType'] { + let seriesType: XYDataLayerConfig['seriesType'] = + type === 'histogram' ? SeriesTypes.BAR : type ?? SeriesTypes.AREA; + + // only bar chart supports horizontal mode + if (isHorizontal && seriesType === SeriesTypes.BAR) { + seriesType = (seriesType + '_horizontal') as XYDataLayerConfig['seriesType']; + } + + // line percentage should convert to area percentage + if (isPercentage) { + seriesType = ((seriesType !== SeriesTypes.LINE ? seriesType : SeriesTypes.AREA) + + '_percentage') as XYDataLayerConfig['seriesType']; + } + + // percentage chart should be stacked + // line stacked should convert to area stacked + if (isPercentage || mode === 'stacked') { + seriesType = ((seriesType !== SeriesTypes.LINE ? seriesType : SeriesTypes.AREA) + + '_stacked') as XYDataLayerConfig['seriesType']; + } + + return seriesType; +} + +function getDataLayers( + layers: Layer[], + series: SeriesParam[], + vis: Vis +): XYDataLayerConfig[] { + const overwriteColors: Record = vis.uiState.get('vis.colors', {}); + return layers.map((layer) => { + const xColumn = layer.columns.find((c) => c.isBucketed && !c.isSplit); + const splitAccessor = layer.columns.find( + (column) => column.isBucketed && column.isSplit + )?.columnId; + // as type and mode will be the same for all metrics we can use first to define it + const firstSeries = series.find((s) => s.data.id === layer.seriesIdsMap[layer.metrics[0]]); + const isHistogram = + xColumn?.operationType === 'date_histogram' || + (xColumn?.operationType === 'range' && xColumn.params.type === 'histogram'); + const firstYAxis = (vis.params.valueAxes ?? vis.type.visConfig.defaults.valueAxes).find( + (axis) => axis.id === firstSeries?.valueAxis + ); + const isPercentage = firstYAxis?.scale.mode === 'percentage'; + const isHorizontal = + firstYAxis?.position !== Position.Left && firstYAxis?.position !== Position.Right; + const seriesType = getSeriesType( + firstSeries?.type, + firstSeries?.mode, + isHorizontal, + isPercentage + ); + + return { + layerId: layer.layerId, + accessors: layer.metrics, + layerType: 'data', + seriesType, + xAccessor: xColumn?.columnId, + simpleView: false, + splitAccessor, + palette: vis.params.palette ?? vis.type.visConfig.defaults.palette, + yConfig: layer.metrics.map((metricId) => { + const serie = series.find((s) => s.data.id === layer.seriesIdsMap[metricId]); + const yAxis = (vis.params.valueAxes ?? vis.type.visConfig.defaults.valueAxes).find( + (axis) => axis.id === serie?.valueAxis + ); + return { + forAccessor: metricId, + axisMode: getYAxisPosition(yAxis?.position ?? 'left'), + color: + !splitAccessor && serie?.data.label ? overwriteColors[serie?.data.label] : undefined, + }; + }), + xScaleType: getXScaleType(xColumn), + isHistogram, + collapseFn: layer.collapseFn, + }; + }); +} + +function getReferenceLineLayers( + layers: Layer[], + vis: Vis +): XYReferenceLineLayerConfig[] { + const thresholdLineConfig = vis.params.thresholdLine ?? vis.type.visConfig.defaults.thresholdLine; + // threshold line is always assigned to the first value axis + const yAxis = (vis.params.valueAxes ?? vis.type.visConfig.defaults.valueAxes)[0]; + return layers.map((layer) => { + return { + layerType: 'referenceLine', + layerId: layer.layerId, + accessors: layer.metrics, + yConfig: layer.metrics.map((metricId) => { + return { + forAccessor: metricId, + axisMode: getYAxisPosition(yAxis?.position ?? 'left'), + color: thresholdLineConfig.color, + lineWidth: thresholdLineConfig.width !== null ? thresholdLineConfig.width : undefined, + lineStyle: + thresholdLineConfig.style === ThresholdLineStyle.DotDashed || + thresholdLineConfig.style === ThresholdLineStyle.Full + ? 'solid' + : thresholdLineConfig.style, + }; + }), + }; + }); +} + +export const getConfiguration = ( + layers: Layer[], + series: SeriesParam[], + vis: Vis +): XYConfiguration => { + const legendDisplayFromUiState = vis.uiState.get('vis.legendOpen') ?? true; + const yRightAxis = (vis.params.valueAxes ?? vis.type.visConfig.defaults.valueAxes).find( + (axis) => getYAxisPosition(axis.position) === Position.Right + ); + const yLeftAxis = (vis.params.valueAxes ?? vis.type.visConfig.defaults.valueAxes).find( + (axis) => getYAxisPosition(axis.position) === Position.Left + ); + // as we have only one x-axis + const xAxis = (vis.params.categoryAxes ?? vis.type.visConfig.defaults.categoryAxes)[0]; + const axisTitlesVisibilitySettings = { + x: xAxis.show, + yLeft: yLeftAxis?.show ?? true, + yRight: yRightAxis?.show ?? true, + }; + const xColumn = layers[0].columns.find((c) => c.isBucketed && !c.isSplit); + const isTimeChart = xColumn?.operationType === 'date_histogram'; + const fittingFunction = vis.params.fittingFunction ?? vis.type.visConfig.defaults.fittingFunction; + return { + layers: [ + ...getDataLayers( + layers.filter((l) => !l.isReferenceLineLayer), + series, + vis + ), + ...getReferenceLineLayers( + layers.filter((l) => l.isReferenceLineLayer), + vis + ), + ], + legend: { + isVisible: + legendDisplayFromUiState && (vis.params.addLegend ?? vis.type.visConfig.defaults.addLegend), + position: vis.params.legendPosition ?? vis.type.visConfig.defaults.legendPosition, + legendSize: vis.params.legendSize ?? vis.type.visConfig.defaults.legendSize, + shouldTruncate: vis.params.truncateLegend ?? vis.type.visConfig.defaults.truncateLegend, + maxLines: vis.params.maxLegendLines ?? vis.type.visConfig.defaults.maxLegendLines, + showSingleSeries: true, + }, + fittingFunction: fittingFunction + ? fittingFunction[0].toUpperCase() + fittingFunction.slice(1) + : undefined, + fillOpacity: vis.params.fillOpacity ?? vis.type.visConfig.defaults.fillOpacity, + gridlinesVisibilitySettings: { + x: vis.params.grid.categoryLines ?? vis.type.visConfig.defaults.grid?.categoryLines, + yLeft: + (vis.params.grid.valueAxis ?? vis.type.visConfig.defaults.grid?.valueAxis) === + yLeftAxis?.id, + yRight: + (vis.params.grid.valueAxis ?? vis.type.visConfig.defaults.grid?.valueAxis) === + yRightAxis?.id, + }, + axisTitlesVisibilitySettings, + tickLabelsVisibilitySettings: { + x: axisTitlesVisibilitySettings.x && (xAxis.labels.show ?? true), + yLeft: axisTitlesVisibilitySettings.yLeft && (yLeftAxis?.labels.show ?? true), + yRight: axisTitlesVisibilitySettings.yRight && (yRightAxis?.labels.show ?? true), + }, + labelsOrientation: { + x: getLabelOrientation(xAxis, isTimeChart), + yLeft: getLabelOrientation(yLeftAxis), + yRight: getLabelOrientation(yRightAxis), + }, + yLeftScale: getYScaleType(yLeftAxis?.scale) ?? ECScaleType.Linear, + yRightScale: getYScaleType(yRightAxis?.scale) ?? ECScaleType.Linear, + yLeftExtent: yLeftAxis?.scale ? getExtents(yLeftAxis, series) : undefined, + yRightExtent: yRightAxis?.scale ? getExtents(yRightAxis, series) : undefined, + yTitle: yLeftAxis?.title.text, + yRightTitle: yRightAxis?.title.text, + xTitle: xAxis.title.text, + valueLabels: + vis.params.labels.show ?? vis.type.visConfig.defaults.labels?.show ? 'show' : 'hide', + valuesInLegend: Boolean(vis.params.labels.show ?? vis.type.visConfig.defaults.labels?.show), + showCurrentTimeMarker: isTimeChart + ? Boolean(vis.params.addTimeMarker ?? vis.type.visConfig.defaults.addTimeMarker) + : undefined, + curveType: getCurveType( + series[0].interpolate === InterpolationMode.StepAfter + ? InterpolationMode.Linear + : series[0].interpolate + ), + }; +}; diff --git a/src/plugins/vis_types/xy/public/convert_to_lens/index.test.ts b/src/plugins/vis_types/xy/public/convert_to_lens/index.test.ts new file mode 100644 index 0000000000000..c77794e22ab78 --- /dev/null +++ b/src/plugins/vis_types/xy/public/convert_to_lens/index.test.ts @@ -0,0 +1,202 @@ +/* + * 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 { convertToLens } from '.'; +import { sampleAreaVis } from '../sample_vis.test.mocks'; + +const mockGetColumnsFromVis = jest.fn(); +const mockCreateStaticValueColumn = jest.fn().mockReturnValue({ operationType: 'static_value' }); +const mockGetVisSchemas = jest.fn().mockReturnValue({ + metric: [{ aggId: '1' }], +}); +const mockGetConfiguration = jest.fn().mockReturnValue({}); + +jest.mock('../services', () => ({ + getDataViewsStart: jest.fn(() => ({ get: () => ({}), getDefault: () => ({}) })), +})); + +jest.mock('../utils/get_series_params', () => ({ + getSeriesParams: jest.fn(() => undefined), +})); + +jest.mock('@kbn/visualizations-plugin/public', () => ({ + convertToLensModule: Promise.resolve({ + getColumnsFromVis: jest.fn(() => mockGetColumnsFromVis()), + createStaticValueColumn: jest.fn(() => mockCreateStaticValueColumn()), + }), + getDataViewByIndexPatternId: jest.fn(() => ({ id: 'index-pattern' })), + getVisSchemas: jest.fn(() => mockGetVisSchemas()), +})); + +jest.mock('./configurations', () => ({ + getConfiguration: jest.fn(() => mockGetConfiguration()), +})); + +describe('convertToLens', () => { + afterEach(() => { + jest.clearAllMocks(); + }); + + test('should return null if getColumnsFromVis returns null', async () => { + mockGetColumnsFromVis.mockReturnValue(null); + const result = await convertToLens(sampleAreaVis as any, { getAbsoluteTime: () => {} } as any); + expect(mockGetColumnsFromVis).toBeCalledTimes(1); + expect(result).toBeNull(); + }); + + test('should return null if multi split series defined', async () => { + mockGetVisSchemas.mockReturnValue({ + metric: [{ aggId: '1' }], + group: [{}, {}], + }); + const result = await convertToLens(sampleAreaVis as any, { getAbsoluteTime: () => {} } as any); + expect(mockGetVisSchemas).toBeCalledTimes(1); + expect(result).toBeNull(); + }); + + test('should return null if sibling pipeline agg defined together with split series', async () => { + mockGetColumnsFromVis.mockReturnValue([ + { + buckets: { all: ['1'], customBuckets: { metric1: '2' } }, + }, + ]); + mockGetVisSchemas.mockReturnValue({ + metric: [{ aggId: '1' }], + group: [{}], + }); + const result = await convertToLens(sampleAreaVis as any, { getAbsoluteTime: () => {} } as any); + expect(mockGetColumnsFromVis).toBeCalledTimes(1); + expect(result).toBeNull(); + }); + + test('should return null if defined several layers with terms split series which uses one of the metrics as order agg', async () => { + mockGetColumnsFromVis.mockReturnValue([ + { + buckets: { all: ['1'], customBuckets: { metric1: '2' } }, + columns: [{ isSplit: true, params: { orderBy: { type: 'column' } } }], + }, + { + buckets: { all: ['2'], customBuckets: { metric1: '2' } }, + columns: [{}], + }, + ]); + mockGetVisSchemas.mockReturnValue({ + metric: [{ aggId: '1' }, { aggId: '2' }], + }); + const result = await convertToLens(sampleAreaVis as any, { getAbsoluteTime: () => {} } as any); + expect(mockGetColumnsFromVis).toBeCalledTimes(1); + expect(result).toBeNull(); + }); + + test('should return null if more than one axis left/right/top/bottom defined', async () => { + mockGetColumnsFromVis.mockReturnValue([ + { + buckets: { all: ['1'], customBuckets: {} }, + columns: [], + }, + ]); + mockGetVisSchemas.mockReturnValue({ + metric: [{ aggId: '1' }, { aggId: '2' }], + }); + const result = await convertToLens( + { + ...sampleAreaVis, + params: { + ...sampleAreaVis.params, + valueAxes: [ + ...sampleAreaVis.params.valueAxes, + { + id: 'ValueAxis-2', + name: 'LeftAxis-2', + type: 'value', + position: 'left', + data: { + id: '2', + }, + }, + ], + seriesParams: [ + ...sampleAreaVis.params.seriesParams, + { show: true, valueAxis: 'ValueAxis-2', data: { id: '2' } }, + ], + }, + } as any, + { getAbsoluteTime: () => {} } as any + ); + expect(mockGetColumnsFromVis).toBeCalledTimes(1); + expect(result).toBeNull(); + }); + + test('should state for valid vis', async () => { + mockGetColumnsFromVis.mockReturnValue([ + { + buckets: { all: ['2', '3'], customBuckets: { 1: '3' } }, + columns: [ + { columnId: '2', isBucketed: true }, + { columnId: '1', meta: { aggId: '1' } }, + { columnId: '3', isBucketed: true }, + ], + bucketCollapseFn: { sum: ['3'] }, + metrics: ['1'], + }, + { + buckets: { all: ['2'], customBuckets: {} }, + columns: [ + { columnId: '2', isBucketed: true }, + { columnId: '1', meta: { aggId: '2' } }, + ], + metrics: ['1'], + bucketCollapseFn: {}, + }, + ]); + mockGetVisSchemas.mockReturnValue({ + metric: [{ aggId: '1' }], + }); + const result = await convertToLens( + { + ...sampleAreaVis, + params: { + ...sampleAreaVis.params, + valueAxes: [ + ...sampleAreaVis.params.valueAxes, + { + id: 'ValueAxis-2', + name: 'LeftAxis-2', + type: 'value', + position: 'left', + data: { + id: '2', + }, + }, + ], + seriesParams: [ + ...sampleAreaVis.params.seriesParams, + { show: true, valueAxis: 'ValueAxis-2', data: { id: '2' } }, + ], + thresholdLine: { ...sampleAreaVis.params.thresholdLine, show: true }, + }, + } as any, + { getAbsoluteTime: () => {} } as any + ); + expect(mockGetColumnsFromVis).toBeCalledTimes(1); + expect(mockGetConfiguration).toBeCalledTimes(1); + expect(mockCreateStaticValueColumn).toBeCalledTimes(1); + expect(result?.type).toEqual('lnsXY'); + expect(result?.layers.length).toEqual(3); + expect(result?.layers[0].columns).toEqual([ + { columnId: '2', isBucketed: true }, + { columnId: '1' }, + { columnId: '3', isBucketed: true }, + ]); + expect(result?.layers[1].columns).toEqual([ + { columnId: '2', isBucketed: true }, + { columnId: '1' }, + ]); + expect(result?.layers[2].columns).toEqual([{ operationType: 'static_value' }]); + }); +}); diff --git a/src/plugins/vis_types/xy/public/convert_to_lens/index.ts b/src/plugins/vis_types/xy/public/convert_to_lens/index.ts new file mode 100644 index 0000000000000..3b4339828c6d5 --- /dev/null +++ b/src/plugins/vis_types/xy/public/convert_to_lens/index.ts @@ -0,0 +1,214 @@ +/* + * 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 { METRIC_TYPES } from '@kbn/data-plugin/public'; +import { Column, ColumnWithMeta } from '@kbn/visualizations-plugin/common'; +import { + convertToLensModule, + getVisSchemas, + getDataViewByIndexPatternId, +} from '@kbn/visualizations-plugin/public'; +import { getDataViewsStart } from '../services'; +import { getSeriesParams } from '../utils/get_series_params'; +import { ConvertXYToLensVisualization } from './types'; + +export interface Layer { + indexPatternId: string; + layerId: string; + columns: Column[]; + metrics: string[]; + columnOrder: never[]; + seriesIdsMap: Record; + isReferenceLineLayer: boolean; + collapseFn?: string; +} + +const SIBBLING_PIPELINE_AGGS: string[] = [ + METRIC_TYPES.AVG_BUCKET, + METRIC_TYPES.SUM_BUCKET, + METRIC_TYPES.MAX_BUCKET, + METRIC_TYPES.MIN_BUCKET, +]; + +export const isColumnWithMeta = (column: Column): column is ColumnWithMeta => { + if ((column as ColumnWithMeta).meta) { + return true; + } + return false; +}; + +export const excludeMetaFromColumn = (column: Column) => { + if (isColumnWithMeta(column)) { + const { meta, ...rest } = column; + return rest; + } + return column; +}; + +export const convertToLens: ConvertXYToLensVisualization = async (vis, timefilter) => { + if (!timefilter) { + return null; + } + + const dataViews = getDataViewsStart(); + const dataView = await getDataViewByIndexPatternId(vis.data.indexPattern?.id, dataViews); + + if (!dataView) { + return null; + } + + const visSchemas = getVisSchemas(vis, { + timefilter, + timeRange: timefilter.getAbsoluteTime(), + }); + + // doesn't support multi split series + if (visSchemas.group && visSchemas.group.length > 1) { + return null; + } + + const firstValueAxesId = vis.params.valueAxes[0].id; + const updatedSeries = getSeriesParams( + vis.data.aggs, + vis.params.seriesParams, + 'metric', + firstValueAxesId + ); + + const finalSeriesParams = updatedSeries ?? vis.params.seriesParams; + const visibleSeries = finalSeriesParams.filter( + (param) => param.show && visSchemas.metric.some((m) => m.aggId?.split('.')[0] === param.data.id) + ); + + const [{ getColumnsFromVis, createStaticValueColumn }, { getConfiguration }] = await Promise.all([ + convertToLensModule, + import('./configurations'), + ]); + const dataLayers = getColumnsFromVis( + vis, + timefilter, + dataView, + { + buckets: ['segment'], + splits: ['group'], + unsupported: ['split_row', 'split_column', 'radius'], + }, + { + dropEmptyRowsInDateHistogram: true, + supportMixedSiblingPipelineAggs: true, + isPercentageMode: false, + }, + visibleSeries + .reduce>((acc, s) => { + const series = acc.find(({ type, mode }) => type === s.type && mode === s.mode); + // sibling pipeline agg always generate new layer because of custom bucket + if ( + series && + visSchemas.metric.some( + (m) => + m.aggId?.split('.')[0] === s.data.id && !SIBBLING_PIPELINE_AGGS.includes(m.aggType) + ) + ) { + series.metrics.push(s.data.id); + } else { + acc.push({ metrics: [s.data.id], type: s.type, mode: s.mode }); + } + return acc; + }, []) + .map(({ metrics }) => ({ metrics })) + ); + + if (dataLayers === null) { + return null; + } + + // doesn't support several layers with terms split series which uses one of the metrics as order agg + if ( + dataLayers.length > 1 && + dataLayers.some((l) => + l.columns.some( + (c) => c.isSplit && 'orderBy' in c.params && c.params.orderBy.type === 'column' + ) + ) + ) { + return null; + } + + // doesn't support sibling pipeline aggs and split series together + if ( + visSchemas.group?.length && + dataLayers.some((l) => Object.keys(l.buckets.customBuckets).length) + ) { + return null; + } + + const visibleYAxes = vis.params.valueAxes.filter((axis) => + visibleSeries.some((seriesParam) => seriesParam.valueAxis === axis.id) + ); + + const positions = visibleYAxes.map((axis) => axis.position); + const uniqPoisitions = new Set(positions); + + // doesn't support more than one axis left/right/top/bottom + if (visibleYAxes.length > 1 && uniqPoisitions.size !== positions.length) { + return null; + } + + const indexPatternId = dataView.id!; + + const uuid = await import('uuid/v4'); + + const layers = dataLayers.map((l) => { + const layerId = uuid.default(); + const seriesIdsMap: Record = {}; + visibleSeries.forEach((s) => { + const column = l.columns.find( + (c) => !c.isBucketed && c.meta.aggId.split('.')[0] === s.data.id + ); + if (column) { + seriesIdsMap[column.columnId] = s.data.id; + } + }); + const collapseFn = l.bucketCollapseFn + ? Object.keys(l.bucketCollapseFn).find((key) => + l.bucketCollapseFn[key].includes(l.buckets.customBuckets[l.metrics[0]]) + ) + : undefined; + return { + indexPatternId, + layerId, + columns: l.columns.map(excludeMetaFromColumn), + metrics: l.metrics, + columnOrder: [], + seriesIdsMap, + collapseFn, + isReferenceLineLayer: false, + }; + }); + + if (vis.params.thresholdLine.show) { + const staticValueColumn = createStaticValueColumn(vis.params.thresholdLine.value || 0); + layers.push({ + indexPatternId, + layerId: uuid.default(), + columns: [staticValueColumn], + columnOrder: [], + metrics: [staticValueColumn.columnId], + isReferenceLineLayer: true, + collapseFn: undefined, + seriesIdsMap: {}, + }); + } + + return { + type: 'lnsXY', + layers: layers.map(({ seriesIdsMap, collapseFn, isReferenceLineLayer, ...rest }) => rest), + configuration: getConfiguration(layers, visibleSeries, vis), + indexPatternIds: [indexPatternId], + }; +}; diff --git a/src/plugins/vis_types/xy/public/convert_to_lens/types.ts b/src/plugins/vis_types/xy/public/convert_to_lens/types.ts new file mode 100644 index 0000000000000..5fa52b4221107 --- /dev/null +++ b/src/plugins/vis_types/xy/public/convert_to_lens/types.ts @@ -0,0 +1,17 @@ +/* + * 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 { TimefilterContract } from '@kbn/data-plugin/public'; +import { NavigateToLensContext, XYConfiguration } from '@kbn/visualizations-plugin/common'; +import { Vis } from '@kbn/visualizations-plugin/public'; +import { VisParams } from '../types'; + +export type ConvertXYToLensVisualization = ( + vis: Vis, + timefilter?: TimefilterContract +) => Promise | null>; diff --git a/src/plugins/vis_types/xy/public/plugin.ts b/src/plugins/vis_types/xy/public/plugin.ts index 4561006e43e92..ad75af4dfffdb 100644 --- a/src/plugins/vis_types/xy/public/plugin.ts +++ b/src/plugins/vis_types/xy/public/plugin.ts @@ -6,10 +6,11 @@ * Side Public License, v 1. */ -import type { CoreSetup, Plugin } from '@kbn/core/public'; +import type { CoreSetup, CoreStart, Plugin } from '@kbn/core/public'; import type { VisualizationsSetup } from '@kbn/visualizations-plugin/public'; import type { ChartsPluginSetup } from '@kbn/charts-plugin/public'; -import { setUISettings, setPalettesService } from './services'; +import type { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public'; +import { setUISettings, setPalettesService, setDataViewsStart } from './services'; import { visTypesDefinitions } from './vis_types'; @@ -24,6 +25,11 @@ export interface VisTypeXyPluginSetupDependencies { charts: ChartsPluginSetup; } +/** @internal */ +export interface VisTypeXyPluginStartDependencies { + dataViews: DataViewsPublicPluginStart; +} + type VisTypeXyCoreSetup = CoreSetup<{}, VisTypeXyPluginStart>; /** @internal */ @@ -42,7 +48,8 @@ export class VisTypeXyPlugin return {}; } - public start() { + public start(core: CoreStart, { dataViews }: VisTypeXyPluginStartDependencies) { + setDataViewsStart(dataViews); return {}; } } 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 e55debd7c77ba..b2660b7c66551 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 @@ -8,6 +8,8 @@ import { LegendSize } from '@kbn/visualizations-plugin/common'; +const mockUiStateGet = jest.fn().mockReturnValue(() => false); + export const sampleAreaVis = { type: { name: 'area', @@ -1918,5 +1920,10 @@ export const sampleAreaVis = { }, }, isHierarchical: () => false, - uiState: {}, + uiState: { + vis: { + legendOpen: false, + }, + get: mockUiStateGet, + }, }; diff --git a/src/plugins/vis_types/xy/public/services.ts b/src/plugins/vis_types/xy/public/services.ts index 2358bcb5ede2e..7513f6188ef0e 100644 --- a/src/plugins/vis_types/xy/public/services.ts +++ b/src/plugins/vis_types/xy/public/services.ts @@ -8,6 +8,7 @@ import type { CoreSetup } from '@kbn/core/public'; import type { ChartsPluginSetup } from '@kbn/charts-plugin/public'; +import type { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public'; import { createGetterSetter } from '@kbn/kibana-utils-plugin/public'; @@ -16,3 +17,6 @@ export const [getUISettings, setUISettings] = export const [getPalettesService, setPalettesService] = createGetterSetter('xy charts.palette'); + +export const [getDataViewsStart, setDataViewsStart] = + createGetterSetter('dataViews'); diff --git a/src/plugins/vis_types/xy/public/to_ast.ts b/src/plugins/vis_types/xy/public/to_ast.ts index 4041075b98c4d..b584fbac26bba 100644 --- a/src/plugins/vis_types/xy/public/to_ast.ts +++ b/src/plugins/vis_types/xy/public/to_ast.ts @@ -18,8 +18,8 @@ import { } from '@kbn/visualizations-plugin/public'; import { buildExpression, buildExpressionFunction } from '@kbn/expressions-plugin/public'; import { BUCKET_TYPES } from '@kbn/data-plugin/public'; -import { TimeRangeBounds } from '@kbn/data-plugin/common'; -import { PaletteOutput } from '@kbn/charts-plugin/common/expressions/palette/types'; +import type { TimeRangeBounds } from '@kbn/data-plugin/common'; +import type { PaletteOutput } from '@kbn/charts-plugin/common/expressions/palette/types'; import { Dimensions, Dimension, @@ -30,32 +30,15 @@ import { ValueAxis, Scale, ChartMode, - InterpolationMode, ScaleType, } from './types'; import { ChartType } from '../common'; import { getSeriesParams } from './utils/get_series_params'; import { getSafeId } from './utils/accessors'; - -interface Bounds { - min?: string | number; - max?: string | number; -} +import { Bounds, getCurveType, getLineStyle, getMode, getYAxisPosition } from './utils/common'; type YDimension = Omit & { accessor: string }; -const getCurveType = (type?: InterpolationMode) => { - switch (type) { - case 'cardinal': - return 'CURVE_MONOTONE_X'; - case 'step-after': - return 'CURVE_STEP_AFTER'; - case 'linear': - default: - return 'LINEAR'; - } -}; - const prepareLengend = (params: VisParams, legendSize?: LegendSize) => { const legend = buildExpressionFunction('legendConfig', { isVisible: params.addLegend, @@ -162,16 +145,6 @@ const prepareLayers = ( return buildExpression([dataLayer]); }; -const getMode = (scale: Scale, bounds?: Bounds) => { - if (scale.defaultYExtents) { - return 'dataBounds'; - } - - if (scale.setYExtents || bounds) { - return 'custom'; - } -}; - const getLabelArgs = (data: CategoryAxis, isTimeChart?: boolean) => { return { truncate: data.labels.truncate, @@ -215,18 +188,6 @@ function getScaleType( return type; } -function getYAxisPosition(position: Position) { - if (position === Position.Top) { - return Position.Right; - } - - if (position === Position.Bottom) { - return Position.Left; - } - - return position; -} - function getXAxisPosition(position: Position) { if (position === Position.Left) { return Position.Bottom; @@ -274,16 +235,6 @@ const prepareYAxis = (data: ValueAxis, showGridLines?: boolean) => { return buildExpression([yAxisConfig]); }; -const getLineStyle = (style: ThresholdLine['style']) => { - switch (style) { - case 'full': - return 'solid'; - case 'dashed': - case 'dot-dashed': - return style; - } -}; - const prepareReferenceLine = (thresholdLine: ThresholdLine, axisId: string) => { const referenceLine = buildExpressionFunction('referenceLine', { value: thresholdLine.value, @@ -483,6 +434,7 @@ export const toExpressionAst: VisToExpressionAst = async (vis, params splitColumnAccessor: dimensions.splitColumn?.map(prepareVisDimension), splitRowAccessor: dimensions.splitRow?.map(prepareVisDimension), valueLabels: vis.params.labels.show ? 'show' : 'hide', + valuesInLegend: vis.params.labels.show, singleTable: true, }); diff --git a/src/plugins/vis_types/xy/public/utils/common.ts b/src/plugins/vis_types/xy/public/utils/common.ts new file mode 100644 index 0000000000000..522cac2aa00ac --- /dev/null +++ b/src/plugins/vis_types/xy/public/utils/common.ts @@ -0,0 +1,62 @@ +/* + * 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 { Position } from '@elastic/charts'; +import type { AxisExtentConfig } from '@kbn/visualizations-plugin/common/convert_to_lens'; +import type { InterpolationMode, Scale, ThresholdLine } from '../types'; + +export interface Bounds { + min?: string | number; + max?: string | number; +} + +export const getCurveType = (type?: InterpolationMode) => { + switch (type) { + case 'cardinal': + return 'CURVE_MONOTONE_X'; + case 'step-after': + return 'CURVE_STEP_AFTER'; + case 'linear': + default: + return 'LINEAR'; + } +}; + +export const getMode = (scale: Scale, bounds?: Bounds): AxisExtentConfig['mode'] => { + if (scale.defaultYExtents) { + return 'dataBounds'; + } + + if (scale.setYExtents || bounds) { + return 'custom'; + } + + return 'full'; +}; + +export const getYAxisPosition = (position: Position) => { + if (position === Position.Top) { + return Position.Right; + } + + if (position === Position.Bottom) { + return Position.Left; + } + + return position; +}; + +export const getLineStyle = (style: ThresholdLine['style']) => { + switch (style) { + case 'full': + return 'solid'; + case 'dashed': + case 'dot-dashed': + return style; + } +}; diff --git a/src/plugins/vis_types/xy/public/vis_types/get_vis_type_from_params.ts b/src/plugins/vis_types/xy/public/vis_types/get_vis_type_from_params.ts index c1f79b041e807..1f7ead86843d9 100644 --- a/src/plugins/vis_types/xy/public/vis_types/get_vis_type_from_params.ts +++ b/src/plugins/vis_types/xy/public/vis_types/get_vis_type_from_params.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { VisParams } from '@kbn/visualizations-plugin/common'; +import type { VisParams } from '@kbn/visualizations-plugin/common'; export const getVisTypeFromParams = (params?: VisParams) => { let type = params?.seriesParams?.[0]?.type; diff --git a/src/plugins/vis_types/xy/public/vis_types/index.ts b/src/plugins/vis_types/xy/public/vis_types/index.ts index 93c973b5316c9..2f7a03b6aaf1c 100644 --- a/src/plugins/vis_types/xy/public/vis_types/index.ts +++ b/src/plugins/vis_types/xy/public/vis_types/index.ts @@ -6,14 +6,27 @@ * Side Public License, v 1. */ +import type { VisTypeDefinition } from '@kbn/visualizations-plugin/public'; +import type { VisParams } from '../types'; import { areaVisTypeDefinition } from './area'; import { lineVisTypeDefinition } from './line'; import { histogramVisTypeDefinition } from './histogram'; import { horizontalBarVisTypeDefinition } from './horizontal_bar'; +import { convertToLens } from '../convert_to_lens'; export const visTypesDefinitions = [ areaVisTypeDefinition, lineVisTypeDefinition, histogramVisTypeDefinition, horizontalBarVisTypeDefinition, -]; +].map>((defenition) => { + return { + ...defenition, + navigateToLens: async (vis, timefilter) => (vis ? convertToLens(vis, timefilter) : null), + getExpressionVariables: async (vis, timeFilter) => { + return { + canNavigateToLens: Boolean(vis?.params ? await convertToLens(vis, timeFilter) : null), + }; + }, + }; +}); diff --git a/src/plugins/visualizations/common/convert_to_lens/constants.ts b/src/plugins/visualizations/common/convert_to_lens/constants.ts index 12ed815bc7247..b3af9b9394d67 100644 --- a/src/plugins/visualizations/common/convert_to_lens/constants.ts +++ b/src/plugins/visualizations/common/convert_to_lens/constants.ts @@ -104,3 +104,33 @@ export const RANGE_MODES = { Range: 'range', Histogram: 'histogram', } as const; + +export const GaugeShapes = { + HORIZONTAL_BULLET: 'horizontalBullet', + VERTICAL_BULLET: 'verticalBullet', + ARC: 'arc', + CIRCLE: 'circle', +} as const; + +export const GaugeTicksPositions = { + HIDDEN: 'hidden', + AUTO: 'auto', + BANDS: 'bands', +} as const; + +export const GaugeLabelMajorModes = { + AUTO: 'auto', + CUSTOM: 'custom', + NONE: 'none', +} as const; + +export const GaugeCentralMajorModes = { + AUTO: 'auto', + CUSTOM: 'custom', + NONE: 'none', +} as const; + +export const GaugeColorModes = { + PALETTE: 'palette', + NONE: 'none', +} as const; diff --git a/src/plugins/visualizations/common/convert_to_lens/lib/configurations/index.ts b/src/plugins/visualizations/common/convert_to_lens/lib/configurations/index.ts new file mode 100644 index 0000000000000..c4592f50836c5 --- /dev/null +++ b/src/plugins/visualizations/common/convert_to_lens/lib/configurations/index.ts @@ -0,0 +1,10 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 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. + */ + +export { getPalette } from './palette'; +export { getPercentageModeConfig } from './percentage_mode'; diff --git a/src/plugins/visualizations/common/convert_to_lens/lib/configurations/palette.test.ts b/src/plugins/visualizations/common/convert_to_lens/lib/configurations/palette.test.ts new file mode 100644 index 0000000000000..e157803df1edb --- /dev/null +++ b/src/plugins/visualizations/common/convert_to_lens/lib/configurations/palette.test.ts @@ -0,0 +1,112 @@ +/* + * 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 { ColorSchemas } from '@kbn/charts-plugin/common'; +import { getPalette } from './palette'; +import { PaletteParams } from './types'; + +describe('getPalette', () => { + const params: PaletteParams = { + colorSchema: ColorSchemas.Greys, + colorsRange: [ + { type: 'range', from: 0, to: 100 }, + { type: 'range', from: 100, to: 200 }, + { type: 'range', from: 200, to: 300 }, + ], + invertColors: false, + }; + + test('should return undefined if empty color ranges were passed', () => { + const paramsWithNoneMetricColorMode: PaletteParams = { + ...params, + colorsRange: [], + }; + expect(getPalette(paramsWithNoneMetricColorMode, { isPercentageMode: false })).toBeUndefined(); + }); + + test('should return correct palette for percentage mode', () => { + expect(getPalette(params, { isPercentageMode: true, min: 0, max: 300 })).toEqual({ + name: 'custom', + params: { + colorStops: [ + { color: '#FFFFFF', stop: 0 }, + { color: '#979797', stop: 0.3333333333333333 }, + { color: '#000000', stop: 0.6666666666666666 }, + ], + continuity: 'none', + maxSteps: 5, + name: 'custom', + progression: 'fixed', + rangeMax: 1, + rangeMin: 0, + rangeType: 'number', + reverse: false, + stops: [ + { color: '#FFFFFF', stop: 0.3333333333333333 }, + { color: '#979797', stop: 0.6666666666666666 }, + { color: '#000000', stop: 1 }, + ], + }, + type: 'palette', + }); + }); + + test('should return correct palette for percentage mode with percent range type', () => { + expect(getPalette(params, { isPercentageMode: true, min: 0, max: 300 }, true)).toEqual({ + name: 'custom', + params: { + colorStops: [ + { color: '#FFFFFF', stop: 0 }, + { color: '#979797', stop: 33.33333333333333 }, + { color: '#000000', stop: 66.66666666666666 }, + ], + continuity: 'none', + maxSteps: 5, + name: 'custom', + progression: 'fixed', + rangeMax: 100, + rangeMin: 0, + rangeType: 'percent', + reverse: false, + stops: [ + { color: '#FFFFFF', stop: 33.33333333333333 }, + { color: '#979797', stop: 66.66666666666666 }, + { color: '#000000', stop: 100 }, + ], + }, + type: 'palette', + }); + }); + + test('should return correct palette', () => { + expect(getPalette(params, { isPercentageMode: false, min: 0, max: 300 })).toEqual({ + name: 'custom', + params: { + colorStops: [ + { color: '#FFFFFF', stop: 0 }, + { color: '#979797', stop: 100 }, + { color: '#000000', stop: 200 }, + ], + continuity: 'none', + maxSteps: 5, + name: 'custom', + progression: 'fixed', + rangeMax: 300, + rangeMin: 0, + rangeType: 'number', + reverse: false, + stops: [ + { color: '#FFFFFF', stop: 100 }, + { color: '#979797', stop: 200 }, + { color: '#000000', stop: 300 }, + ], + }, + type: 'palette', + }); + }); +}); diff --git a/src/plugins/visualizations/common/convert_to_lens/lib/configurations/palette.ts b/src/plugins/visualizations/common/convert_to_lens/lib/configurations/palette.ts new file mode 100644 index 0000000000000..a89177c914996 --- /dev/null +++ b/src/plugins/visualizations/common/convert_to_lens/lib/configurations/palette.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 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 color from 'color'; +import { CustomPaletteParams, PaletteOutput } from '@kbn/coloring'; +import { getStopsWithColorsFromRanges, PaletteConfig } from '../../../utils'; +import { PaletteParams } from './types'; +import { PercentageModeConfig, PercentageModeConfigWithMinMax } from '../../types'; + +type ColorStopsWithMinMax = Pick< + CustomPaletteParams, + 'colorStops' | 'stops' | 'steps' | 'rangeMax' | 'rangeMin' | 'continuity' +>; + +const buildPaletteParams = ({ color: colors, stop }: PaletteConfig): ColorStopsWithMinMax => { + const colorsWithoutStartColor = colors.slice(1, colors.length); + return { + rangeMin: stop[0], + rangeMax: stop[stop.length - 1], + continuity: 'none', + colorStops: colorsWithoutStartColor.map((c, index) => ({ + color: color(c!).hex(), + stop: stop[index], + })), + stops: colorsWithoutStartColor.map((c, index) => ({ + color: color(c!).hex(), + stop: stop[index + 1], + })), + }; +}; + +const buildCustomPalette = ( + colorStopsWithMinMax: ColorStopsWithMinMax, + isPercentRangeType: boolean = false +): PaletteOutput => { + return { + name: 'custom', + params: { + maxSteps: 5, + name: 'custom', + progression: 'fixed', + rangeMax: Infinity, + rangeMin: -Infinity, + rangeType: isPercentRangeType ? 'percent' : 'number', + reverse: false, + ...colorStopsWithMinMax, + }, + type: 'palette', + }; +}; + +const convertToPercents = ( + value: number, + { min, max }: PercentageModeConfigWithMinMax, + isPercentPaletteSupported: boolean +) => { + const percent = (value - min) / (max - min); + return isPercentPaletteSupported ? percent * 100 : percent; +}; + +const convertToPercentColorStops = ( + colorStops: PaletteConfig, + percentageModeConfig: PercentageModeConfigWithMinMax, + isPercentPaletteSupported: boolean = false +) => { + const stop = colorStops.stop.map((stopValue) => + convertToPercents(stopValue, percentageModeConfig, isPercentPaletteSupported) + ); + return { ...colorStops, stop }; +}; + +export const getPalette = ( + params: PaletteParams, + percentageModeConfig: PercentageModeConfig, + isPercentPaletteSupported: boolean = false +): PaletteOutput | undefined => { + const { colorSchema, colorsRange, invertColors } = params; + + if (!(colorsRange && colorsRange.length)) { + return; + } + + const stopsWithColors = getStopsWithColorsFromRanges(colorsRange, colorSchema, invertColors); + const percentStopsWithColors = percentageModeConfig.isPercentageMode + ? convertToPercentColorStops(stopsWithColors, percentageModeConfig, isPercentPaletteSupported) + : stopsWithColors; + + return buildCustomPalette( + buildPaletteParams(percentStopsWithColors), + isPercentPaletteSupported && percentageModeConfig.isPercentageMode + ); +}; diff --git a/src/plugins/visualizations/common/convert_to_lens/lib/configurations/percentage_mode.test.ts b/src/plugins/visualizations/common/convert_to_lens/lib/configurations/percentage_mode.test.ts new file mode 100644 index 0000000000000..f148bffc6ea88 --- /dev/null +++ b/src/plugins/visualizations/common/convert_to_lens/lib/configurations/percentage_mode.test.ts @@ -0,0 +1,36 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 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 { ColorSchemas } from '@kbn/charts-plugin/common'; +import { getPercentageModeConfig } from './percentage_mode'; +import { ExtendedPaletteParams } from './types'; + +const params: ExtendedPaletteParams = { + percentageMode: false, + colorSchema: ColorSchemas.Greys, + colorsRange: [ + { type: 'range', from: 0, to: 100 }, + { type: 'range', from: 100, to: 200 }, + { type: 'range', from: 200, to: 300 }, + ], + invertColors: false, +}; + +describe('getPercentageModeConfig', () => { + test('should return falsy percentage mode if percentage mode is off', () => { + expect(getPercentageModeConfig(params)).toEqual({ isPercentageMode: false }); + }); + + test('should return percentage mode config', () => { + expect(getPercentageModeConfig({ ...params, percentageMode: true })).toEqual({ + isPercentageMode: true, + min: 0, + max: 300, + }); + }); +}); diff --git a/src/plugins/visualizations/common/convert_to_lens/lib/configurations/percentage_mode.ts b/src/plugins/visualizations/common/convert_to_lens/lib/configurations/percentage_mode.ts new file mode 100644 index 0000000000000..d375856c620fe --- /dev/null +++ b/src/plugins/visualizations/common/convert_to_lens/lib/configurations/percentage_mode.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 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 { PercentageModeConfig } from '../../types'; +import { ExtendedPaletteParams } from './types'; + +export const getPercentageModeConfig = ( + params: ExtendedPaletteParams, + respectPercentageMode: boolean = true +): PercentageModeConfig => { + const { colorsRange } = params; + const minMax = { + min: colorsRange[0].from, + max: colorsRange[colorsRange.length - 1].to, + }; + if (!params.percentageMode) { + return respectPercentageMode + ? { isPercentageMode: false } + : { isPercentageMode: false, ...minMax }; + } + return { + isPercentageMode: true, + ...minMax, + }; +}; diff --git a/src/plugins/visualizations/common/convert_to_lens/lib/configurations/types.ts b/src/plugins/visualizations/common/convert_to_lens/lib/configurations/types.ts new file mode 100644 index 0000000000000..9bc19946b769f --- /dev/null +++ b/src/plugins/visualizations/common/convert_to_lens/lib/configurations/types.ts @@ -0,0 +1,20 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 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 { Range } from '@kbn/expressions-plugin/common'; +import { ColorSchemas } from '@kbn/charts-plugin/common'; + +export interface PaletteParams { + colorSchema: ColorSchemas; + colorsRange: Range[]; + invertColors: boolean; +} + +export interface ExtendedPaletteParams extends PaletteParams { + percentageMode: boolean; +} diff --git a/src/plugins/visualizations/common/convert_to_lens/lib/convert/index.ts b/src/plugins/visualizations/common/convert_to_lens/lib/convert/index.ts index 9da33607be2a9..7f1fb81fd20b8 100644 --- a/src/plugins/visualizations/common/convert_to_lens/lib/convert/index.ts +++ b/src/plugins/visualizations/common/convert_to_lens/lib/convert/index.ts @@ -21,3 +21,4 @@ export * from './types'; export * from './last_value'; export * from './range'; export * from './percentage_mode'; +export * from './static_value'; diff --git a/src/plugins/visualizations/common/convert_to_lens/lib/convert/metric.ts b/src/plugins/visualizations/common/convert_to_lens/lib/convert/metric.ts index f46adea9538dc..eb21b9f0fe91d 100644 --- a/src/plugins/visualizations/common/convert_to_lens/lib/convert/metric.ts +++ b/src/plugins/visualizations/common/convert_to_lens/lib/convert/metric.ts @@ -23,6 +23,7 @@ import { } from './types'; import { getFieldNameFromField } from '../utils'; import { isFieldValid } from '../../utils'; +import { Operation } from '../../types'; type MetricAggregationWithoutParams = | typeof Operations.AVERAGE @@ -97,12 +98,19 @@ export const convertMetricAggregationColumnWithoutSpecialParams = ( return null; } + const column = createColumn(agg, field, { + reducedTimeRange, + }); + return { operationType: aggregation.name, sourceField, - ...createColumn(agg, field, { - reducedTimeRange, - }), + ...column, + dataType: ([Operations.COUNT, Operations.UNIQUE_COUNT] as Operation[]).includes( + aggregation.name + ) + ? 'number' + : column.dataType, params: { ...getFormat() }, timeShift: agg.aggParams?.timeShift, }; diff --git a/src/plugins/visualizations/common/convert_to_lens/lib/convert/sibling_pipeline.ts b/src/plugins/visualizations/common/convert_to_lens/lib/convert/sibling_pipeline.ts index 03e1d955dd045..a8389cb8601e4 100644 --- a/src/plugins/visualizations/common/convert_to_lens/lib/convert/sibling_pipeline.ts +++ b/src/plugins/visualizations/common/convert_to_lens/lib/convert/sibling_pipeline.ts @@ -13,7 +13,7 @@ import { convertToSchemaConfig } from '../../../vis_schemas'; export const convertToSiblingPipelineColumns = ( columnConverterArgs: ExtendedColumnConverterArgs ): AggBasedColumn | null => { - const { aggParams, label } = columnConverterArgs.agg; + const { aggParams, label, aggId } = columnConverterArgs.agg; if (!aggParams) { return null; } @@ -23,7 +23,7 @@ export const convertToSiblingPipelineColumns = ( } const customMetricColumn = convertMetricToColumns( - { ...convertToSchemaConfig(aggParams.customMetric), label }, + { ...convertToSchemaConfig(aggParams.customMetric), label, aggId }, columnConverterArgs.dataView, columnConverterArgs.aggs ); diff --git a/src/plugins/visualizations/common/convert_to_lens/lib/convert/static_value.ts b/src/plugins/visualizations/common/convert_to_lens/lib/convert/static_value.ts new file mode 100644 index 0000000000000..0310e162b8e85 --- /dev/null +++ b/src/plugins/visualizations/common/convert_to_lens/lib/convert/static_value.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 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 uuid from 'uuid'; +import { StaticValueColumn } from '../../types'; + +export const createStaticValueColumn = (value: number): StaticValueColumn => ({ + operationType: 'static_value', + columnId: uuid(), + isBucketed: false, + isSplit: false, + dataType: 'number', + references: [], + params: { + value: value.toString(), + }, +}); diff --git a/src/plugins/visualizations/common/convert_to_lens/lib/convert/types.ts b/src/plugins/visualizations/common/convert_to_lens/lib/convert/types.ts index 3dfaee67a61e0..8e6f9ec9443bb 100644 --- a/src/plugins/visualizations/common/convert_to_lens/lib/convert/types.ts +++ b/src/plugins/visualizations/common/convert_to_lens/lib/convert/types.ts @@ -58,7 +58,7 @@ export type SiblingPipelineMetric = | METRIC_TYPES.MIN_BUCKET | METRIC_TYPES.MAX_BUCKET; -export type BucketColumn = DateHistogramColumn | TermsColumn | FiltersColumn; +export type BucketColumn = DateHistogramColumn | TermsColumn | FiltersColumn | RangeColumn; export interface CommonColumnConverterArgs< Agg extends SupportedAggregation = SupportedAggregation > { diff --git a/src/plugins/visualizations/common/convert_to_lens/lib/index.ts b/src/plugins/visualizations/common/convert_to_lens/lib/index.ts index 083450c8ff5d1..3c416dc5b95fa 100644 --- a/src/plugins/visualizations/common/convert_to_lens/lib/index.ts +++ b/src/plugins/visualizations/common/convert_to_lens/lib/index.ts @@ -9,3 +9,4 @@ export * from './buckets'; export * from './metrics'; export * from './convert'; +export * from './configurations'; diff --git a/src/plugins/visualizations/common/convert_to_lens/lib/metrics/metrics.test.ts b/src/plugins/visualizations/common/convert_to_lens/lib/metrics/metrics.test.ts index 207dedd133bc9..1cf3ff0b84064 100644 --- a/src/plugins/visualizations/common/convert_to_lens/lib/metrics/metrics.test.ts +++ b/src/plugins/visualizations/common/convert_to_lens/lib/metrics/metrics.test.ts @@ -598,7 +598,7 @@ describe('convertMetricToColumns valid cases', () => { { aggType: METRIC_TYPES.AVG_BUCKET } as SchemaConfig, dataView, [], - { isPercentageMode: true }, + { isPercentageMode: true, min: 0, max: 100 }, ], result, mockConvertToColumnInPercentageMode, diff --git a/src/plugins/visualizations/common/convert_to_lens/lib/utils.test.ts b/src/plugins/visualizations/common/convert_to_lens/lib/utils.test.ts index 73118b6ad4f03..1f91201aff503 100644 --- a/src/plugins/visualizations/common/convert_to_lens/lib/utils.test.ts +++ b/src/plugins/visualizations/common/convert_to_lens/lib/utils.test.ts @@ -365,7 +365,7 @@ describe('getCustomBucketsFromSiblingAggs', () => { }, params: {}, aggType: METRIC_TYPES.AVG_BUCKET, - aggId: 'some-agg-id', + aggId: 'some-agg-id-1', aggParams: { customBucket: bucketWithSerialize1, }, @@ -381,7 +381,7 @@ describe('getCustomBucketsFromSiblingAggs', () => { }, params: {}, aggType: METRIC_TYPES.AVG_BUCKET, - aggId: 'some-agg-id', + aggId: 'some-agg-id-2', aggParams: { customBucket: bucketWithSerialize2, }, @@ -399,7 +399,7 @@ describe('getCustomBucketsFromSiblingAggs', () => { }, params: {}, aggType: METRIC_TYPES.AVG_BUCKET, - aggId: 'some-agg-id', + aggId: 'some-agg-id-3', aggParams: { customBucket: bucketWithSerialize3, }, @@ -407,8 +407,8 @@ describe('getCustomBucketsFromSiblingAggs', () => { test("should filter out duplicated custom buckets, ignoring id's", () => { expect(getCustomBucketsFromSiblingAggs([metric1, metric2, metric3])).toEqual([ - bucketWithSerialize1, - bucketWithSerialize2, + { customBucket: bucketWithSerialize1, metricIds: ['some-agg-id-1', 'some-agg-id-3'] }, + { customBucket: bucketWithSerialize2, metricIds: ['some-agg-id-2'] }, ]); }); }); diff --git a/src/plugins/visualizations/common/convert_to_lens/lib/utils.ts b/src/plugins/visualizations/common/convert_to_lens/lib/utils.ts index c4e5c5474bf0c..ce50312d92cf3 100644 --- a/src/plugins/visualizations/common/convert_to_lens/lib/utils.ts +++ b/src/plugins/visualizations/common/convert_to_lens/lib/utils.ts @@ -151,19 +151,19 @@ export const isStdDevAgg = (metric: SchemaConfig): metric is SchemaConfig { - return metrics.reduce((acc, metric) => { - if ( - isSiblingPipeline(metric) && - metric.aggParams?.customBucket && - acc.every( - (bucket) => - !isEqual( - omit(metric.aggParams?.customBucket?.serialize(), ['id']), - omit(bucket.serialize(), ['id']) - ) - ) - ) { - acc.push(metric.aggParams.customBucket); + return metrics.reduce>((acc, metric) => { + if (isSiblingPipeline(metric) && metric.aggParams?.customBucket && metric.aggId) { + const customBucket = acc.find((bucket) => + isEqual( + omit(metric.aggParams?.customBucket?.serialize(), ['id']), + omit(bucket.customBucket.serialize(), ['id']) + ) + ); + if (customBucket) { + customBucket.metricIds.push(metric.aggId); + } else { + acc.push({ customBucket: metric.aggParams.customBucket, metricIds: [metric.aggId] }); + } } return acc; diff --git a/src/plugins/visualizations/common/convert_to_lens/types/common.ts b/src/plugins/visualizations/common/convert_to_lens/types/common.ts index c526a7116877d..63f9dcd482c58 100644 --- a/src/plugins/visualizations/common/convert_to_lens/types/common.ts +++ b/src/plugins/visualizations/common/convert_to_lens/types/common.ts @@ -51,6 +51,14 @@ export interface MinMax { max: number; } -export type PercentageModeConfig = - | ({ isPercentageMode: true } & MinMax) - | { isPercentageMode: boolean }; +export interface BasicFullPercentageModeConfig { + isPercentageMode: boolean; +} + +export interface BasicPercentageModeConfig { + isPercentageMode: false; +} + +export type PercentageModeConfigWithMinMax = BasicFullPercentageModeConfig & MinMax; + +export type PercentageModeConfig = BasicPercentageModeConfig | PercentageModeConfigWithMinMax; diff --git a/src/plugins/visualizations/common/convert_to_lens/types/configurations.ts b/src/plugins/visualizations/common/convert_to_lens/types/configurations.ts index a6a771d07e7a6..72d0323ac3525 100644 --- a/src/plugins/visualizations/common/convert_to_lens/types/configurations.ts +++ b/src/plugins/visualizations/common/convert_to_lens/types/configurations.ts @@ -21,6 +21,11 @@ import { YAxisModes, XYCurveTypes, LayerTypes, + GaugeShapes, + GaugeTicksPositions, + GaugeLabelMajorModes, + GaugeColorModes, + GaugeCentralMajorModes, } from '../constants'; export type FillType = $Values; @@ -32,6 +37,11 @@ export type CategoryDisplayType = $Values; export type NumberDisplayType = $Values; export type LegendDisplayType = $Values; export type LayerType = $Values; +export type GaugeColorMode = $Values; +export type GaugeShape = $Values; +export type GaugeLabelMajorMode = $Values; +export type GaugeCentralMajorMode = $Values; +export type GaugeTicksPosition = $Values; export interface AxisExtentConfig { mode: 'full' | 'custom' | 'dataBounds'; @@ -45,7 +55,7 @@ export interface YConfig { color?: string; icon?: string; lineWidth?: number; - lineStyle?: 'solid' | 'dashed' | 'dotted' | 'dot-dashed'; + lineStyle?: 'solid' | 'dashed' | 'dotted'; fill?: FillType; iconPosition?: 'auto' | 'left' | 'right' | 'above' | 'below'; textVisibility?: boolean; @@ -152,6 +162,7 @@ export interface XYConfiguration { fillOpacity?: number; hideEndzones?: boolean; valuesInLegend?: boolean; + showCurrentTimeMarker?: boolean; } export interface SortingState { @@ -227,8 +238,43 @@ export interface PartitionVisConfiguration { palette?: PaletteOutput; } +export const LENS_GAUGE_ID = 'lnsGauge'; + +export const GROUP_ID = { + METRIC: 'metric', + MIN: 'min', + MAX: 'max', + GOAL: 'goal', +} as const; + +interface GaugeState { + metricAccessor?: string; + minAccessor?: string; + maxAccessor?: string; + goalAccessor?: string; + ticksPosition: GaugeTicksPosition; + labelMajorMode: GaugeLabelMajorMode; + labelMajor?: string; + labelMinor?: string; + centralMajorMode?: GaugeCentralMajorMode; + centralMajor?: string; + colorMode?: GaugeColorMode; + palette?: PaletteOutput; + shape: GaugeShape; + /** @deprecated This field is deprecated and going to be removed in the futher release versions. */ + percentageMode?: boolean; + respectRanges?: boolean; + commonLabel?: string; +} + +export type GaugeVisConfiguration = GaugeState & { + layerId: string; + layerType: typeof LayerTypes.DATA; +}; + export type Configuration = | XYConfiguration | TableVisConfiguration | PartitionVisConfiguration - | MetricVisConfiguration; + | MetricVisConfiguration + | GaugeVisConfiguration; diff --git a/src/plugins/visualizations/common/convert_to_lens/utils.ts b/src/plugins/visualizations/common/convert_to_lens/utils.ts index 3536282d830d3..51c7e8239a439 100644 --- a/src/plugins/visualizations/common/convert_to_lens/utils.ts +++ b/src/plugins/visualizations/common/convert_to_lens/utils.ts @@ -6,9 +6,9 @@ * Side Public License, v 1. */ -import { DataViewField } from '@kbn/data-views-plugin/common'; -import { SupportedMetric } from './lib/convert/supported_metrics'; -import { Layer, XYAnnotationsLayerConfig, XYLayerConfig } from './types'; +import type { DataViewField } from '@kbn/data-views-plugin/common'; +import type { SupportedMetric } from './lib/convert/supported_metrics'; +import type { Layer, XYAnnotationsLayerConfig, XYLayerConfig } from './types'; export const isAnnotationsLayer = ( layer: Pick diff --git a/src/plugins/visualizations/common/utils/index.ts b/src/plugins/visualizations/common/utils/index.ts index 35e01a9121ac4..d960607238394 100644 --- a/src/plugins/visualizations/common/utils/index.ts +++ b/src/plugins/visualizations/common/utils/index.ts @@ -17,3 +17,5 @@ export { getAccessor, getFormatByAccessor, } from './accessors'; +export { getStopsWithColorsFromRanges } from './palette'; +export type { PaletteConfig } from './palette'; diff --git a/src/plugins/vis_types/gauge/public/utils/palette.ts b/src/plugins/visualizations/common/utils/palette.ts similarity index 100% rename from src/plugins/vis_types/gauge/public/utils/palette.ts rename to src/plugins/visualizations/common/utils/palette.ts diff --git a/src/plugins/visualizations/public/convert_to_lens/index.ts b/src/plugins/visualizations/public/convert_to_lens/index.ts index 9cd2ba2768ad7..73509d49157ae 100644 --- a/src/plugins/visualizations/public/convert_to_lens/index.ts +++ b/src/plugins/visualizations/public/convert_to_lens/index.ts @@ -7,4 +7,9 @@ */ export { getColumnsFromVis } from './schemas'; -export { getPercentageColumnFormulaColumn } from '../../common/convert_to_lens/lib'; +export { + getPercentageColumnFormulaColumn, + getPalette, + getPercentageModeConfig, + createStaticValueColumn, +} from '../../common/convert_to_lens/lib'; diff --git a/src/plugins/visualizations/public/convert_to_lens/schemas.test.ts b/src/plugins/visualizations/public/convert_to_lens/schemas.test.ts index 5b8b7832730b9..54975d08b8486 100644 --- a/src/plugins/visualizations/public/convert_to_lens/schemas.test.ts +++ b/src/plugins/visualizations/public/convert_to_lens/schemas.test.ts @@ -21,6 +21,7 @@ import { getColumnsFromVis } from './schemas'; const mockConvertMetricToColumns = jest.fn(); const mockConvertBucketToColumns = jest.fn(); const mockGetCutomBucketsFromSiblingAggs = jest.fn(); +const mockGetCustomBucketColumns = jest.fn(); const mockGetVisSchemas = jest.fn(); const mockGetBucketCollapseFn = jest.fn(); @@ -55,6 +56,7 @@ jest.mock('./utils', () => ({ getMetricsWithoutDuplicates: jest.fn(() => mockGetMetricsWithoutDuplicates()), isValidVis: jest.fn(() => mockIsValidVis()), sortColumns: jest.fn(() => mockSortColumns()), + getCustomBucketColumns: jest.fn(() => mockGetCustomBucketColumns()), })); describe('getColumnsFromVis', () => { @@ -73,6 +75,7 @@ describe('getColumnsFromVis', () => { jest.clearAllMocks(); mockGetVisSchemas.mockReturnValue({}); mockIsValidVis.mockReturnValue(true); + mockGetCustomBucketColumns.mockReturnValue({ customBucketColumns: [], customBucketsMap: {} }); }); test('should return null if vis is not valid', () => { @@ -107,7 +110,10 @@ describe('getColumnsFromVis', () => { test('should return null if one sibling agg was provided and it is not supported', () => { const buckets: AggConfig[] = [aggConfig]; mockGetCutomBucketsFromSiblingAggs.mockReturnValue(buckets); - mockConvertBucketToColumns.mockReturnValue(null); + mockGetCustomBucketColumns.mockReturnValue({ + customBucketColumns: [null], + customBucketsMap: {}, + }); mockGetMetricsWithoutDuplicates.mockReturnValue([{}]); const result = getColumnsFromVis(vis, dataServiceMock.query.timefilter.timefilter, dataView, { @@ -120,7 +126,7 @@ describe('getColumnsFromVis', () => { expect(mockIsValidVis).toBeCalledTimes(1); expect(mockGetCutomBucketsFromSiblingAggs).toBeCalledTimes(1); expect(mockGetMetricsWithoutDuplicates).toBeCalledTimes(1); - expect(mockConvertBucketToColumns).toBeCalledTimes(1); + expect(mockGetCustomBucketColumns).toBeCalledTimes(1); expect(mockGetBucketColumns).toBeCalledTimes(0); }); @@ -190,7 +196,7 @@ describe('getColumnsFromVis', () => { expect(mockSortColumns).toBeCalledTimes(0); }); - test('should return columns', () => { + test('should return one layer with columns', () => { const buckets: AggConfig[] = [aggConfig]; const bucketColumns = [ { @@ -238,13 +244,18 @@ describe('getColumnsFromVis', () => { buckets: [], }); - expect(result).toEqual({ - bucketCollapseFn, - buckets: [bucketId], - columns: [...metrics, ...buckets], - columnsWithoutReferenced, - metrics: [metricId], - }); + expect(result).toEqual([ + { + bucketCollapseFn, + buckets: { + all: [bucketId], + customBuckets: {}, + }, + columns: [...metrics, ...buckets], + columnsWithoutReferenced, + metrics: [metricId], + }, + ]); expect(mockGetVisSchemas).toBeCalledTimes(1); expect(mockIsValidVis).toBeCalledTimes(1); expect(mockGetCutomBucketsFromSiblingAggs).toBeCalledTimes(1); @@ -254,4 +265,84 @@ describe('getColumnsFromVis', () => { expect(mockSortColumns).toBeCalledTimes(1); expect(mockGetColumnsWithoutReferenced).toBeCalledTimes(1); }); + + test('should return several layer with columns if series is provided', () => { + const buckets: AggConfig[] = [aggConfig]; + const bucketColumns = [ + { + sourceField: 'some-field', + columnId: 'col3', + operationType: 'date_histogram', + isBucketed: false, + isSplit: false, + dataType: 'string', + params: { interval: '1h' }, + meta: { aggId: 'agg-id-1' }, + }, + ]; + const mectricAggs = [{ aggId: 'col-id-3' }, { aggId: 'col-id-4' }]; + const metrics = [ + { + sourceField: 'some-field', + columnId: 'col2', + operationType: 'max', + isBucketed: false, + isSplit: false, + dataType: 'string', + params: {}, + meta: { aggId: 'col-id-3' }, + }, + { + sourceField: 'some-field', + columnId: 'col3', + operationType: 'max', + isBucketed: false, + isSplit: false, + dataType: 'string', + params: {}, + meta: { aggId: 'col-id-4' }, + }, + ]; + + const columnsWithoutReferenced = ['col2']; + const metricId = 'metric1'; + const bucketId = 'bucket1'; + const bucketCollapseFn = 'max'; + + mockGetCutomBucketsFromSiblingAggs.mockReturnValue([]); + mockGetMetricsWithoutDuplicates.mockReturnValue(mectricAggs); + mockConvertMetricToColumns.mockReturnValue(metrics); + mockConvertBucketToColumns.mockReturnValue(bucketColumns); + mockGetBucketColumns.mockReturnValue(bucketColumns); + mockGetColumnsWithoutReferenced.mockReturnValue(columnsWithoutReferenced); + mockSortColumns.mockReturnValue([...metrics, ...buckets]); + mockGetColumnIds.mockReturnValueOnce([metricId]); + mockGetColumnIds.mockReturnValueOnce([bucketId]); + mockGetColumnIds.mockReturnValueOnce([metricId]); + mockGetColumnIds.mockReturnValueOnce([bucketId]); + mockGetBucketCollapseFn.mockReturnValueOnce(bucketCollapseFn); + mockGetBucketCollapseFn.mockReturnValueOnce(bucketCollapseFn); + + const result = getColumnsFromVis( + vis, + dataServiceMock.query.timefilter.timefilter, + dataView, + { + splits: [], + buckets: [], + }, + undefined, + [{ metrics: ['col-id-3'] }, { metrics: ['col-id-4'] }] + ); + + expect(result?.length).toEqual(2); + expect(mockGetVisSchemas).toBeCalledTimes(1); + expect(mockIsValidVis).toBeCalledTimes(1); + expect(mockGetCutomBucketsFromSiblingAggs).toBeCalledTimes(1); + expect(mockGetMetricsWithoutDuplicates).toBeCalledTimes(1); + expect(mockConvertMetricToColumns).toBeCalledTimes(2); + expect(mockGetBucketColumns).toBeCalledTimes(4); + expect(mockSortColumns).toBeCalledTimes(2); + expect(mockGetColumnsWithoutReferenced).toBeCalledTimes(2); + }); }); diff --git a/src/plugins/visualizations/public/convert_to_lens/schemas.ts b/src/plugins/visualizations/public/convert_to_lens/schemas.ts index ecfbbf34ad9c9..3a225e540faae 100644 --- a/src/plugins/visualizations/public/convert_to_lens/schemas.ts +++ b/src/plugins/visualizations/public/convert_to_lens/schemas.ts @@ -7,16 +7,17 @@ */ import type { DataView } from '@kbn/data-views-plugin/common'; -import { METRIC_TYPES, TimefilterContract } from '@kbn/data-plugin/public'; +import { IAggConfig, METRIC_TYPES, TimefilterContract } from '@kbn/data-plugin/public'; import { AggBasedColumn, PercentageModeConfig, SchemaConfig } from '../../common'; import { convertMetricToColumns } from '../../common/convert_to_lens/lib/metrics'; -import { convertBucketToColumns } from '../../common/convert_to_lens/lib/buckets'; import { getCustomBucketsFromSiblingAggs } from '../../common/convert_to_lens/lib/utils'; +import { BucketColumn } from '../../common/convert_to_lens/lib'; import type { Vis } from '../types'; import { getVisSchemas, Schemas } from '../vis_schemas'; import { getBucketCollapseFn, getBucketColumns, + getCustomBucketColumns, getColumnIds, getColumnsWithoutReferenced, getMetricsWithoutDuplicates, @@ -31,66 +32,44 @@ const areVisSchemasValid = (visSchemas: Schemas, unsupported: Array( - vis: Vis, - timefilter: TimefilterContract, +const createLayer = ( + visSchemas: Schemas, + allMetrics: Array>, + metricsForLayer: Array>, + customBucketsWithMetricIds: Array<{ + customBucket: IAggConfig; + metricIds: string[]; + }>, dataView: DataView, { splits = [], buckets = [], - unsupported = [], }: { splits?: Array; buckets?: Array; - unsupported?: Array; } = {}, - config?: { - dropEmptyRowsInDateHistogram?: boolean; - } & (PercentageModeConfig | void) + percentageModeConfig: PercentageModeConfig, + dropEmptyRowsInDateHistogram?: boolean ) => { - const { dropEmptyRowsInDateHistogram, ...percentageModeConfig } = config ?? { - isPercentageMode: false, - }; - const visSchemas = getVisSchemas(vis, { - timefilter, - timeRange: timefilter.getAbsoluteTime(), - }); - - if (!isValidVis(visSchemas) || !areVisSchemasValid(visSchemas, unsupported)) { - return null; - } - - const customBuckets = getCustomBucketsFromSiblingAggs(visSchemas.metric); - - // doesn't support sibbling pipeline aggs with different bucket aggs - if (customBuckets.length > 1) { + const metricColumns = metricsForLayer.flatMap((m) => + convertMetricToColumns(m, dataView, allMetrics, percentageModeConfig) + ); + if (metricColumns.includes(null)) { return null; } + const metricColumnsWithoutNull = metricColumns as AggBasedColumn[]; - const metricsWithoutDuplicates = getMetricsWithoutDuplicates(visSchemas.metric); - const aggs = metricsWithoutDuplicates as Array>; - - const metricColumns = aggs.flatMap((m) => - convertMetricToColumns(m, dataView, aggs, percentageModeConfig) + const { customBucketColumns, customBucketsMap } = getCustomBucketColumns( + customBucketsWithMetricIds, + metricColumnsWithoutNull, + dataView, + allMetrics, + dropEmptyRowsInDateHistogram ); - if (metricColumns.includes(null)) { + if (customBucketColumns.includes(null)) { return null; } - const metrics = metricColumns as AggBasedColumn[]; - const customBucketColumns = []; - - if (customBuckets.length) { - const customBucketColumn = convertBucketToColumns( - { agg: customBuckets[0], dataView, metricColumns: metrics, aggs }, - false, - dropEmptyRowsInDateHistogram - ); - if (!customBucketColumn) { - return null; - } - customBucketColumns.push(customBucketColumn); - } const bucketColumns = getBucketColumns( visSchemas, @@ -117,19 +96,121 @@ export const getColumnsFromVis = ( } const columns = sortColumns( - [...metrics, ...bucketColumns, ...splitBucketColumns, ...customBucketColumns], + [ + ...metricColumnsWithoutNull, + ...bucketColumns, + ...splitBucketColumns, + ...(customBucketColumns as BucketColumn[]), + ], visSchemas, [...buckets, ...splits], - metricsWithoutDuplicates + metricsForLayer ); const columnsWithoutReferenced = getColumnsWithoutReferenced(columns); return { metrics: getColumnIds(columnsWithoutReferenced.filter((с) => !с.isBucketed)), - buckets: getColumnIds(columnsWithoutReferenced.filter((c) => c.isBucketed)), - bucketCollapseFn: getBucketCollapseFn(visSchemas.metric, customBucketColumns), + buckets: { + all: getColumnIds(columnsWithoutReferenced.filter((c) => c.isBucketed)), + customBuckets: customBucketsMap, + }, + bucketCollapseFn: getBucketCollapseFn( + visSchemas.metric, + customBucketColumns as BucketColumn[], + customBucketsMap, + metricColumnsWithoutNull + ), columnsWithoutReferenced, columns, }; }; + +export const getColumnsFromVis = ( + vis: Vis, + timefilter: TimefilterContract, + dataView: DataView, + { + splits = [], + buckets = [], + unsupported = [], + }: { + splits?: Array; + buckets?: Array; + unsupported?: Array; + } = {}, + config?: { + dropEmptyRowsInDateHistogram?: boolean; + supportMixedSiblingPipelineAggs?: boolean; + } & (PercentageModeConfig | void), + series?: Array<{ metrics: string[] }> +) => { + const { dropEmptyRowsInDateHistogram, supportMixedSiblingPipelineAggs, ...percentageModeConfig } = + config ?? { + isPercentageMode: false, + }; + const visSchemas = getVisSchemas(vis, { + timefilter, + timeRange: timefilter.getAbsoluteTime(), + }); + + if ( + !isValidVis(visSchemas, supportMixedSiblingPipelineAggs) || + !areVisSchemasValid(visSchemas, unsupported) + ) { + return null; + } + + const customBucketsWithMetricIds = getCustomBucketsFromSiblingAggs(visSchemas.metric); + + // doesn't support sibbling pipeline aggs with different bucket aggs + if (!supportMixedSiblingPipelineAggs && customBucketsWithMetricIds.length > 1) { + return null; + } + + const metricsWithoutDuplicates = getMetricsWithoutDuplicates(visSchemas.metric); + const aggs = metricsWithoutDuplicates as Array>; + const layers = []; + + if (series && series.length) { + for (const { metrics: metricAggIds } of series) { + const metrics = aggs.filter( + (agg) => agg.aggId && metricAggIds.includes(agg.aggId.split('.')[0]) + ); + const customBucketsForLayer = customBucketsWithMetricIds.filter((c) => + c.metricIds.some((m) => metricAggIds.includes(m)) + ); + const layer = createLayer( + visSchemas, + aggs, + metrics, + customBucketsForLayer, + dataView, + { splits, buckets }, + percentageModeConfig, + dropEmptyRowsInDateHistogram + ); + if (!layer) { + return null; + } + layers.push(layer); + } + } else { + const layer = createLayer( + visSchemas, + aggs, + aggs, + customBucketsWithMetricIds, + dataView, + { splits, buckets }, + percentageModeConfig, + dropEmptyRowsInDateHistogram + ); + if (!layer) { + return null; + } + layers.push(layer); + } + + return layers; +}; diff --git a/src/plugins/visualizations/public/convert_to_lens/utils.test.ts b/src/plugins/visualizations/public/convert_to_lens/utils.test.ts index 734a250a2972c..50f667430a8cb 100644 --- a/src/plugins/visualizations/public/convert_to_lens/utils.test.ts +++ b/src/plugins/visualizations/public/convert_to_lens/utils.test.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { BUCKET_TYPES, METRIC_TYPES } from '@kbn/data-plugin/common'; +import { BUCKET_TYPES, IAggConfig, METRIC_TYPES } from '@kbn/data-plugin/common'; import { stubLogstashDataView } from '@kbn/data-views-plugin/common/data_view.stub'; import { AggBasedColumn, @@ -27,6 +27,7 @@ import { getBucketColumns, getColumnIds, getColumnsWithoutReferenced, + getCustomBucketColumns, getMetricsWithoutDuplicates, isReferenced, isValidVis, @@ -104,6 +105,7 @@ describe('getColumnsWithoutReferenced', () => { describe('getBucketCollapseFn', () => { const metric1: SchemaConfig = { accessor: 0, + aggId: '1', label: '', format: { id: undefined, @@ -115,21 +117,25 @@ describe('getBucketCollapseFn', () => { const metric2: SchemaConfig = { ...metric1, + aggId: '2', aggType: METRIC_TYPES.AVG_BUCKET, }; const metric3: SchemaConfig = { ...metric1, + aggId: '3', aggType: METRIC_TYPES.MAX_BUCKET, }; const metric4: SchemaConfig = { ...metric1, + aggId: '4', aggType: METRIC_TYPES.MIN_BUCKET, }; const metric5: SchemaConfig = { ...metric1, + aggId: '5', aggType: METRIC_TYPES.SUM_BUCKET, }; @@ -151,18 +157,54 @@ describe('getBucketCollapseFn', () => { test.each< [ string, - [Array>, AggBasedColumn[]], - Record + [ + Array>, + AggBasedColumn[], + Record, + AggBasedColumn[] + ], + Record ] >([ - ['avg', [[metric1, metric2], [customBucketColum]], { [customBucketColum.columnId]: 'avg' }], - ['max', [[metric1, metric3], [customBucketColum]], { [customBucketColum.columnId]: 'max' }], - ['min', [[metric1, metric4], [customBucketColum]], { [customBucketColum.columnId]: 'min' }], - ['sum', [[metric1, metric5], [customBucketColum]], { [customBucketColum.columnId]: 'sum' }], [ - 'undefined if no sibling pipeline agg is provided', - [[metric1], [customBucketColum]], - { [customBucketColum.columnId]: undefined }, + 'avg', + [ + [metric1, metric2], + [customBucketColum], + { test: 'bucket-1' }, + [{ columnId: 'test', meta: { aggId: metric2.aggId } } as AggBasedColumn], + ], + { sum: [], min: [], max: [], avg: [customBucketColum.columnId] }, + ], + [ + 'max', + [ + [metric1, metric3], + [customBucketColum], + { test: 'bucket-1' }, + [{ columnId: 'test', meta: { aggId: metric3.aggId } } as AggBasedColumn], + ], + { sum: [], min: [], max: [customBucketColum.columnId], avg: [] }, + ], + [ + 'min', + [ + [metric1, metric4], + [customBucketColum], + { test: 'bucket-1' }, + [{ columnId: 'test', meta: { aggId: metric4.aggId } } as AggBasedColumn], + ], + { sum: [], min: [customBucketColum.columnId], max: [], avg: [] }, + ], + [ + 'sum', + [ + [metric1, metric5], + [customBucketColum], + { test: 'bucket-1' }, + [{ columnId: 'test', meta: { aggId: metric5.aggId } } as AggBasedColumn], + ], + { sum: [customBucketColum.columnId], min: [], max: [], avg: [] }, ], ])('should return%s', (_, input, expected) => { expect(getBucketCollapseFn(...input)).toEqual(expected); @@ -607,4 +649,77 @@ describe('getColumnIds', () => { colId4, ]); }); + + describe('getCustomBucketColumns', () => { + const dataView = stubLogstashDataView; + const baseMetric = { + accessor: 0, + label: '', + format: { + id: undefined, + params: undefined, + }, + params: {}, + }; + const metric1: SchemaConfig = { + ...baseMetric, + accessor: 2, + aggType: METRIC_TYPES.COUNT, + aggId: '3', + }; + const metric2: SchemaConfig = { + ...baseMetric, + accessor: 3, + aggType: METRIC_TYPES.MAX, + aggId: '4', + }; + const customBucketsWithMetricIds = [ + { + customBucket: {} as IAggConfig, + metricIds: ['3', '4'], + }, + { + customBucket: {} as IAggConfig, + metricIds: ['5'], + }, + ]; + test('return custom buckets columns and map', () => { + mockConvertBucketToColumns.mockReturnValueOnce({ + columnId: 'col-1', + operationType: 'date_histogram', + }); + mockConvertBucketToColumns.mockReturnValueOnce({ + columnId: 'col-2', + operationType: 'terms', + }); + expect( + getCustomBucketColumns( + customBucketsWithMetricIds, + [ + { columnId: 'col-3', meta: { aggId: '3' } }, + { columnId: 'col-4', meta: { aggId: '4' } }, + { columnId: 'col-5', meta: { aggId: '5' } }, + ] as AggBasedColumn[], + dataView, + [metric1, metric2] + ) + ).toEqual({ + customBucketColumns: [ + { + columnId: 'col-1', + operationType: 'date_histogram', + }, + { + columnId: 'col-2', + operationType: 'terms', + }, + ], + customBucketsMap: { + 'col-3': 'col-1', + 'col-4': 'col-1', + 'col-5': 'col-2', + }, + }); + }); + }); }); diff --git a/src/plugins/visualizations/public/convert_to_lens/utils.ts b/src/plugins/visualizations/public/convert_to_lens/utils.ts index a5337568b5568..0cab4f698fb2f 100644 --- a/src/plugins/visualizations/public/convert_to_lens/utils.ts +++ b/src/plugins/visualizations/public/convert_to_lens/utils.ts @@ -7,10 +7,11 @@ */ import type { DataView } from '@kbn/data-views-plugin/common'; -import { METRIC_TYPES } from '@kbn/data-plugin/public'; +import { IAggConfig, METRIC_TYPES } from '@kbn/data-plugin/public'; import { AggBasedColumn, SchemaConfig, SupportedAggregation } from '../../common'; import { convertBucketToColumns } from '../../common/convert_to_lens/lib/buckets'; import { isSiblingPipeline } from '../../common/convert_to_lens/lib/utils'; +import { BucketColumn } from '../../common/convert_to_lens/lib'; import { Schemas } from '../vis_schemas'; export const isReferenced = (columnId: string, references: string[]) => @@ -25,14 +26,31 @@ export const getColumnsWithoutReferenced = (columns: AggBasedColumn[]) => { export const getBucketCollapseFn = ( metrics: Array>, - customBucketColumns: AggBasedColumn[] + customBucketColumns: AggBasedColumn[], + customBucketsMap: Record, + metricColumns: AggBasedColumn[] ) => { - const collapseFn = metrics.find((m) => isSiblingPipeline(m))?.aggType.split('_')[0]; - return customBucketColumns.length - ? { - [customBucketColumns[0].columnId]: collapseFn, + const collapseFnMap: Record = { + min: [], + max: [], + sum: [], + avg: [], + }; + customBucketColumns.forEach((bucket) => { + const metricColumnsIds = Object.keys(customBucketsMap).filter( + (key) => customBucketsMap[key] === bucket.columnId + ); + metricColumnsIds.forEach((metricColumnsId) => { + const metricColumn = metricColumns.find((c) => c.columnId === metricColumnsId)!; + const collapseFn = metrics + .find((m) => m.aggId === metricColumn.meta.aggId) + ?.aggType.split('_')[0]; + if (collapseFn) { + collapseFnMap[collapseFn].push(bucket.columnId); } - : {}; + }); + }); + return collapseFnMap; }; export const getBucketColumns = ( @@ -67,7 +85,7 @@ export const getBucketColumns = ( return columns; }; -export const isValidVis = (visSchemas: Schemas) => { +export const isValidVis = (visSchemas: Schemas, supportMixedSiblingPipelineAggs?: boolean) => { const { metric } = visSchemas; const siblingPipelineAggs = metric.filter((m) => isSiblingPipeline(m)); @@ -76,7 +94,10 @@ export const isValidVis = (visSchemas: Schemas) => { } // doesn't support mixed sibling pipeline aggregations - if (siblingPipelineAggs.some((agg) => agg.aggType !== siblingPipelineAggs[0].aggType)) { + if ( + siblingPipelineAggs.some((agg) => agg.aggType !== siblingPipelineAggs[0].aggType) && + !supportMixedSiblingPipelineAggs + ) { return false; } @@ -103,7 +124,8 @@ export const sortColumns = ( ...acc, ...(key === 'metric' ? metricsWithoutDuplicates : visSchemas[key])?.reduce( (newAcc, schema) => { - newAcc[schema.aggId] = schema.accessor; + // metrics should always have sort more than buckets + newAcc[schema.aggId] = key === 'metric' ? schema.accessor : 1000 + schema.accessor; return newAcc; }, {} @@ -121,3 +143,36 @@ export const sortColumns = ( }; export const getColumnIds = (columns: AggBasedColumn[]) => columns.map(({ columnId }) => columnId); + +export const getCustomBucketColumns = ( + customBucketsWithMetricIds: Array<{ + customBucket: IAggConfig; + metricIds: string[]; + }>, + metricColumns: AggBasedColumn[], + dataView: DataView, + aggs: Array>, + dropEmptyRowsInDateHistogram?: boolean +) => { + const customBucketColumns: Array = []; + const customBucketsMap: Record = {}; + customBucketsWithMetricIds.forEach((customBucketWithMetricIds) => { + const customBucketColumn = convertBucketToColumns( + { agg: customBucketWithMetricIds.customBucket, dataView, metricColumns, aggs }, + true, + dropEmptyRowsInDateHistogram + ); + customBucketColumns.push(customBucketColumn); + if (customBucketColumn) { + customBucketWithMetricIds.metricIds.forEach((metricAggId) => { + const metricColumnId = metricColumns.find( + (metricColumn) => metricColumn?.meta.aggId === metricAggId + )?.columnId; + if (metricColumnId) { + customBucketsMap[metricColumnId] = customBucketColumn.columnId; + } + }); + } + }); + return { customBucketColumns, customBucketsMap }; +}; diff --git a/test/functional/apps/console/_console.ts b/test/functional/apps/console/_console.ts index 6736dc5a2f721..d7a591efca014 100644 --- a/test/functional/apps/console/_console.ts +++ b/test/functional/apps/console/_console.ts @@ -27,7 +27,6 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const log = getService('log'); const browser = getService('browser'); const PageObjects = getPageObjects(['common', 'console', 'header']); - const toasts = getService('toasts'); const security = getService('security'); const testSubjects = getService('testSubjects'); @@ -72,32 +71,6 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { expect(initialSize.width).to.be.greaterThan(afterSize.width); }); - describe('with a data URI in the load_from query', () => { - it('loads the data from the URI', async () => { - await PageObjects.common.navigateToApp('console', { - hash: '#/console?load_from=data:text/plain,BYUwNmD2Q', - }); - - await retry.try(async () => { - const actualRequest = await PageObjects.console.getRequest(); - log.debug(actualRequest); - expect(actualRequest.trim()).to.eql('hello'); - }); - }); - - describe('with invalid data', () => { - it('shows a toast error', async () => { - await PageObjects.common.navigateToApp('console', { - hash: '#/console?load_from=data:text/plain,BYUwNmD2', - }); - - await retry.try(async () => { - expect(await toasts.getToastCount()).to.equal(1); - }); - }); - }); - }); - describe('with kbn: prefix in request', () => { before(async () => { await PageObjects.console.clearTextArea(); diff --git a/test/functional/apps/console/_text_input.ts b/test/functional/apps/console/_text_input.ts new file mode 100644 index 0000000000000..29290fac6728f --- /dev/null +++ b/test/functional/apps/console/_text_input.ts @@ -0,0 +1,100 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 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 expect from '@kbn/expect'; +import { FtrProviderContext } from '../../ftr_provider_context'; + +export default function ({ getService, getPageObjects }: FtrProviderContext) { + const retry = getService('retry'); + const toasts = getService('toasts'); + const PageObjects = getPageObjects(['common', 'console', 'header']); + + describe('text input', function testTextInput() { + before(async () => { + await PageObjects.common.navigateToApp('console'); + await PageObjects.console.collapseHelp(); + }); + + beforeEach(async () => { + await PageObjects.console.clearTextArea(); + }); + + describe('with a data URI in the load_from query', () => { + it('loads the data from the URI', async () => { + await PageObjects.common.navigateToApp('console', { + hash: '#/console?load_from=data:text/plain,BYUwNmD2Q', + }); + + await retry.try(async () => { + const actualRequest = await PageObjects.console.getRequest(); + expect(actualRequest.trim()).to.eql('hello'); + }); + }); + + describe('with invalid data', () => { + it('shows a toast error', async () => { + await PageObjects.common.navigateToApp('console', { + hash: '#/console?load_from=data:text/plain,BYUwNmD2', + }); + + await retry.try(async () => { + expect(await toasts.getToastCount()).to.equal(1); + }); + }); + }); + }); + + describe('copy/pasting cURL commands into the console', () => { + it('should convert cURL commands into the console request format', async () => { + await PageObjects.console.enterRequest( + `\n curl -XGET "http://localhost:9200/_search?pretty" -d'\n{"query": {"match_all": {}}}'` + ); + await PageObjects.console.copyRequestsToClipboard(); + await PageObjects.console.clearTextArea(); + await PageObjects.console.pasteClipboardValue(); + await retry.try(async () => { + const actualRequest = await PageObjects.console.getRequest(); + expect(actualRequest.trim()).to.eql('GET /_search?pretty\n {"query": {"match_all": {}}}'); + }); + }); + }); + + describe('console history', () => { + const sendRequest = async (request: string) => { + await PageObjects.console.enterRequest(request); + await PageObjects.console.clickPlay(); + await PageObjects.header.waitUntilLoadingHasFinished(); + }; + + it('should show the history', async () => { + await sendRequest('GET /_search?pretty'); + await PageObjects.console.clickHistory(); + await retry.try(async () => { + const history = await PageObjects.console.getHistoryEntries(); + expect(history).to.eql(['/_search?pretty (a few seconds ago)']); + }); + + // Clear the history + await PageObjects.console.clickClearHistory(); + await PageObjects.console.closeHistory(); + }); + + it('should load a request from history', async () => { + await sendRequest('GET _search\n{"query": {"match_all": {}}}'); + await PageObjects.console.clearTextArea(); + await PageObjects.console.clickHistory(); + await PageObjects.console.loadRequestFromHistory(0); + await retry.try(async () => { + const actualRequest = await PageObjects.console.getRequest(); + expect(actualRequest.trim()).to.eql( + 'GET _search\n{\n "query": {\n "match_all": {}\n }\n}' + ); + }); + }); + }); + }); +} diff --git a/test/functional/apps/console/index.js b/test/functional/apps/console/index.js index 06c29f0e031ec..a2a1206fe85bd 100644 --- a/test/functional/apps/console/index.js +++ b/test/functional/apps/console/index.js @@ -25,6 +25,7 @@ export default function ({ getService, loadTestFile }) { loadTestFile(require.resolve('./_xjson')); loadTestFile(require.resolve('./_misc_console_behavior')); loadTestFile(require.resolve('./_context_menu')); + loadTestFile(require.resolve('./_text_input')); } }); } diff --git a/test/functional/apps/discover/group1/_discover.ts b/test/functional/apps/discover/group1/_discover.ts index 9ac159fa39168..1ac0ad6fe013f 100644 --- a/test/functional/apps/discover/group1/_discover.ts +++ b/test/functional/apps/discover/group1/_discover.ts @@ -364,20 +364,16 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); describe('URL state', () => { - const getCurrentDataViewId = (currentUrl: string) => { - const [indexSubstring] = currentUrl.match(/index:[^,]*/)!; - const dataViewId = indexSubstring.replace('index:', ''); - return dataViewId; - }; - it('should show a warning and fall back to the default data view when navigating to a URL with an invalid data view ID', async () => { await PageObjects.common.navigateToApp('discover'); await PageObjects.timePicker.setDefaultAbsoluteRange(); await PageObjects.header.waitUntilLoadingHasFinished(); + const dataViewId = await PageObjects.discover.getCurrentDataViewId(); + const originalUrl = await browser.getCurrentUrl(); - const dataViewId = getCurrentDataViewId(originalUrl); const newUrl = originalUrl.replace(dataViewId, 'invalid-data-view-id'); await browser.get(newUrl); + await PageObjects.header.waitUntilLoadingHasFinished(); expect(await browser.getCurrentUrl()).to.be(originalUrl); expect(await testSubjects.exists('dscDataViewNotFoundShowDefaultWarning')).to.be(true); @@ -387,10 +383,12 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await PageObjects.common.navigateToApp('discover'); await PageObjects.timePicker.setDefaultAbsoluteRange(); const originalHash = await browser.execute<[], string>('return window.location.hash'); - const dataViewId = getCurrentDataViewId(originalHash); + const dataViewId = await PageObjects.discover.getCurrentDataViewId(); + const newHash = originalHash.replace(dataViewId, 'invalid-data-view-id'); await browser.execute(`window.location.hash = "${newHash}"`); await PageObjects.header.waitUntilLoadingHasFinished(); + const currentHash = await browser.execute<[], string>('return window.location.hash'); expect(currentHash).to.be(originalHash); expect(await testSubjects.exists('dscDataViewNotFoundShowSavedWarning')).to.be(true); diff --git a/test/functional/apps/discover/group2/_adhoc_data_views.ts b/test/functional/apps/discover/group2/_adhoc_data_views.ts index c7f17472250fd..9a1f4dd84d300 100644 --- a/test/functional/apps/discover/group2/_adhoc_data_views.ts +++ b/test/functional/apps/discover/group2/_adhoc_data_views.ts @@ -11,15 +11,16 @@ import { FtrProviderContext } from '../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const dataGrid = getService('dataGrid'); + const toasts = getService('toasts'); const esArchiver = getService('esArchiver'); const filterBar = getService('filterBar'); const dashboardAddPanel = getService('dashboardAddPanel'); const fieldEditor = getService('fieldEditor'); const kibanaServer = getService('kibanaServer'); - const browser = getService('browser'); const retry = getService('retry'); const queryBar = getService('queryBar'); const testSubjects = getService('testSubjects'); + const browser = getService('browser'); const PageObjects = getPageObjects([ 'common', 'unifiedSearch', @@ -33,22 +34,6 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const find = getService('find'); const security = getService('security'); - const getCurrentDataViewId = async () => { - const currentUrl = await browser.getCurrentUrl(); - const [indexSubstring] = currentUrl.match(/index:[^,]*/)!; - const dataViewId = indexSubstring.replace('index:', ''); - return dataViewId; - }; - - const addRuntimeField = async (name: string, script: string) => { - await PageObjects.discover.clickAddField(); - await fieldEditor.setName(name); - await fieldEditor.enableValue(); - await fieldEditor.typeScript(script); - await fieldEditor.save(); - await PageObjects.header.waitUntilLoadingHasFinished(); - }; - const addSearchToDashboard = async (name: string) => { await dashboardAddPanel.addSavedSearch(name); await PageObjects.header.waitUntilLoadingHasFinished(); @@ -113,35 +98,35 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); it('should not update data view id when saving search first time', async () => { - const prevDataViewId = await getCurrentDataViewId(); + const prevDataViewId = await PageObjects.discover.getCurrentDataViewId(); await PageObjects.discover.saveSearch('logstash*-ss'); await PageObjects.header.waitUntilLoadingHasFinished(); - const newDataViewId = await getCurrentDataViewId(); + const newDataViewId = await PageObjects.discover.getCurrentDataViewId(); expect(prevDataViewId).to.equal(newDataViewId); }); it('should update data view id when saving new search copy', async () => { - const prevDataViewId = await getCurrentDataViewId(); + const prevDataViewId = await PageObjects.discover.getCurrentDataViewId(); await PageObjects.discover.saveSearch('logstash*-ss-new', true); await PageObjects.header.waitUntilLoadingHasFinished(); - const newDataViewId = await getCurrentDataViewId(); + const newDataViewId = await PageObjects.discover.getCurrentDataViewId(); expect(prevDataViewId).not.to.equal(newDataViewId); }); it('should update data view id when saving data view from hoc one', async () => { - const prevDataViewId = await getCurrentDataViewId(); + const prevDataViewId = await PageObjects.discover.getCurrentDataViewId(); await testSubjects.click('discoverAlertsButton'); await testSubjects.click('confirmModalConfirmButton'); await PageObjects.header.waitUntilLoadingHasFinished(); - const newDataViewId = await getCurrentDataViewId(); + const newDataViewId = await PageObjects.discover.getCurrentDataViewId(); expect(prevDataViewId).not.to.equal(newDataViewId); }); @@ -149,9 +134,16 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { it('search results should be different after data view update', async () => { await PageObjects.discover.createAdHocDataView('logst', true); await PageObjects.header.waitUntilLoadingHasFinished(); + const prevDataViewId = await PageObjects.discover.getCurrentDataViewId(); - await addRuntimeField('_bytes-runtimefield', `emit(doc["bytes"].value.toString())`); + // trigger data view id update + await PageObjects.discover.addRuntimeField( + '_bytes-runtimefield', + `emit(doc["bytes"].value.toString())` + ); await PageObjects.discover.clickFieldListItemToggle('_bytes-runtimefield'); + const newDataViewId = await PageObjects.discover.getCurrentDataViewId(); + expect(newDataViewId).not.to.equal(prevDataViewId); // save first search await PageObjects.discover.saveSearch('logst*-ss-_bytes-runtimefield'); @@ -162,7 +154,11 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await PageObjects.discover.removeField('_bytes-runtimefield'); await PageObjects.header.waitUntilLoadingHasFinished(); - await addRuntimeField('_bytes-runtimefield', `emit((doc["bytes"].value * 2).toString())`); + // trigger data view id update + await PageObjects.discover.addRuntimeField( + '_bytes-runtimefield', + `emit((doc["bytes"].value * 2).toString())` + ); await PageObjects.discover.clickFieldListItemToggle('_bytes-runtimefield'); // save second search @@ -185,5 +181,61 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { expect(+second).to.equal(+first * 2); }); + + it('should update id after data view field edit', async () => { + await PageObjects.common.navigateToApp('discover'); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.discover.loadSavedSearch('logst*-ss-_bytes-runtimefield'); + await PageObjects.header.waitUntilLoadingHasFinished(); + + const prevDataViewId = await PageObjects.discover.getCurrentDataViewId(); + + // trigger data view id update + await dataGrid.clickEditField('_bytes-runtimefield'); + await fieldEditor.setName('_bytes-runtimefield-edited', true); + await fieldEditor.save(); + await fieldEditor.confirmSave(); + await PageObjects.header.waitUntilLoadingHasFinished(); + + const newDataViewId = await PageObjects.discover.getCurrentDataViewId(); + expect(prevDataViewId).not.to.equal(newDataViewId); + }); + + it('should notify about invalid filter reffs', async () => { + await PageObjects.discover.createAdHocDataView('logstas', true); + await PageObjects.header.waitUntilLoadingHasFinished(); + + await filterBar.addFilter('nestedField.child', 'is', 'nestedValue'); + await PageObjects.header.waitUntilLoadingHasFinished(); + + await filterBar.addFilter('extension', 'is', 'jpg'); + await PageObjects.header.waitUntilLoadingHasFinished(); + + const first = await PageObjects.discover.getCurrentDataViewId(); + // trigger data view id update + await PageObjects.discover.addRuntimeField( + '_bytes-runtimefield', + `emit((doc["bytes"].value * 2).toString())` + ); + await PageObjects.header.waitUntilLoadingHasFinished(); + + const second = await PageObjects.discover.getCurrentDataViewId(); + expect(first).not.equal(second); + + await toasts.dismissAllToasts(); + + await browser.goBack(); + await PageObjects.header.waitUntilLoadingHasFinished(); + + const firstToast = await toasts.getToastContent(1); + expect(firstToast).to.equal( + `"${first}" is not a configured data view ID\nShowing the saved data view: "logstas*" (${second})` + ); + + const secondToast = await toasts.getToastContent(2); + expect(secondToast).to.equal( + `Different index references\nData view id references in some of the applied filters differ from the current data view.` + ); + }); }); } diff --git a/test/functional/apps/visualize/group2/index.ts b/test/functional/apps/visualize/group2/index.ts index 4925c3ef73598..5a83044deee17 100644 --- a/test/functional/apps/visualize/group2/index.ts +++ b/test/functional/apps/visualize/group2/index.ts @@ -19,11 +19,22 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) { log.debug('Starting visualize before method'); await browser.setWindowSize(1280, 800); await kibanaServer.savedObjects.cleanStandardList(); + await kibanaServer.uiSettings.update({ + 'histogram:maxBars': 100, + }); + await browser.refresh(); await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/logstash_functional'); await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/long_window_logstash'); }); + after(async () => { + await kibanaServer.uiSettings.update({ + 'histogram:maxBars': 1000, + }); + await browser.refresh(); + }); + loadTestFile(require.resolve('./_inspector')); loadTestFile(require.resolve('./_experimental_vis')); loadTestFile(require.resolve('./_gauge_chart')); diff --git a/test/functional/apps/visualize/replaced_vislib_chart_types/index.ts b/test/functional/apps/visualize/replaced_vislib_chart_types/index.ts index 8ee970693b7a9..d8e35e8f12bfc 100644 --- a/test/functional/apps/visualize/replaced_vislib_chart_types/index.ts +++ b/test/functional/apps/visualize/replaced_vislib_chart_types/index.ts @@ -28,6 +28,7 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) { before(async () => { await kibanaServer.uiSettings.update({ 'visualization:visualize:legacyHeatmapChartsLibrary': false, + 'histogram:maxBars': 100, }); await browser.refresh(); }); @@ -35,6 +36,7 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) { after(async () => { await kibanaServer.uiSettings.update({ 'visualization:visualize:legacyHeatmapChartsLibrary': true, + 'histogram:maxBars': 1000, }); await browser.refresh(); }); diff --git a/test/functional/page_objects/common_page.ts b/test/functional/page_objects/common_page.ts index a92cd19405378..d40e19e2526a9 100644 --- a/test/functional/page_objects/common_page.ts +++ b/test/functional/page_objects/common_page.ts @@ -467,7 +467,7 @@ export class CommonPageObject extends FtrService { async waitForSaveModalToClose() { this.log.debug('Waiting for save modal to close'); await this.retry.try(async () => { - if (await this.testSubjects.exists('savedObjectSaveModal')) { + if (await this.testSubjects.exists('savedObjectSaveModal', { timeout: 5000 })) { throw new Error('save modal still open'); } }); diff --git a/test/functional/page_objects/console_page.ts b/test/functional/page_objects/console_page.ts index 0069682f828d6..a368d085160f4 100644 --- a/test/functional/page_objects/console_page.ts +++ b/test/functional/page_objects/console_page.ts @@ -505,4 +505,46 @@ export class ConsolePageObject extends FtrService { const body = await this.getRequestBody(); return body.split('\n').length; } + + public async copyRequestsToClipboard() { + const textArea = await this.testSubjects.find('console-textarea'); + await textArea.pressKeys([Key[process.platform === 'darwin' ? 'COMMAND' : 'CONTROL'], 'a']); + await textArea.pressKeys([Key[process.platform === 'darwin' ? 'COMMAND' : 'CONTROL'], 'c']); + } + + public async pasteClipboardValue() { + const textArea = await this.testSubjects.find('console-textarea'); + await textArea.pressKeys([Key[process.platform === 'darwin' ? 'COMMAND' : 'CONTROL'], 'v']); + } + + public async clickHistory() { + const historyButton = await this.testSubjects.find('consoleHistoryButton'); + await historyButton.click(); + } + + public async getHistoryEntries() { + const history = await this.find.allByCssSelector('.list-group-item'); + return await Promise.all(history.map(async (item) => await item.getVisibleText())); + } + + public async loadRequestFromHistory(index: number) { + const historyItem = await this.find.byCssSelector(`#historyReq${index}`); + await historyItem.click(); + await this.testSubjects.click('consoleHistoryApplyButton'); + } + + public async clickClearHistory() { + const clearHistoryButton = await this.testSubjects.find('consoleClearHistoryButton'); + await clearHistoryButton.click(); + + await this.retry.waitFor('history to be cleared', async () => { + const history = await this.getHistoryEntries(); + return history.length === 0; + }); + } + + public async closeHistory() { + const closeButton = await this.testSubjects.find('consoleHistoryCloseButton'); + await closeButton.click(); + } } diff --git a/test/functional/page_objects/discover_page.ts b/test/functional/page_objects/discover_page.ts index cc398f8d67be6..d9bc8c46a4acc 100644 --- a/test/functional/page_objects/discover_page.ts +++ b/test/functional/page_objects/discover_page.ts @@ -683,4 +683,36 @@ export class DiscoverPageObject extends FtrService { const button = await this.testSubjects.find('discover-dataView-switch-link'); return button.getAttribute('title'); } + + public async getCurrentDataViewId() { + const currentUrl = await this.browser.getCurrentUrl(); + const matches = currentUrl.matchAll(/index:[^,]*/g); + const indexes = []; + for (const matchEntry of matches) { + const [index] = matchEntry; + indexes.push(decodeURIComponent(index).replace('index:', '').replaceAll("'", '')); + } + + const first = indexes[0]; + if (first) { + const allEqual = indexes.every((val) => val === first); + if (allEqual) { + return first; + } else { + throw new Error( + 'Discover URL state contains different index references. They should be all the same.' + ); + } + } + throw new Error("Discover URL state doesn't contain an index reference."); + } + + public async addRuntimeField(name: string, script: string) { + await this.clickAddField(); + await this.fieldEditor.setName(name); + await this.fieldEditor.enableValue(); + await this.fieldEditor.typeScript(script); + await this.fieldEditor.save(); + await this.header.waitUntilLoadingHasFinished(); + } } diff --git a/test/functional/page_objects/visual_builder_page.ts b/test/functional/page_objects/visual_builder_page.ts index dc12e8ae8fa59..edbd53e80d8c5 100644 --- a/test/functional/page_objects/visual_builder_page.ts +++ b/test/functional/page_objects/visual_builder_page.ts @@ -406,6 +406,27 @@ export class VisualBuilderPageObject extends FtrService { }); } + public async createNewAggSeries(nth = 0) { + const prevAggs = await this.testSubjects.findAll('draggable'); + const elements = await this.testSubjects.findAll('AddAddBtn'); + await elements[nth].click(); + await this.visChart.waitForVisualizationRenderingStabilized(); + await this.retry.waitFor('new agg series is added', async () => { + const currentAggs = await this.testSubjects.findAll('draggable'); + return currentAggs.length > prevAggs.length; + }); + } + + public async createColorRule(nth = 0) { + const elements = await this.testSubjects.findAll('AddAddBtn'); + await elements[nth].click(); + await this.visChart.waitForVisualizationRenderingStabilized(); + await this.retry.waitFor('new color rule is added', async () => { + const currentAddButtons = await this.testSubjects.findAll('AddAddBtn'); + return currentAddButtons.length > elements.length; + }); + } + public async selectAggType(value: string, nth = 0) { const elements = await this.testSubjects.findAll('aggSelector'); await this.comboBox.setElement(elements[nth], value); @@ -619,6 +640,11 @@ export class VisualBuilderPageObject extends FtrService { await input.type(labelName); } + public async setStaticValue(value: number, nth: number = 0): Promise { + const input = (await this.testSubjects.findAll('staticValue'))[nth]; + await input.type(value.toString()); + } + /** * set field for type of aggregation * @@ -682,16 +708,16 @@ export class VisualBuilderPageObject extends FtrService { public async setColorRuleOperator(condition: string): Promise { await this.retry.try(async () => { - await this.comboBox.clearInputField('colorRuleOperator'); - await this.comboBox.set('colorRuleOperator', condition); + await this.comboBox.clearLastInputField('colorRuleOperator'); + await this.comboBox.setForLastInput('colorRuleOperator', condition); }); } - public async setColorRuleValue(value: number): Promise { + public async setColorRuleValue(value: number, nth: number = 0): Promise { await this.retry.try(async () => { - const colorRuleValueInput = await this.find.byCssSelector( - '[data-test-subj="colorRuleValue"]' - ); + const colorRuleValueInput = ( + await this.find.allByCssSelector('[data-test-subj="colorRuleValue"]') + )[nth]; await colorRuleValueInput.type(value.toString()); }); } diff --git a/test/functional/page_objects/visualize_editor_page.ts b/test/functional/page_objects/visualize_editor_page.ts index 1700b82782580..5b22ccc27a8fa 100644 --- a/test/functional/page_objects/visualize_editor_page.ts +++ b/test/functional/page_objects/visualize_editor_page.ts @@ -147,7 +147,12 @@ export class VisualizeEditorPageObject extends FtrService { await this.testSubjects.click('visEditorAddFilterButton'); } - public async selectField(fieldValue: string, groupName = 'buckets', isChildAggregation = false) { + public async selectField( + fieldValue: string, + groupName = 'buckets', + isChildAggregation = false, + aggregationIndex = 0 + ) { this.log.debug(`selectField ${fieldValue}`); const selector = ` [data-test-subj="${groupName}AggGroup"] @@ -156,8 +161,8 @@ export class VisualizeEditorPageObject extends FtrService { ${isChildAggregation ? '.visEditorAgg__subAgg' : ''} [data-test-subj="visDefaultEditorField"] `; - const fieldEl = await this.find.byCssSelector(selector); - await this.comboBox.setElement(fieldEl, fieldValue); + const fieldEls = await this.find.allByCssSelector(selector); + await this.comboBox.setElement(fieldEls[aggregationIndex], fieldValue); } public async selectOrderByMetric(aggNth: number, metric: string) { @@ -175,16 +180,17 @@ export class VisualizeEditorPageObject extends FtrService { public async selectAggregation( aggValue: string, groupName = 'buckets', - isChildAggregation = false + isChildAggregation = false, + aggregationIndex = 0 ) { - const comboBoxElement = await this.find.byCssSelector(` + const comboBoxElements = await this.find.allByCssSelector(` [data-test-subj="${groupName}AggGroup"] [data-test-subj^="visEditorAggAccordion"].euiAccordion-isOpen ${isChildAggregation ? '.visEditorAgg__subAgg' : ''} [data-test-subj="defaultEditorAggSelect"] `); - await this.comboBox.setElement(comboBoxElement, aggValue); + await this.comboBox.setElement(comboBoxElements[aggregationIndex], aggValue); await this.common.sleep(500); } diff --git a/test/functional/page_objects/visualize_page.ts b/test/functional/page_objects/visualize_page.ts index 95adb7e64b1ec..6dd17c9c13e1c 100644 --- a/test/functional/page_objects/visualize_page.ts +++ b/test/functional/page_objects/visualize_page.ts @@ -61,6 +61,7 @@ export class VisualizePageObject extends FtrService { [FORMATS_UI_SETTINGS.FORMAT_BYTES_DEFAULT_PATTERN]: '0,0.[000]b', 'visualization:visualize:legacyPieChartsLibrary': !isNewLibrary, 'visualization:visualize:legacyHeatmapChartsLibrary': !isNewLibrary, + 'histogram:maxBars': 100, }); } @@ -147,6 +148,15 @@ export class VisualizePageObject extends FtrService { await this.waitForVisualizationSelectPage(); } + public async navigateToLensFromAnotherVisulization() { + const button = await this.testSubjects.find('visualizeEditInLensButton'); + await button.click(); + } + + public async hasNavigateToLensButton() { + return await this.testSubjects.exists('visualizeEditInLensButton'); + } + public async hasVisType(type: string) { return await this.testSubjects.exists(`visType-${type}`); } @@ -180,6 +190,10 @@ export class VisualizePageObject extends FtrService { await this.clickVisType('gauge'); } + public async clickGoal() { + await this.clickVisType('goal'); + } + public async clickPieChart() { await this.clickVisType('pie'); } diff --git a/test/functional/services/combo_box.ts b/test/functional/services/combo_box.ts index 98b04f83aa47f..96d51cd24611a 100644 --- a/test/functional/services/combo_box.ts +++ b/test/functional/services/combo_box.ts @@ -36,6 +36,13 @@ export class ComboBoxService extends FtrService { await this.setElement(comboBox, value); } + public async setForLastInput(comboBoxSelector: string, value: string): Promise { + this.log.debug(`comboBox.set, comboBoxSelector: ${comboBoxSelector}`); + const comboBoxes = await this.testSubjects.findAll(comboBoxSelector); + const comboBox = comboBoxes[comboBoxes.length - 1]; + await this.setElement(comboBox, value); + } + /** * Clicks option in combobox dropdown * @@ -308,4 +315,12 @@ export class ComboBoxService extends FtrService { const input = await comboBoxElement.findByTagName('input'); await input.clearValueWithKeyboard(); } + + public async clearLastInputField(comboBoxSelector: string): Promise { + this.log.debug(`comboBox.clearInputField, comboBoxSelector:${comboBoxSelector}`); + const comboBoxElements = await this.testSubjects.findAll(comboBoxSelector); + const comboBoxElement = comboBoxElements[comboBoxElements.length - 1]; + const input = await comboBoxElement.findByTagName('input'); + await input.clearValueWithKeyboard(); + } } diff --git a/test/functional/services/data_grid.ts b/test/functional/services/data_grid.ts index c3107188d7c56..0c3464e103eca 100644 --- a/test/functional/services/data_grid.ts +++ b/test/functional/services/data_grid.ts @@ -296,6 +296,10 @@ export class DataGridService extends FtrService { await this.openColMenuByField(field); await this.find.clickByButtonText('Copy name'); } + public async clickEditField(field: string) { + await this.openColMenuByField(field); + await this.testSubjects.click('gridEditFieldButton'); + } public async getDetailsRow(): Promise { const detailRows = await this.getDetailsRows(); diff --git a/test/functional/services/listing_table.ts b/test/functional/services/listing_table.ts index 8db68883715e2..ce210be9d222e 100644 --- a/test/functional/services/listing_table.ts +++ b/test/functional/services/listing_table.ts @@ -51,6 +51,16 @@ export class ListingTableService extends FtrService { return visualizationNames; } + private async getAllSelectableItemsNamesOnCurrentPage(): Promise { + const visualizationNames = []; + const links = await this.find.allByCssSelector('.euiTableRow-isSelectable .euiLink'); + for (let i = 0; i < links.length; i++) { + visualizationNames.push(await links[i].getVisibleText()); + } + this.log.debug(`Found ${visualizationNames.length} selectable visualizations on current page`); + return visualizationNames; + } + public async waitUntilTableIsLoaded() { return this.retry.try(async () => { const isLoaded = await this.find.existsByDisplayedByCssSelector( @@ -65,6 +75,29 @@ export class ListingTableService extends FtrService { }); } + /** + * Navigates through all pages on Landing page and returns array of items names that are selectable + * Added for visualize_integration saved object tagging tests + */ + public async getAllSelectableItemsNames(): Promise { + this.log.debug('ListingTable.getAllItemsNames'); + let morePages = true; + let visualizationNames: string[] = []; + while (morePages) { + visualizationNames = visualizationNames.concat( + await this.getAllSelectableItemsNamesOnCurrentPage() + ); + morePages = !( + (await this.testSubjects.getAttribute('pagination-button-next', 'disabled')) === 'true' + ); + if (morePages) { + await this.testSubjects.click('pagerNextButton'); + await this.header.waitUntilLoadingHasFinished(); + } + } + return visualizationNames; + } + /** * Navigates through all pages on Landing page and returns array of items names */ diff --git a/test/functional/services/toasts.ts b/test/functional/services/toasts.ts index d71d66e399785..6866c2a8b2fd2 100644 --- a/test/functional/services/toasts.ts +++ b/test/functional/services/toasts.ts @@ -67,6 +67,11 @@ export class ToastsService extends FtrService { return await list.findByCssSelector(`.euiToast:nth-child(${index})`); } + public async getToastContent(index: number) { + const toast = await this.getToastElement(index); + return await toast.getVisibleText(); + } + private async getGlobalToastList() { return await this.testSubjects.find('globalToastList'); } diff --git a/test/plugin_functional/test_suites/core_plugins/rendering.ts b/test/plugin_functional/test_suites/core_plugins/rendering.ts index a3968330e1425..2bfd0c7b5dda3 100644 --- a/test/plugin_functional/test_suites/core_plugins/rendering.ts +++ b/test/plugin_functional/test_suites/core_plugins/rendering.ts @@ -91,6 +91,9 @@ export default function ({ getService }: PluginFunctionalProviderContext) { 'unifiedSearch.autocomplete.valueSuggestions.tiers (array)', 'unifiedSearch.autocomplete.valueSuggestions.timeout (duration)', 'data.search.aggs.shardDelay.enabled (boolean)', + 'data.search.asyncSearch.batchedReduceSize (number)', + 'data.search.asyncSearch.keepAlive (duration)', + 'data.search.asyncSearch.waitForCompletion (duration)', 'data.search.sessions.defaultExpiration (duration)', 'data.search.sessions.enabled (boolean)', 'data.search.sessions.management.expiresSoonWarning (duration)', diff --git a/x-pack/examples/embedded_lens_example/public/app.tsx b/x-pack/examples/embedded_lens_example/public/app.tsx index 42784984a0d44..e4df914a54c3c 100644 --- a/x-pack/examples/embedded_lens_example/public/app.tsx +++ b/x-pack/examples/embedded_lens_example/public/app.tsx @@ -100,7 +100,7 @@ function getLensAttributes( ], state: { datasourceStates: { - indexpattern: { + formBased: { layers: { layer1: dataLayer!, }, diff --git a/x-pack/examples/testing_embedded_lens/public/app.tsx b/x-pack/examples/testing_embedded_lens/public/app.tsx index cd550a9280004..2b8799c1951a3 100644 --- a/x-pack/examples/testing_embedded_lens/public/app.tsx +++ b/x-pack/examples/testing_embedded_lens/public/app.tsx @@ -148,7 +148,7 @@ function getBaseAttributes( ], state: { datasourceStates: { - indexpattern: { + formBased: { layers: { layer1: finalDataLayer, }, diff --git a/x-pack/examples/third_party_lens_navigation_prompt/public/plugin.ts b/x-pack/examples/third_party_lens_navigation_prompt/public/plugin.ts index aca5f5d0b37b8..0538c7f501742 100644 --- a/x-pack/examples/third_party_lens_navigation_prompt/public/plugin.ts +++ b/x-pack/examples/third_party_lens_navigation_prompt/public/plugin.ts @@ -71,7 +71,7 @@ function getLensAttributes(defaultDataView: DataView): TypedLensByValueInput['at ], state: { datasourceStates: { - indexpattern: { + formBased: { layers: { layer1: dataLayer, }, diff --git a/x-pack/examples/third_party_vis_lens_example/README.md b/x-pack/examples/third_party_vis_lens_example/README.md index f2fa563f33393..ccb8fc69d41ae 100644 --- a/x-pack/examples/third_party_vis_lens_example/README.md +++ b/x-pack/examples/third_party_vis_lens_example/README.md @@ -16,7 +16,7 @@ To test the migration, you can import the following ndjson file via saved object ``` {"attributes":{"fieldFormatMap":"{\"hour_of_day\":{}}","runtimeFieldMap":"{\"hour_of_day\":{\"type\":\"long\",\"script\":{\"source\":\"emit(doc['timestamp'].value.getHour());\"}}}","timeFieldName":"timestamp","title":"kibana_sample_data_logs"},"coreMigrationVersion":"8.0.0","id":"90943e30-9a47-11e8-b64d-95841ca0b247","migrationVersion":{"index-pattern":"8.0.0"},"references":[],"type":"index-pattern","updated_at":"2022-01-24T10:54:24.209Z","version":"WzQzMTQ3LDFd"} -{"attributes":{"description":"","state":{"datasourceStates":{"indexpattern":{"layers":{"f2700077-50bf-48e4-829c-f695f87e226d":{"columnOrder":["5e704cac-8490-457a-b635-01f3a5a132b7"],"columns":{"5e704cac-8490-457a-b635-01f3a5a132b7":{"dataType":"number","isBucketed":false,"label":"Count of records","operationType":"count","scale":"ratio","sourceField":"Records"}},"incompleteColumns":{}}}}},"filters":[],"query":{"language":"kuery","query":""},"visualization":{"column":"5e704cac-8490-457a-b635-01f3a5a132b7","layerId":"f2700077-50bf-48e4-829c-f695f87e226d"}},"title":"Rotating number test","visualizationType":"rotatingNumber"},"coreMigrationVersion":"8.0.0","id":"468f0be0-7e86-11ec-9739-d570ffd3fbe4","migrationVersion":{"lens":"8.0.0"},"references":[{"id":"90943e30-9a47-11e8-b64d-95841ca0b247","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"90943e30-9a47-11e8-b64d-95841ca0b247","name":"indexpattern-datasource-layer-f2700077-50bf-48e4-829c-f695f87e226d","type":"index-pattern"}],"type":"lens","updated_at":"2022-01-26T08:59:31.618Z","version":"WzQzNjUzLDFd"} +{"attributes":{"description":"","state":{"datasourceStates":{"formBased":{"layers":{"f2700077-50bf-48e4-829c-f695f87e226d":{"columnOrder":["5e704cac-8490-457a-b635-01f3a5a132b7"],"columns":{"5e704cac-8490-457a-b635-01f3a5a132b7":{"dataType":"number","isBucketed":false,"label":"Count of records","operationType":"count","scale":"ratio","sourceField":"Records"}},"incompleteColumns":{}}}}},"filters":[],"query":{"language":"kuery","query":""},"visualization":{"column":"5e704cac-8490-457a-b635-01f3a5a132b7","layerId":"f2700077-50bf-48e4-829c-f695f87e226d"}},"title":"Rotating number test","visualizationType":"rotatingNumber"},"coreMigrationVersion":"8.0.0","id":"468f0be0-7e86-11ec-9739-d570ffd3fbe4","migrationVersion":{"lens":"8.0.0"},"references":[{"id":"90943e30-9a47-11e8-b64d-95841ca0b247","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"90943e30-9a47-11e8-b64d-95841ca0b247","name":"indexpattern-datasource-layer-f2700077-50bf-48e4-829c-f695f87e226d","type":"index-pattern"}],"type":"lens","updated_at":"2022-01-26T08:59:31.618Z","version":"WzQzNjUzLDFd"} {"excludedObjects":[],"excludedObjectsCount":0,"exportedCount":2,"missingRefCount":0,"missingReferences":[]} ``` diff --git a/x-pack/examples/third_party_vis_lens_example/public/plugin.ts b/x-pack/examples/third_party_vis_lens_example/public/plugin.ts index f7a0378619b3a..38922ae676666 100644 --- a/x-pack/examples/third_party_vis_lens_example/public/plugin.ts +++ b/x-pack/examples/third_party_vis_lens_example/public/plugin.ts @@ -67,7 +67,7 @@ function getLensAttributes(defaultDataView: DataView): TypedLensByValueInput['at ], state: { datasourceStates: { - indexpattern: { + formBased: { layers: { layer1: dataLayer, }, diff --git a/x-pack/packages/ml/aiops_utils/src/stream_factory.test.ts b/x-pack/packages/ml/aiops_utils/src/stream_factory.test.ts index 1e6d7b40b22d0..27751b7dc3fd1 100644 --- a/x-pack/packages/ml/aiops_utils/src/stream_factory.test.ts +++ b/x-pack/packages/ml/aiops_utils/src/stream_factory.test.ts @@ -29,7 +29,7 @@ describe('streamFactory', () => { let mockLogger: Logger; beforeEach(() => { - mockLogger = { error: jest.fn() } as unknown as Logger; + mockLogger = { debug: jest.fn(), error: jest.fn(), info: jest.fn() } as unknown as Logger; }); it('should encode and receive an uncompressed string based stream', async () => { diff --git a/x-pack/packages/ml/aiops_utils/src/stream_factory.ts b/x-pack/packages/ml/aiops_utils/src/stream_factory.ts index fa455a04c23f1..d6e60e76efaa9 100644 --- a/x-pack/packages/ml/aiops_utils/src/stream_factory.ts +++ b/x-pack/packages/ml/aiops_utils/src/stream_factory.ts @@ -14,12 +14,15 @@ import type { Headers, ResponseHeaders } from '@kbn/core-http-server'; import { acceptCompression } from './accept_compression'; -// We need this otherwise Kibana server will crash with a 'ERR_METHOD_NOT_IMPLEMENTED' error. -class ResponseStream extends Stream.PassThrough { - flush() {} - _read() {} +// type guard to identify compressed stream +function isCompressedSream(arg: unknown): arg is zlib.Gzip { + return typeof arg === 'object' && arg !== null && typeof (arg as zlib.Gzip).flush === 'function'; } +const FLUSH_PAYLOAD_SIZE = 4 * 1024; + +class UncompressedResponseStream extends Stream.PassThrough {} + const DELIMITER = '\n'; type StreamType = 'string' | 'ndjson'; @@ -27,9 +30,9 @@ type StreamType = 'string' | 'ndjson'; interface StreamFactoryReturnType { DELIMITER: string; end: () => void; - push: (d: T) => void; + push: (d: T, drain?: boolean) => void; responseWithHeaders: { - body: zlib.Gzip | ResponseStream; + body: zlib.Gzip | UncompressedResponseStream; headers?: ResponseHeaders; }; } @@ -39,11 +42,16 @@ interface StreamFactoryReturnType { * for gzip compression depending on provided request headers. * * @param headers - Request headers. + * @param logger - Kibana logger. + * @param compressOverride - Optional flag to override header based compression setting. + * @param flushFix - Adds an attribute with a random string payload to overcome buffer flushing with certain proxy configurations. + * * @returns An object with stream attributes and methods. */ export function streamFactory( headers: Headers, logger: Logger, + compressOverride?: boolean, flushFix?: boolean ): StreamFactoryReturnType; /** @@ -51,27 +59,72 @@ export function streamFactory( * request headers. Any non-string data pushed to the stream will be stream as NDJSON. * * @param headers - Request headers. + * @param logger - Kibana logger. + * @param compressOverride - Optional flag to override header based compression setting. + * @param flushFix - Adds an attribute with a random string payload to overcome buffer flushing with certain proxy configurations. + * * @returns An object with stream attributes and methods. */ export function streamFactory( headers: Headers, logger: Logger, + compressOverride: boolean = true, flushFix: boolean = false ): StreamFactoryReturnType { let streamType: StreamType; - const isCompressed = acceptCompression(headers); + const isCompressed = compressOverride && acceptCompression(headers); + + const stream = isCompressed ? zlib.createGzip() : new UncompressedResponseStream(); + + // If waiting for draining of the stream, items will be added to this buffer. + const backPressureBuffer: T[] = []; - const stream = isCompressed ? zlib.createGzip() : new ResponseStream(); + // Flag will be set when the "drain" listener is active so we can avoid setting multiple listeners. + let waitForDrain = false; + + // Instead of a flag this is an array where we check if we are waiting on any callback from writing to the stream. + // It needs to be an array to avoid running into race conditions. + const waitForCallbacks: number[] = []; + + // Flag to set if the stream should be ended. Because there could be items in the backpressure buffer, we might + // not want to end the stream right away. Once the backpressure buffer is cleared, we'll end the stream eventually. + let tryToEnd = false; + + function logDebugMessage(msg: string) { + logger.debug(`HTTP Response Stream: ${msg}`); + } function end() { - stream.end(); + tryToEnd = true; + + logDebugMessage(`backPressureBuffer size on end(): ${backPressureBuffer.length}`); + logDebugMessage(`waitForCallbacks size on end(): ${waitForCallbacks.length}`); + + // Before ending the stream, we need to empty the backPressureBuffer + if (backPressureBuffer.length > 0) { + const el = backPressureBuffer.shift(); + if (el !== undefined) { + push(el, true); + } + return; + } + + if (waitForCallbacks.length === 0) { + logDebugMessage('All backPressureBuffer and waitForCallbacks cleared, ending the stream.'); + stream.end(); + } } - function push(d: T) { + function push(d: T, drain = false) { + logDebugMessage( + `Push to stream. Current backPressure buffer size: ${backPressureBuffer.length}, drain flag: ${drain}` + ); + if (d === undefined) { logger.error('Stream chunk must not be undefined.'); return; } + // Initialize the stream type with the first push to the stream, // otherwise check the integrity of the data to be pushed. if (streamType === undefined) { @@ -84,26 +137,69 @@ export function streamFactory( return; } + if ((!drain && waitForDrain) || (!drain && backPressureBuffer.length > 0)) { + logDebugMessage('Adding item to backpressure buffer.'); + backPressureBuffer.push(d); + return; + } + try { const line = streamType === 'ndjson' ? `${JSON.stringify({ ...d, // This is a temporary fix for response streaming with proxy configurations that buffer responses up to 4KB in size. - ...(flushFix ? { flushPayload: crypto.randomBytes(4096).toString('hex') } : {}), + ...(flushFix + ? { flushPayload: crypto.randomBytes(FLUSH_PAYLOAD_SIZE).toString('hex') } + : {}), })}${DELIMITER}` : d; - stream.write(line); + + waitForCallbacks.push(1); + const writeOk = stream.write(line, () => { + waitForCallbacks.pop(); + // Calling .flush() on a compression stream will + // make zlib return as much output as currently possible. + if (isCompressedSream(stream)) { + stream.flush(); + } + + if (tryToEnd && waitForCallbacks.length === 0) { + end(); + } + }); + + logDebugMessage(`Ok to write to the stream again? ${writeOk}`); + + if (!writeOk) { + logDebugMessage(`Should we add the "drain" listener?: ${!waitForDrain}`); + if (!waitForDrain) { + waitForDrain = true; + stream.once('drain', () => { + logDebugMessage( + 'The "drain" listener triggered, we can continue pushing to the stream.' + ); + + waitForDrain = false; + if (backPressureBuffer.length > 0) { + const el = backPressureBuffer.shift(); + if (el !== undefined) { + push(el, true); + } + } + }); + } + } else if (writeOk && drain && backPressureBuffer.length > 0) { + logDebugMessage('Continue clearing the backpressure buffer.'); + const el = backPressureBuffer.shift(); + if (el !== undefined) { + push(el, true); + } + } } catch (e) { logger.error(`Could not serialize or stream data chunk: ${e.toString()}`); return; } - - // Calling .flush() on a compression stream will - // make zlib return as much output as currently possible. - if (isCompressed) { - stream.flush(); - } } const responseWithHeaders: StreamFactoryReturnType['responseWithHeaders'] = { diff --git a/x-pack/plugins/actions/server/feature.ts b/x-pack/plugins/actions/server/feature.ts index c176e9f261551..aa0b88dbee633 100644 --- a/x-pack/plugins/actions/server/feature.ts +++ b/x-pack/plugins/actions/server/feature.ts @@ -28,7 +28,7 @@ export const ACTIONS_FEATURE = { app: [], order: FEATURE_ORDER, management: { - insightsAndAlerting: ['triggersActions'], + insightsAndAlerting: ['triggersActions', 'triggersActionsConnectors'], }, privileges: { all: { @@ -36,7 +36,7 @@ export const ACTIONS_FEATURE = { api: [], catalogue: [], management: { - insightsAndAlerting: ['triggersActions'], + insightsAndAlerting: ['triggersActions', 'triggersActionsConnectors'], }, savedObject: { all: [ @@ -53,7 +53,7 @@ export const ACTIONS_FEATURE = { api: [], catalogue: [], management: { - insightsAndAlerting: ['triggersActions'], + insightsAndAlerting: ['triggersActions', 'triggersActionsConnectors'], }, savedObject: { // action execution requires 'read' over `actions`, but 'all' over `action_task_params` diff --git a/x-pack/plugins/actions/server/saved_objects/get_import_warnings.ts b/x-pack/plugins/actions/server/saved_objects/get_import_warnings.ts index 2c8eef94f9a4d..ce2b290ed2ab4 100644 --- a/x-pack/plugins/actions/server/saved_objects/get_import_warnings.ts +++ b/x-pack/plugins/actions/server/saved_objects/get_import_warnings.ts @@ -29,7 +29,7 @@ export function getImportWarnings( { type: 'action_required', message, - actionPath: '/app/management/insightsAndAlerting/triggersActions/connectors', + actionPath: '/app/management/insightsAndAlerting/triggersActionsConnectors', buttonLabel: GO_TO_CONNECTORS_BUTTON_LABLE, } as SavedObjectsImportWarning, ]; diff --git a/x-pack/plugins/actions/server/sub_action_framework/sub_action_connector.ts b/x-pack/plugins/actions/server/sub_action_framework/sub_action_connector.ts index 41f2b03b3da77..01b7876d69afd 100644 --- a/x-pack/plugins/actions/server/sub_action_framework/sub_action_connector.ts +++ b/x-pack/plugins/actions/server/sub_action_framework/sub_action_connector.ts @@ -146,7 +146,9 @@ export abstract class SubActionConnector { `Request to external service failed. Connector Id: ${this.connector.id}. Connector type: ${this.connector.type}. Method: ${error.config.method}. URL: ${error.config.url}` ); - const errorMessage = this.getResponseErrorMessage(error); + const errorMessage = `Status code: ${error.status}. Message: ${this.getResponseErrorMessage( + error + )}`; throw new Error(errorMessage); } diff --git a/x-pack/plugins/aiops/common/api/explain_log_rate_spikes/schema.ts b/x-pack/plugins/aiops/common/api/explain_log_rate_spikes/schema.ts index f816af06f5324..a5d48462c5170 100644 --- a/x-pack/plugins/aiops/common/api/explain_log_rate_spikes/schema.ts +++ b/x-pack/plugins/aiops/common/api/explain_log_rate_spikes/schema.ts @@ -21,6 +21,9 @@ export const aiopsExplainLogRateSpikesSchema = schema.object({ deviationMax: schema.number(), /** The index to query for log rate spikes */ index: schema.string(), + /** Settings to override headers derived compression and flush fix */ + compressResponse: schema.maybe(schema.boolean()), + flushFix: schema.maybe(schema.boolean()), }); export type AiopsExplainLogRateSpikesSchema = TypeOf; diff --git a/x-pack/plugins/aiops/public/components/explain_log_rate_spikes/explain_log_rate_spikes_analysis.tsx b/x-pack/plugins/aiops/public/components/explain_log_rate_spikes/explain_log_rate_spikes_analysis.tsx index 9949ec537b77a..74be1a0f048fc 100644 --- a/x-pack/plugins/aiops/public/components/explain_log_rate_spikes/explain_log_rate_spikes_analysis.tsx +++ b/x-pack/plugins/aiops/public/components/explain_log_rate_spikes/explain_log_rate_spikes_analysis.tsx @@ -95,6 +95,7 @@ export const ExplainLogRateSpikesAnalysis: FC timeFieldName: dataView.timeFieldName ?? '', index: dataView.title, grouping: true, + flushFix: true, ...windowParameters, }, { reducer: streamReducer, initialState } diff --git a/x-pack/plugins/aiops/server/routes/explain_log_rate_spikes.ts b/x-pack/plugins/aiops/server/routes/explain_log_rate_spikes.ts index 949b535ca16fb..67cbcce241401 100644 --- a/x-pack/plugins/aiops/server/routes/explain_log_rate_spikes.ts +++ b/x-pack/plugins/aiops/server/routes/explain_log_rate_spikes.ts @@ -51,6 +51,9 @@ import { markDuplicates, } from './queries/get_simple_hierarchical_tree'; +// 10s ping frequency to keep the stream alive. +const PING_FREQUENCY = 10000; + // Overall progress is a float from 0 to 1. const LOADED_FIELD_CANDIDATES = 0.2; const PROGRESS_STEP_P_VALUES = 0.5; @@ -77,12 +80,12 @@ export const defineExplainLogRateSpikesRoute = ( let logMessageCounter = 1; - function logInfoMessage(msg: string) { - logger.info(`Explain Log Rate Spikes #${logMessageCounter}: ${msg}`); + function logDebugMessage(msg: string) { + logger.debug(`Explain Log Rate Spikes #${logMessageCounter}: ${msg}`); logMessageCounter++; } - logInfoMessage('Starting analysis.'); + logDebugMessage('Starting analysis.'); const groupingEnabled = !!request.body.grouping; @@ -90,15 +93,16 @@ export const defineExplainLogRateSpikesRoute = ( const controller = new AbortController(); + let isRunning = false; let loaded = 0; let shouldStop = false; request.events.aborted$.subscribe(() => { - logInfoMessage('aborted$ subscription trigger.'); + logDebugMessage('aborted$ subscription trigger.'); shouldStop = true; controller.abort(); }); request.events.completed$.subscribe(() => { - logInfoMessage('completed$ subscription trigger.'); + logDebugMessage('completed$ subscription trigger.'); shouldStop = true; controller.abort(); }); @@ -107,17 +111,26 @@ export const defineExplainLogRateSpikesRoute = ( end: streamEnd, push, responseWithHeaders, - } = streamFactory(request.headers, logger, true); - - function pushPing() { - push(pingAction()); + } = streamFactory( + request.headers, + logger, + request.body.compressResponse, + request.body.flushFix + ); + + function pushPingWithTimeout() { + setTimeout(() => { + if (isRunning) { + logDebugMessage('Ping message.'); + push(pingAction()); + pushPingWithTimeout(); + } + }, PING_FREQUENCY); } - const pingInterval = setInterval(pushPing, 1000); - function end() { - logInfoMessage('Ending analysis.'); - clearInterval(pingInterval); + isRunning = false; + logDebugMessage('Ending analysis.'); streamEnd(); } @@ -139,15 +152,16 @@ export const defineExplainLogRateSpikesRoute = ( } function pushError(m: string) { - logInfoMessage('Push error.'); + logDebugMessage('Push error.'); push(addErrorAction(m)); } - // Async IIFE to run the analysis while not blocking returning `responseWithHeaders`. - (async () => { - logInfoMessage('Reset.'); + async function runAnalysis() { + isRunning = true; + logDebugMessage('Reset.'); push(resetAction()); - logInfoMessage('Load field candidates.'); + pushPingWithTimeout(); + logDebugMessage('Load field candidates.'); push( updateLoadingStateAction({ ccsWarning: false, @@ -204,11 +218,11 @@ export const defineExplainLogRateSpikesRoute = ( const fieldCandidatesChunks = chunk(fieldCandidates, chunkSize); - logInfoMessage('Fetch p-values.'); + logDebugMessage('Fetch p-values.'); for (const fieldCandidatesChunk of fieldCandidatesChunks) { chunkCount++; - logInfoMessage(`Fetch p-values. Chunk ${chunkCount} of ${fieldCandidatesChunks.length}`); + logDebugMessage(`Fetch p-values. Chunk ${chunkCount} of ${fieldCandidatesChunks.length}`); let pValues: Awaited>; try { pValues = await fetchChangePointPValues( @@ -258,7 +272,7 @@ export const defineExplainLogRateSpikesRoute = ( ); if (shouldStop) { - logInfoMessage('shouldStop fetching p-values.'); + logDebugMessage('shouldStop fetching p-values.'); end(); return; @@ -266,7 +280,7 @@ export const defineExplainLogRateSpikesRoute = ( } if (changePoints?.length === 0) { - logInfoMessage('Stopping analysis, did not find change points.'); + logDebugMessage('Stopping analysis, did not find change points.'); endWithUpdatedLoadingState(); return; } @@ -275,7 +289,7 @@ export const defineExplainLogRateSpikesRoute = ( { fieldName: request.body.timeFieldName, type: KBN_FIELD_TYPES.DATE }, ]; - logInfoMessage('Fetch overall histogram.'); + logDebugMessage('Fetch overall histogram.'); let overallTimeSeries: NumericChartData | undefined; try { @@ -313,7 +327,7 @@ export const defineExplainLogRateSpikesRoute = ( } if (groupingEnabled) { - logInfoMessage('Group results.'); + logDebugMessage('Group results.'); push( updateLoadingStateAction({ @@ -498,7 +512,7 @@ export const defineExplainLogRateSpikesRoute = ( pushHistogramDataLoadingState(); - logInfoMessage('Fetch group histograms.'); + logDebugMessage('Fetch group histograms.'); await asyncForEach(changePointGroups, async (cpg) => { if (overallTimeSeries !== undefined) { @@ -577,7 +591,7 @@ export const defineExplainLogRateSpikesRoute = ( loaded += PROGRESS_STEP_HISTOGRAMS_GROUPS; - logInfoMessage('Fetch field/value histograms.'); + logDebugMessage('Fetch field/value histograms.'); // time series filtered by fields if (changePoints && overallTimeSeries !== undefined) { @@ -661,7 +675,10 @@ export const defineExplainLogRateSpikesRoute = ( } endWithUpdatedLoadingState(); - })(); + } + + // Do not call this using `await` so it will run asynchronously while we return the stream already. + runAnalysis(); return response.ok(responseWithHeaders); } diff --git a/x-pack/plugins/alerting/common/execution_log_types.ts b/x-pack/plugins/alerting/common/execution_log_types.ts index b08a0bf76d69e..223b45cb98923 100644 --- a/x-pack/plugins/alerting/common/execution_log_types.ts +++ b/x-pack/plugins/alerting/common/execution_log_types.ts @@ -30,6 +30,7 @@ export const EMPTY_EXECUTION_KPI_RESULT = { success: 0, unknown: 0, failure: 0, + warning: 0, activeAlerts: 0, newAlerts: 0, recoveredAlerts: 0, diff --git a/x-pack/plugins/alerting/common/rule.ts b/x-pack/plugins/alerting/common/rule.ts index 1514de7b95209..c6c598cf8aebc 100644 --- a/x-pack/plugins/alerting/common/rule.ts +++ b/x-pack/plugins/alerting/common/rule.ts @@ -48,6 +48,8 @@ export enum RuleExecutionStatusWarningReasons { MAX_ALERTS = 'maxAlerts', } +export type RuleAlertingOutcome = 'failure' | 'success' | 'unknown' | 'warning'; + export interface RuleExecutionStatus { status: RuleExecutionStatuses; lastExecutionDate: Date; diff --git a/x-pack/plugins/alerting/server/lib/alerting_event_logger/alerting_event_logger.test.ts b/x-pack/plugins/alerting/server/lib/alerting_event_logger/alerting_event_logger.test.ts index 8fe081864b118..3dea32f4f45a4 100644 --- a/x-pack/plugins/alerting/server/lib/alerting_event_logger/alerting_event_logger.test.ts +++ b/x-pack/plugins/alerting/server/lib/alerting_event_logger/alerting_event_logger.test.ts @@ -223,6 +223,12 @@ describe('AlertingEventLogger', () => { ...event.rule, name: 'my-super-cool-rule', }, + kibana: { + ...event.kibana, + alerting: { + outcome: 'success', + }, + }, message: 'success!', }); }); @@ -260,6 +266,12 @@ describe('AlertingEventLogger', () => { error: { message: 'something went wrong!', }, + kibana: { + ...event.kibana, + alerting: { + outcome: 'failure', + }, + }, message: 'rule failed!', }); }); @@ -446,6 +458,7 @@ describe('AlertingEventLogger', () => { ...event?.kibana, alerting: { status: 'error', + outcome: 'failure', }, }, message: 'test:123: execution failed', @@ -484,6 +497,7 @@ describe('AlertingEventLogger', () => { ...event?.kibana, alerting: { status: 'error', + outcome: 'failure', }, }, message: 'test:123: execution failed', @@ -526,6 +540,7 @@ describe('AlertingEventLogger', () => { ...event?.kibana, alerting: { status: 'error', + outcome: 'failure', }, }, message: 'i am an existing error message', @@ -560,6 +575,7 @@ describe('AlertingEventLogger', () => { ...event?.kibana, alerting: { status: 'warning', + outcome: 'warning', }, }, message: 'something funky happened', @@ -594,6 +610,7 @@ describe('AlertingEventLogger', () => { ...event?.kibana, alerting: { status: 'warning', + outcome: 'warning', }, }, message: 'something funky happened', @@ -630,6 +647,7 @@ describe('AlertingEventLogger', () => { ...event?.kibana, alerting: { status: 'warning', + outcome: 'success', }, }, message: 'success!', diff --git a/x-pack/plugins/alerting/server/lib/alerting_event_logger/alerting_event_logger.ts b/x-pack/plugins/alerting/server/lib/alerting_event_logger/alerting_event_logger.ts index 18e4044172eb4..4fd3afafba5c2 100644 --- a/x-pack/plugins/alerting/server/lib/alerting_event_logger/alerting_event_logger.ts +++ b/x-pack/plugins/alerting/server/lib/alerting_event_logger/alerting_event_logger.ts @@ -127,7 +127,7 @@ export class AlertingEventLogger { throw new Error('AlertingEventLogger not initialized'); } - updateEvent(this.event, { message, outcome: 'success' }); + updateEvent(this.event, { message, outcome: 'success', alertingOutcome: 'success' }); } public setExecutionFailed(message: string, errorMessage: string) { @@ -135,7 +135,12 @@ export class AlertingEventLogger { throw new Error('AlertingEventLogger not initialized'); } - updateEvent(this.event, { message, outcome: 'failure', error: errorMessage }); + updateEvent(this.event, { + message, + outcome: 'failure', + alertingOutcome: 'failure', + error: errorMessage, + }); } public logTimeout() { @@ -175,6 +180,7 @@ export class AlertingEventLogger { if (status.error) { updateEvent(this.event, { outcome: 'failure', + alertingOutcome: 'failure', reason: status.error?.reason || 'unknown', error: this.event?.error?.message || status.error.message, ...(this.event.message @@ -186,6 +192,7 @@ export class AlertingEventLogger { } else { if (status.warning) { updateEvent(this.event, { + alertingOutcome: 'warning', reason: status.warning?.reason || 'unknown', message: status.warning?.message || this.event?.message, }); @@ -325,6 +332,7 @@ export function initializeExecuteRecord(context: RuleContext) { interface UpdateEventOpts { message?: string; outcome?: string; + alertingOutcome?: string; error?: string; ruleName?: string; status?: string; @@ -332,8 +340,10 @@ interface UpdateEventOpts { metrics?: RuleRunMetrics; timings?: TaskRunnerTimings; } + export function updateEvent(event: IEvent, opts: UpdateEventOpts) { - const { message, outcome, error, ruleName, status, reason, metrics, timings } = opts; + const { message, outcome, error, ruleName, status, reason, metrics, timings, alertingOutcome } = + opts; if (!event) { throw new Error('Cannot update event because it is not initialized.'); } @@ -346,6 +356,12 @@ export function updateEvent(event: IEvent, opts: UpdateEventOpts) { event.event.outcome = outcome; } + if (alertingOutcome) { + event.kibana = event.kibana || {}; + event.kibana.alerting = event.kibana.alerting || {}; + event.kibana.alerting.outcome = alertingOutcome; + } + if (error) { event.error = event.error || {}; event.error.message = error; diff --git a/x-pack/plugins/alerting/server/lib/get_execution_log_aggregation.test.ts b/x-pack/plugins/alerting/server/lib/get_execution_log_aggregation.test.ts index eb46ae67e2ef1..ee05e3cda32f6 100644 --- a/x-pack/plugins/alerting/server/lib/get_execution_log_aggregation.test.ts +++ b/x-pack/plugins/alerting/server/lib/get_execution_log_aggregation.test.ts @@ -281,6 +281,7 @@ describe('getExecutionLogAggregation', () => { 'kibana.version', 'rule.id', 'rule.name', + 'kibana.alerting.outcome', ], }, }, @@ -486,6 +487,7 @@ describe('getExecutionLogAggregation', () => { 'kibana.version', 'rule.id', 'rule.name', + 'kibana.alerting.outcome', ], }, }, @@ -691,6 +693,7 @@ describe('getExecutionLogAggregation', () => { 'kibana.version', 'rule.id', 'rule.name', + 'kibana.alerting.outcome', ], }, }, @@ -787,6 +790,9 @@ describe('formatExecutionLogResult', () => { }, kibana: { version: '8.2.0', + alerting: { + outcome: 'success', + }, }, message: "rule executed: example.always-firing:a348a740-9e2c-11ec-bd64-774ed95c43ef: 'test rule'", @@ -866,12 +872,14 @@ describe('formatExecutionLogResult', () => { _score: 1.0, _source: { rule: { id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef', name: 'rule_name' }, - event: { outcome: 'success', }, kibana: { version: '8.2.0', + alerting: { + outcome: 'success', + }, }, message: "rule executed: example.always-firing:a348a740-9e2c-11ec-bd64-774ed95c43ef: 'test rule'", @@ -1028,6 +1036,9 @@ describe('formatExecutionLogResult', () => { }, kibana: { version: '8.2.0', + alerting: { + outcome: 'failure', + }, }, message: "rule execution failure: example.always-firing:a348a740-9e2c-11ec-bd64-774ed95c43ef: 'test rule'", @@ -1115,6 +1126,9 @@ describe('formatExecutionLogResult', () => { }, kibana: { version: '8.2.0', + alerting: { + outcome: 'success', + }, }, message: "rule executed: example.always-firing:a348a740-9e2c-11ec-bd64-774ed95c43ef: 'test rule'", @@ -1271,6 +1285,9 @@ describe('formatExecutionLogResult', () => { }, kibana: { version: '8.2.0', + alerting: { + outcome: 'success', + }, }, message: "rule executed: example.always-firing:a348a740-9e2c-11ec-bd64-774ed95c43ef: 'test rule'", @@ -1350,6 +1367,9 @@ describe('formatExecutionLogResult', () => { }, kibana: { version: '8.2.0', + alerting: { + outcome: 'success', + }, }, message: "rule executed: example.always-firing:a348a740-9e2c-11ec-bd64-774ed95c43ef: 'test rule'", @@ -1506,6 +1526,9 @@ describe('formatExecutionLogResult', () => { }, kibana: { version: '8.2.0', + alerting: { + outcome: 'success', + }, }, message: "rule executed: example.always-firing:a348a740-9e2c-11ec-bd64-774ed95c43ef: 'test rule'", @@ -1590,6 +1613,9 @@ describe('formatExecutionLogResult', () => { }, kibana: { version: '8.2.0', + alerting: { + outcome: 'success', + }, }, message: "rule executed: example.always-firing:a348a740-9e2c-11ec-bd64-774ed95c43ef: 'test rule'", @@ -1711,13 +1737,18 @@ describe('getExecutionKPIAggregation', () => { executionUuid: { terms: { field: 'kibana.alert.rule.execution.uuid', - size: 1000, + order: [ + { + 'ruleExecution>executeStartTime': 'desc', + }, + ], + size: 10000, }, aggs: { executionUuidSorted: { bucket_sort: { from: 0, - size: 1000, + size: 10000, gap_policy: 'insert_zeros', }, }, @@ -1777,6 +1808,11 @@ describe('getExecutionKPIAggregation', () => { }, }, aggs: { + executeStartTime: { + min: { + field: 'event.start', + }, + }, numTriggeredActions: { sum: { field: 'kibana.alert.rule.execution.metrics.number_of_triggered_actions', @@ -1808,9 +1844,17 @@ describe('getExecutionKPIAggregation', () => { }, }, ruleExecutionOutcomes: { - terms: { - field: 'event.outcome', - size: 2, + multi_terms: { + size: 3, + terms: [ + { + field: 'kibana.alerting.outcome', + missing: '', + }, + { + field: 'event.outcome', + }, + ], }, }, }, @@ -1850,13 +1894,18 @@ describe('getExecutionKPIAggregation', () => { executionUuid: { terms: { field: 'kibana.alert.rule.execution.uuid', - size: 1000, + order: [ + { + 'ruleExecution>executeStartTime': 'desc', + }, + ], + size: 10000, }, aggs: { executionUuidSorted: { bucket_sort: { from: 0, - size: 1000, + size: 10000, gap_policy: 'insert_zeros', }, }, @@ -1928,6 +1977,11 @@ describe('getExecutionKPIAggregation', () => { }, }, aggs: { + executeStartTime: { + min: { + field: 'event.start', + }, + }, numTriggeredActions: { sum: { field: 'kibana.alert.rule.execution.metrics.number_of_triggered_actions', @@ -1959,9 +2013,17 @@ describe('getExecutionKPIAggregation', () => { }, }, ruleExecutionOutcomes: { - terms: { - field: 'event.outcome', - size: 2, + multi_terms: { + size: 3, + terms: [ + { + field: 'kibana.alerting.outcome', + missing: '', + }, + { + field: 'event.outcome', + }, + ], }, }, }, @@ -2001,13 +2063,18 @@ describe('getExecutionKPIAggregation', () => { executionUuid: { terms: { field: 'kibana.alert.rule.execution.uuid', - size: 1000, + order: [ + { + 'ruleExecution>executeStartTime': 'desc', + }, + ], + size: 10000, }, aggs: { executionUuidSorted: { bucket_sort: { from: 0, - size: 1000, + size: 10000, gap_policy: 'insert_zeros', }, }, @@ -2079,6 +2146,11 @@ describe('getExecutionKPIAggregation', () => { }, }, aggs: { + executeStartTime: { + min: { + field: 'event.start', + }, + }, numTriggeredActions: { sum: { field: 'kibana.alert.rule.execution.metrics.number_of_triggered_actions', @@ -2110,9 +2182,17 @@ describe('getExecutionKPIAggregation', () => { }, }, ruleExecutionOutcomes: { - terms: { - field: 'event.outcome', - size: 2, + multi_terms: { + size: 3, + terms: [ + { + field: 'kibana.alerting.outcome', + missing: '', + }, + { + field: 'event.outcome', + }, + ], }, }, }, @@ -2150,6 +2230,7 @@ describe('formatExecutionKPIAggBuckets', () => { success: 0, triggeredActions: 0, unknown: 0, + warning: 0, }); }); @@ -2188,7 +2269,8 @@ describe('formatExecutionKPIAggBuckets', () => { sum_other_doc_count: 0, buckets: [ { - key: 'success', + key: ['success', 'success'], + key_as_string: 'success|success', doc_count: 3, }, ], @@ -2233,7 +2315,8 @@ describe('formatExecutionKPIAggBuckets', () => { sum_other_doc_count: 0, buckets: [ { - key: 'success', + key: ['success', 'success'], + key_as_string: 'success|success', doc_count: 2, }, ], @@ -2264,6 +2347,129 @@ describe('formatExecutionKPIAggBuckets', () => { success: 5, unknown: 0, failure: 0, + warning: 0, + activeAlerts: 10, + newAlerts: 10, + recoveredAlerts: 0, + erroredActions: 3, + triggeredActions: 10, + }); + }); + + test('should format results correctly when outcome is warning and alerting outcome is not set', () => { + const results = { + aggregations: { + excludeExecuteStart: { + meta: {}, + doc_count: 875, + executionUuid: { + meta: {}, + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [ + { + ruleExecution: { + meta: {}, + doc_count: 3, + numTriggeredActions: { + value: 5.0, + }, + numGeneratedActions: { + value: 5.0, + }, + numActiveAlerts: { + value: 5.0, + }, + numNewAlerts: { + value: 5.0, + }, + numRecoveredAlerts: { + value: 0.0, + }, + ruleExecutionOutcomes: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [ + { + key: ['warning', 'success'], + key_as_string: 'warning|success', + doc_count: 3, + }, + ], + }, + }, + actionExecution: { + meta: {}, + doc_count: 5, + actionOutcomes: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [ + { + key: 'success', + doc_count: 5, + }, + ], + }, + }, + }, + { + ruleExecution: { + meta: {}, + doc_count: 2, + numTriggeredActions: { + value: 5.0, + }, + numGeneratedActions: { + value: 5.0, + }, + numActiveAlerts: { + value: 5.0, + }, + numNewAlerts: { + value: 5.0, + }, + numRecoveredAlerts: { + value: 0.0, + }, + ruleExecutionOutcomes: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [ + { + key: ['', 'success'], + key_as_string: '|success', + doc_count: 2, + }, + ], + }, + }, + actionExecution: { + meta: {}, + doc_count: 3, + actionOutcomes: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [ + { + key: 'failure', + doc_count: 3, + }, + ], + }, + }, + }, + ], + }, + }, + }, + }; + + expect(formatExecutionKPIResult(results)).toEqual({ + success: 2, + unknown: 0, + failure: 0, + warning: 3, activeAlerts: 10, newAlerts: 10, recoveredAlerts: 0, diff --git a/x-pack/plugins/alerting/server/lib/get_execution_log_aggregation.ts b/x-pack/plugins/alerting/server/lib/get_execution_log_aggregation.ts index fedc827a46c73..c2b261cd531ad 100644 --- a/x-pack/plugins/alerting/server/lib/get_execution_log_aggregation.ts +++ b/x-pack/plugins/alerting/server/lib/get_execution_log_aggregation.ts @@ -8,19 +8,21 @@ import { KueryNode } from '@kbn/core-saved-objects-api-server'; import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import Boom from '@hapi/boom'; -import { flatMap, get } from 'lodash'; +import { flatMap, get, isEmpty } from 'lodash'; import { AggregateEventsBySavedObjectResult } from '@kbn/event-log-plugin/server'; import { fromKueryExpression, toElasticsearchQuery } from '@kbn/es-query'; import { parseDuration } from '.'; import { IExecutionLog, IExecutionLogResult, EMPTY_EXECUTION_KPI_RESULT } from '../../common'; const DEFAULT_MAX_BUCKETS_LIMIT = 1000; // do not retrieve more than this number of executions +const DEFAULT_MAX_KPI_BUCKETS_LIMIT = 10000; const RULE_ID_FIELD = 'rule.id'; const RULE_NAME_FIELD = 'rule.name'; const PROVIDER_FIELD = 'event.provider'; const START_FIELD = 'event.start'; const ACTION_FIELD = 'event.action'; +const ALERTING_OUTCOME_FIELD = 'kibana.alerting.outcome'; const OUTCOME_FIELD = 'event.outcome'; const DURATION_FIELD = 'event.duration'; const MESSAGE_FIELD = 'message'; @@ -148,13 +150,14 @@ export const getExecutionKPIAggregation = (filter?: IExecutionLogAggOptions['fil // Bucket by execution UUID terms: { field: EXECUTION_UUID_FIELD, - size: DEFAULT_MAX_BUCKETS_LIMIT, + size: DEFAULT_MAX_KPI_BUCKETS_LIMIT, + order: formatSortForTermSort([{ timestamp: { order: 'desc' } }]), }, aggs: { executionUuidSorted: { bucket_sort: { from: 0, - size: 1000, + size: DEFAULT_MAX_KPI_BUCKETS_LIMIT, gap_policy: 'insert_zeros' as estypes.AggregationsGapPolicy, }, }, @@ -167,7 +170,7 @@ export const getExecutionKPIAggregation = (filter?: IExecutionLogAggOptions['fil aggs: { actionOutcomes: { terms: { - field: 'event.outcome', + field: OUTCOME_FIELD, size: 2, }, }, @@ -181,6 +184,11 @@ export const getExecutionKPIAggregation = (filter?: IExecutionLogAggOptions['fil }, }, aggs: { + executeStartTime: { + min: { + field: START_FIELD, + }, + }, numTriggeredActions: { sum: { field: 'kibana.alert.rule.execution.metrics.number_of_triggered_actions', @@ -212,9 +220,17 @@ export const getExecutionKPIAggregation = (filter?: IExecutionLogAggOptions['fil }, }, ruleExecutionOutcomes: { - terms: { - field: 'event.outcome', - size: 2, + multi_terms: { + size: 3, + terms: [ + { + field: ALERTING_OUTCOME_FIELD, + missing: '', + }, + { + field: OUTCOME_FIELD, + }, + ], }, }, }, @@ -395,6 +411,7 @@ export function getExecutionLogAggregation({ VERSION_FIELD, RULE_ID_FIELD, RULE_NAME_FIELD, + ALERTING_OUTCOME_FIELD, ], }, }, @@ -466,16 +483,19 @@ function formatExecutionLogAggBucket(bucket: IExecutionUuidAggBucket): IExecutio const actionExecutionError = actionExecutionOutcomes.find((subBucket) => subBucket?.key === 'failure')?.doc_count ?? 0; - const outcomeAndMessage = bucket?.ruleExecution?.outcomeAndMessage?.hits?.hits[0]?._source; - const status = outcomeAndMessage ? outcomeAndMessage?.event?.outcome ?? '' : ''; + const outcomeAndMessage = bucket?.ruleExecution?.outcomeAndMessage?.hits?.hits[0]?._source ?? {}; + let status = outcomeAndMessage.kibana?.alerting?.outcome ?? ''; + if (isEmpty(status)) { + status = outcomeAndMessage.event?.outcome ?? ''; + } + const outcomeMessage = outcomeAndMessage.message ?? ''; + const outcomeErrorMessage = outcomeAndMessage.error?.message ?? ''; const message = - status === 'failure' - ? `${outcomeAndMessage?.message ?? ''} - ${outcomeAndMessage?.error?.message ?? ''}` - : outcomeAndMessage?.message ?? ''; - const version = outcomeAndMessage ? outcomeAndMessage?.kibana?.version ?? '' : ''; + status === 'failure' ? `${outcomeMessage} - ${outcomeErrorMessage}` : outcomeMessage; + const version = outcomeAndMessage.kibana?.version ?? ''; - const ruleId = outcomeAndMessage ? outcomeAndMessage?.rule?.id ?? '' : ''; - const ruleName = outcomeAndMessage ? outcomeAndMessage?.rule?.name ?? '' : ''; + const ruleId = outcomeAndMessage.rule?.id ?? ''; + const ruleName = outcomeAndMessage.rule?.name ?? ''; return { id: bucket?.key ?? '', timestamp: bucket?.ruleExecution?.executeStartTime.value_as_string ?? '', @@ -504,6 +524,7 @@ function formatExecutionKPIAggBuckets(buckets: IExecutionUuidKpiAggBucket[]) { success: 0, unknown: 0, failure: 0, + warning: 0, activeAlerts: 0, newAlerts: 0, recoveredAlerts: 0, @@ -516,14 +537,31 @@ function formatExecutionKPIAggBuckets(buckets: IExecutionUuidKpiAggBucket[]) { const actionExecutionOutcomes = bucket?.actionExecution?.actionOutcomes?.buckets ?? []; const ruleExecutionCount = bucket?.ruleExecution?.doc_count ?? 0; - const successRuleExecution = - ruleExecutionOutcomes.find((subBucket) => subBucket?.key === 'success')?.doc_count ?? 0; - const failureRuleExecution = - ruleExecutionOutcomes.find((subBucket) => subBucket?.key === 'failure')?.doc_count ?? 0; - - objToReturn.success += successRuleExecution; - objToReturn.unknown += ruleExecutionCount - (successRuleExecution + failureRuleExecution); - objToReturn.failure += failureRuleExecution; + const outcomes = { + successRuleExecution: 0, + failureRuleExecution: 0, + warningRuleExecution: 0, + }; + ruleExecutionOutcomes.reduce((acc, subBucket) => { + const key = subBucket.key[0] ? subBucket.key[0] : subBucket.key[1]; + if (key === 'success') { + acc.successRuleExecution = subBucket.doc_count ?? 0; + } else if (key === 'failure') { + acc.failureRuleExecution = subBucket.doc_count ?? 0; + } else if (key === 'warning') { + acc.warningRuleExecution = subBucket.doc_count ?? 0; + } + return acc; + }, outcomes); + + objToReturn.success += outcomes.successRuleExecution; + objToReturn.unknown += + ruleExecutionCount - + (outcomes.successRuleExecution + + outcomes.failureRuleExecution + + outcomes.warningRuleExecution); + objToReturn.failure += outcomes.failureRuleExecution; + objToReturn.warning += outcomes.warningRuleExecution; objToReturn.activeAlerts += bucket?.ruleExecution?.numActiveAlerts.value ?? 0; objToReturn.newAlerts += bucket?.ruleExecution?.numNewAlerts.value ?? 0; objToReturn.recoveredAlerts += bucket?.ruleExecution?.numRecoveredAlerts.value ?? 0; diff --git a/x-pack/plugins/alerting/server/routes/get_global_execution_kpi.test.ts b/x-pack/plugins/alerting/server/routes/get_global_execution_kpi.test.ts index 89b21547c892a..e223d0a714d20 100644 --- a/x-pack/plugins/alerting/server/routes/get_global_execution_kpi.test.ts +++ b/x-pack/plugins/alerting/server/routes/get_global_execution_kpi.test.ts @@ -26,6 +26,7 @@ describe('getGlobalExecutionKPIRoute', () => { success: 3, unknown: 0, failure: 0, + warning: 0, activeAlerts: 5, newAlerts: 5, recoveredAlerts: 0, diff --git a/x-pack/plugins/alerting/server/routes/get_rule_execution_kpi.test.ts b/x-pack/plugins/alerting/server/routes/get_rule_execution_kpi.test.ts index db5033404788c..ff15a60623168 100644 --- a/x-pack/plugins/alerting/server/routes/get_rule_execution_kpi.test.ts +++ b/x-pack/plugins/alerting/server/routes/get_rule_execution_kpi.test.ts @@ -27,6 +27,7 @@ describe('getRuleExecutionKPIRoute', () => { success: 3, unknown: 0, failure: 0, + warning: 0, activeAlerts: 5, newAlerts: 5, recoveredAlerts: 0, diff --git a/x-pack/plugins/alerting/server/rules_client/tests/get_execution_log.test.ts b/x-pack/plugins/alerting/server/rules_client/tests/get_execution_log.test.ts index f5525820da6dc..83b85f4879cff 100644 --- a/x-pack/plugins/alerting/server/rules_client/tests/get_execution_log.test.ts +++ b/x-pack/plugins/alerting/server/rules_client/tests/get_execution_log.test.ts @@ -152,6 +152,9 @@ const aggregateResults = { }, kibana: { version: '8.2.0', + alerting: { + outcome: 'success', + }, }, message: "rule executed: example.always-firing:a348a740-9e2c-11ec-bd64-774ed95c43ef: 'test rule'", @@ -255,6 +258,9 @@ const aggregateResults = { }, kibana: { version: '8.2.0', + alerting: { + outcome: 'success', + }, }, message: "rule executed: example.always-firing:a348a740-9e2c-11ec-bd64-774ed95c43ef: 'test rule'", diff --git a/x-pack/plugins/alerting/server/saved_objects/migrations.ts b/x-pack/plugins/alerting/server/saved_objects/migrations.ts deleted file mode 100644 index 20ebb7b4eb8e9..0000000000000 --- a/x-pack/plugins/alerting/server/saved_objects/migrations.ts +++ /dev/null @@ -1,1082 +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 { isRuleType, ruleTypeMappings } from '@kbn/securitysolution-rules'; -import { isString } from 'lodash/fp'; -import { omit, pick } from 'lodash'; -import moment from 'moment-timezone'; -import { gte } from 'semver'; -import { - LogMeta, - SavedObjectMigrationMap, - SavedObjectUnsanitizedDoc, - SavedObjectMigrationFn, - SavedObjectMigrationContext, - SavedObjectAttributes, - SavedObjectAttribute, - SavedObjectReference, -} from '@kbn/core/server'; -import { EncryptedSavedObjectsPluginSetup } from '@kbn/encrypted-saved-objects-plugin/server'; -import type { IsMigrationNeededPredicate } from '@kbn/encrypted-saved-objects-plugin/server'; -import { MigrateFunctionsObject, MigrateFunction } from '@kbn/kibana-utils-plugin/common'; -import { mergeSavedObjectMigrationMaps } from '@kbn/core/server'; -import { isSerializedSearchSource, SerializedSearchSourceFields } from '@kbn/data-plugin/common'; -import { extractRefsFromGeoContainmentAlert } from './geo_containment/migrations'; -import { RawRule, RawRuleAction, RawRuleExecutionStatus } from '../types'; -import { getMappedParams } from '../rules_client/lib/mapped_params_utils'; - -const SIEM_APP_ID = 'securitySolution'; -const SIEM_SERVER_APP_ID = 'siem'; -const MINIMUM_SS_MIGRATION_VERSION = '8.3.0'; -export const LEGACY_LAST_MODIFIED_VERSION = 'pre-7.10.0'; -export const FILEBEAT_7X_INDICATOR_PATH = 'threatintel.indicator'; - -interface AlertLogMeta extends LogMeta { - migrations: { alertDocument: SavedObjectUnsanitizedDoc }; -} - -type AlertMigration = ( - doc: SavedObjectUnsanitizedDoc, - context: SavedObjectMigrationContext -) => SavedObjectUnsanitizedDoc; - -function createEsoMigration( - encryptedSavedObjects: EncryptedSavedObjectsPluginSetup, - isMigrationNeededPredicate: IsMigrationNeededPredicate, - migrationFunc: AlertMigration -) { - return encryptedSavedObjects.createMigration({ - isMigrationNeededPredicate, - migration: migrationFunc, - shouldMigrateIfDecryptionFails: true, // shouldMigrateIfDecryptionFails flag that applies the migration to undecrypted document if decryption fails - }); -} - -const SUPPORT_INCIDENTS_ACTION_TYPES = ['.servicenow', '.jira', '.resilient']; - -export const isAnyActionSupportIncidents = (doc: SavedObjectUnsanitizedDoc): boolean => - doc.attributes.actions.some((action) => - SUPPORT_INCIDENTS_ACTION_TYPES.includes(action.actionTypeId) - ); - -// Deprecated in 8.0 -export const isSiemSignalsRuleType = (doc: SavedObjectUnsanitizedDoc): boolean => - doc.attributes.alertTypeId === 'siem.signals'; - -export const isEsQueryRuleType = (doc: SavedObjectUnsanitizedDoc) => - doc.attributes.alertTypeId === '.es-query'; - -export const isDetectionEngineAADRuleType = (doc: SavedObjectUnsanitizedDoc): boolean => - (Object.values(ruleTypeMappings) as string[]).includes(doc.attributes.alertTypeId); - -/** - * Returns true if the alert type is that of "siem.notifications" which is a legacy notification system that was deprecated in 7.16.0 - * in favor of using the newer alerting notifications system. - * @param doc The saved object alert type document - * @returns true if this is a legacy "siem.notifications" rule, otherwise false - * @deprecated Once we are confident all rules relying on side-car actions SO's have been migrated to SO references we should remove this function - */ -export const isSecuritySolutionLegacyNotification = ( - doc: SavedObjectUnsanitizedDoc -): boolean => doc.attributes.alertTypeId === 'siem.notifications'; - -export function getMigrations( - encryptedSavedObjects: EncryptedSavedObjectsPluginSetup, - searchSourceMigrations: MigrateFunctionsObject, - isPreconfigured: (connectorId: string) => boolean -): SavedObjectMigrationMap { - const migrationWhenRBACWasIntroduced = createEsoMigration( - encryptedSavedObjects, - // migrate all documents in 7.10 in order to add the "meta" RBAC field - (doc): doc is SavedObjectUnsanitizedDoc => true, - pipeMigrations( - markAsLegacyAndChangeConsumer, - setAlertIdAsDefaultDedupkeyOnPagerDutyActions, - initializeExecutionStatus - ) - ); - - const migrationAlertUpdatedAtAndNotifyWhen = createEsoMigration( - encryptedSavedObjects, - // migrate all documents in 7.11 in order to add the "updatedAt" and "notifyWhen" fields - (doc): doc is SavedObjectUnsanitizedDoc => true, - pipeMigrations(setAlertUpdatedAtDate, setNotifyWhen) - ); - - const migrationActions7112 = createEsoMigration( - encryptedSavedObjects, - (doc): doc is SavedObjectUnsanitizedDoc => isAnyActionSupportIncidents(doc), - pipeMigrations(restructureConnectorsThatSupportIncident) - ); - - const migrationSecurityRules713 = createEsoMigration( - encryptedSavedObjects, - (doc): doc is SavedObjectUnsanitizedDoc => isSiemSignalsRuleType(doc), - pipeMigrations(removeNullsFromSecurityRules) - ); - - const migrationSecurityRules714 = createEsoMigration( - encryptedSavedObjects, - (doc): doc is SavedObjectUnsanitizedDoc => isSiemSignalsRuleType(doc), - pipeMigrations(removeNullAuthorFromSecurityRules) - ); - - const migrationSecurityRules715 = createEsoMigration( - encryptedSavedObjects, - (doc): doc is SavedObjectUnsanitizedDoc => isSiemSignalsRuleType(doc), - pipeMigrations(addExceptionListsToReferences) - ); - - const migrateRules716 = createEsoMigration( - encryptedSavedObjects, - (doc): doc is SavedObjectUnsanitizedDoc => true, - pipeMigrations( - setLegacyId, - getRemovePreconfiguredConnectorsFromReferencesFn(isPreconfigured), - addRuleIdsToLegacyNotificationReferences, - extractRefsFromGeoContainmentAlert - ) - ); - - const migrationRules800 = createEsoMigration( - encryptedSavedObjects, - (doc: SavedObjectUnsanitizedDoc): doc is SavedObjectUnsanitizedDoc => true, - pipeMigrations( - addThreatIndicatorPathToThreatMatchRules, - addSecuritySolutionAADRuleTypes, - fixInventoryThresholdGroupId - ) - ); - - const migrationRules801 = createEsoMigration( - encryptedSavedObjects, - (doc: SavedObjectUnsanitizedDoc): doc is SavedObjectUnsanitizedDoc => true, - pipeMigrations(addSecuritySolutionAADRuleTypeTags) - ); - - const migrationRules820 = createEsoMigration( - encryptedSavedObjects, - (doc: SavedObjectUnsanitizedDoc): doc is SavedObjectUnsanitizedDoc => true, - pipeMigrations(addMappedParams) - ); - - const migrationRules830 = createEsoMigration( - encryptedSavedObjects, - (doc: SavedObjectUnsanitizedDoc): doc is SavedObjectUnsanitizedDoc => true, - pipeMigrations(addSearchType, removeInternalTags, convertSnoozes) - ); - - const migrationRules841 = createEsoMigration( - encryptedSavedObjects, - (doc: SavedObjectUnsanitizedDoc): doc is SavedObjectUnsanitizedDoc => true, - pipeMigrations(removeIsSnoozedUntil) - ); - - const migrationRules850 = createEsoMigration( - encryptedSavedObjects, - (doc): doc is SavedObjectUnsanitizedDoc => isEsQueryRuleType(doc), - pipeMigrations(stripOutRuntimeFieldsInOldESQuery) - ); - - return mergeSavedObjectMigrationMaps( - { - '7.10.0': executeMigrationWithErrorHandling(migrationWhenRBACWasIntroduced, '7.10.0'), - '7.11.0': executeMigrationWithErrorHandling(migrationAlertUpdatedAtAndNotifyWhen, '7.11.0'), - '7.11.2': executeMigrationWithErrorHandling(migrationActions7112, '7.11.2'), - '7.13.0': executeMigrationWithErrorHandling(migrationSecurityRules713, '7.13.0'), - '7.14.1': executeMigrationWithErrorHandling(migrationSecurityRules714, '7.14.1'), - '7.15.0': executeMigrationWithErrorHandling(migrationSecurityRules715, '7.15.0'), - '7.16.0': executeMigrationWithErrorHandling(migrateRules716, '7.16.0'), - '8.0.0': executeMigrationWithErrorHandling(migrationRules800, '8.0.0'), - '8.0.1': executeMigrationWithErrorHandling(migrationRules801, '8.0.1'), - '8.2.0': executeMigrationWithErrorHandling(migrationRules820, '8.2.0'), - '8.3.0': executeMigrationWithErrorHandling(migrationRules830, '8.3.0'), - '8.4.1': executeMigrationWithErrorHandling(migrationRules841, '8.4.1'), - '8.5.0': executeMigrationWithErrorHandling(migrationRules850, '8.5.0'), - }, - getSearchSourceMigrations(encryptedSavedObjects, searchSourceMigrations) - ); -} - -function executeMigrationWithErrorHandling( - migrationFunc: SavedObjectMigrationFn, - version: string -) { - return (doc: SavedObjectUnsanitizedDoc, context: SavedObjectMigrationContext) => { - try { - return migrationFunc(doc, context); - } catch (ex) { - context.log.error( - `encryptedSavedObject ${version} migration failed for alert ${doc.id} with error: ${ex.message}`, - { - migrations: { - alertDocument: doc, - }, - } - ); - throw ex; - } - }; -} - -const setAlertUpdatedAtDate = ( - doc: SavedObjectUnsanitizedDoc -): SavedObjectUnsanitizedDoc => { - const updatedAt = doc.updated_at || doc.attributes.createdAt; - return { - ...doc, - attributes: { - ...doc.attributes, - updatedAt, - }, - }; -}; - -const setNotifyWhen = ( - doc: SavedObjectUnsanitizedDoc -): SavedObjectUnsanitizedDoc => { - const notifyWhen = doc.attributes.throttle ? 'onThrottleInterval' : 'onActiveAlert'; - return { - ...doc, - attributes: { - ...doc.attributes, - notifyWhen, - }, - }; -}; - -const consumersToChange: Map = new Map( - Object.entries({ - alerting: 'alerts', - metrics: 'infrastructure', - [SIEM_APP_ID]: SIEM_SERVER_APP_ID, - }) -); - -function markAsLegacyAndChangeConsumer( - doc: SavedObjectUnsanitizedDoc -): SavedObjectUnsanitizedDoc { - const { - attributes: { consumer }, - } = doc; - return { - ...doc, - attributes: { - ...doc.attributes, - consumer: consumersToChange.get(consumer) ?? consumer, - // mark any alert predating 7.10 as a legacy alert - meta: { - versionApiKeyLastmodified: LEGACY_LAST_MODIFIED_VERSION, - }, - }, - }; -} - -function setAlertIdAsDefaultDedupkeyOnPagerDutyActions( - doc: SavedObjectUnsanitizedDoc -): SavedObjectUnsanitizedDoc { - const { attributes } = doc; - return { - ...doc, - attributes: { - ...attributes, - ...(attributes.actions - ? { - actions: attributes.actions.map((action) => { - if (action.actionTypeId !== '.pagerduty' || action.params.eventAction === 'trigger') { - return action; - } - return { - ...action, - params: { - ...action.params, - dedupKey: action.params.dedupKey ?? '{{alertId}}', - }, - }; - }), - } - : {}), - }, - }; -} - -function initializeExecutionStatus( - doc: SavedObjectUnsanitizedDoc -): SavedObjectUnsanitizedDoc { - const { attributes } = doc; - return { - ...doc, - attributes: { - ...attributes, - executionStatus: { - status: 'pending', - lastExecutionDate: new Date().toISOString(), - error: null, - } as RawRuleExecutionStatus, - }, - }; -} - -function isEmptyObject(obj: {}) { - for (const attr in obj) { - if (Object.prototype.hasOwnProperty.call(obj, attr)) { - return false; - } - } - return true; -} - -function restructureConnectorsThatSupportIncident( - doc: SavedObjectUnsanitizedDoc -): SavedObjectUnsanitizedDoc { - const { actions } = doc.attributes; - const newActions = actions.reduce((acc, action) => { - if ( - ['.servicenow', '.jira', '.resilient'].includes(action.actionTypeId) && - action.params.subAction === 'pushToService' - ) { - // Future developer, we needed to do that because when we created this migration - // we forget to think about user already using 7.11.0 and having an incident attribute build the right way - // IMPORTANT -> if you change this code please do the same inside of this file - // x-pack/plugins/alerting/server/saved_objects/migrations.ts - const subActionParamsIncident = - (action.params?.subActionParams as SavedObjectAttributes)?.incident ?? null; - if (subActionParamsIncident != null && !isEmptyObject(subActionParamsIncident)) { - return [...acc, action]; - } - if (action.actionTypeId === '.servicenow') { - const { - title, - comments, - comment, - description, - severity, - urgency, - impact, - short_description: shortDescription, - } = action.params.subActionParams as { - title: string; - description?: string; - severity?: string; - urgency?: string; - impact?: string; - comment?: string; - comments?: Array<{ commentId: string; comment: string }>; - short_description?: string; - }; - return [ - ...acc, - { - ...action, - params: { - subAction: 'pushToService', - subActionParams: { - incident: { - short_description: shortDescription ?? title, - description, - severity, - urgency, - impact, - }, - comments: [ - ...(comments ?? []), - ...(comment != null ? [{ commentId: '1', comment }] : []), - ], - }, - }, - }, - ] as RawRuleAction[]; - } else if (action.actionTypeId === '.jira') { - const { title, comments, description, issueType, priority, labels, parent, summary } = - action.params.subActionParams as { - title: string; - description: string; - issueType: string; - priority?: string; - labels?: string[]; - parent?: string; - comments?: unknown[]; - summary?: string; - }; - return [ - ...acc, - { - ...action, - params: { - subAction: 'pushToService', - subActionParams: { - incident: { - summary: summary ?? title, - description, - issueType, - priority, - labels, - parent, - }, - comments, - }, - }, - }, - ] as RawRuleAction[]; - } else if (action.actionTypeId === '.resilient') { - const { title, comments, description, incidentTypes, severityCode, name } = action.params - .subActionParams as { - title: string; - description: string; - incidentTypes?: number[]; - severityCode?: number; - comments?: unknown[]; - name?: string; - }; - return [ - ...acc, - { - ...action, - params: { - subAction: 'pushToService', - subActionParams: { - incident: { - name: name ?? title, - description, - incidentTypes, - severityCode, - }, - comments, - }, - }, - }, - ] as RawRuleAction[]; - } - } - - return [...acc, action]; - }, [] as RawRuleAction[]); - - return { - ...doc, - attributes: { - ...doc.attributes, - actions: newActions, - }, - }; -} - -function convertNullToUndefined(attribute: SavedObjectAttribute) { - return attribute != null ? attribute : undefined; -} - -function removeNullsFromSecurityRules( - doc: SavedObjectUnsanitizedDoc -): SavedObjectUnsanitizedDoc { - const { - attributes: { params }, - } = doc; - return { - ...doc, - attributes: { - ...doc.attributes, - params: { - ...params, - buildingBlockType: convertNullToUndefined(params.buildingBlockType), - note: convertNullToUndefined(params.note), - index: convertNullToUndefined(params.index), - language: convertNullToUndefined(params.language), - license: convertNullToUndefined(params.license), - outputIndex: convertNullToUndefined(params.outputIndex), - savedId: convertNullToUndefined(params.savedId), - timelineId: convertNullToUndefined(params.timelineId), - timelineTitle: convertNullToUndefined(params.timelineTitle), - meta: convertNullToUndefined(params.meta), - query: convertNullToUndefined(params.query), - filters: convertNullToUndefined(params.filters), - riskScoreMapping: params.riskScoreMapping != null ? params.riskScoreMapping : [], - ruleNameOverride: convertNullToUndefined(params.ruleNameOverride), - severityMapping: params.severityMapping != null ? params.severityMapping : [], - threat: params.threat != null ? params.threat : [], - threshold: - params.threshold != null && - typeof params.threshold === 'object' && - !Array.isArray(params.threshold) - ? { - field: Array.isArray(params.threshold.field) - ? params.threshold.field - : params.threshold.field === '' || params.threshold.field == null - ? [] - : [params.threshold.field], - value: params.threshold.value, - cardinality: - params.threshold.cardinality != null ? params.threshold.cardinality : [], - } - : undefined, - timestampOverride: convertNullToUndefined(params.timestampOverride), - exceptionsList: - params.exceptionsList != null - ? params.exceptionsList - : params.exceptions_list != null - ? params.exceptions_list - : params.lists != null - ? params.lists - : [], - threatFilters: convertNullToUndefined(params.threatFilters), - machineLearningJobId: - params.machineLearningJobId == null - ? undefined - : Array.isArray(params.machineLearningJobId) - ? params.machineLearningJobId - : [params.machineLearningJobId], - }, - }, - }; -} - -/** - * The author field was introduced later and was not part of the original rules. We overlooked - * the filling in the author field as an empty array in an earlier upgrade routine from - * 'removeNullsFromSecurityRules' during the 7.13.0 upgrade. Since we don't change earlier migrations, - * but rather only move forward with the "arrow of time" we are going to upgrade and fix - * it if it is missing for anyone in 7.14.0 and above release. Earlier releases if we want to fix them, - * would have to be modified as a "7.13.1", etc... if we want to fix it there. - * @param doc The document that is not migrated and contains a "null" or "undefined" author field - * @returns The document with the author field fleshed in. - */ -function removeNullAuthorFromSecurityRules( - doc: SavedObjectUnsanitizedDoc -): SavedObjectUnsanitizedDoc { - const { - attributes: { params }, - } = doc; - return { - ...doc, - attributes: { - ...doc.attributes, - params: { - ...params, - author: params.author != null ? params.author : [], - }, - }, - }; -} - -/** - * This migrates exception list containers to saved object references on an upgrade. - * We only migrate if we find these conditions: - * - exceptionLists are an array and not null, undefined, or malformed data. - * - The exceptionList item is an object and id is a string and not null, undefined, or malformed data - * - The existing references do not already have an exceptionItem reference already found within it. - * Some of these issues could crop up during either user manual errors of modifying things, earlier migration - * issues, etc... - * @param doc The document that might have exceptionListItems to migrate - * @returns The document migrated with saved object references - */ -function addExceptionListsToReferences( - doc: SavedObjectUnsanitizedDoc -): SavedObjectUnsanitizedDoc { - const { - attributes: { - params: { exceptionsList }, - }, - references, - } = doc; - if (!Array.isArray(exceptionsList)) { - // early return if we are not an array such as being undefined or null or malformed. - return doc; - } else { - const exceptionsToTransform = removeMalformedExceptionsList(exceptionsList); - const newReferences = exceptionsToTransform.flatMap( - (exceptionItem, index) => { - const existingReferenceFound = references?.find((reference) => { - return ( - reference.id === exceptionItem.id && - ((reference.type === 'exception-list' && exceptionItem.namespace_type === 'single') || - (reference.type === 'exception-list-agnostic' && - exceptionItem.namespace_type === 'agnostic')) - ); - }); - if (existingReferenceFound) { - // skip if the reference already exists for some uncommon reason so we do not add an additional one. - // This enables us to be idempotent and you can run this migration multiple times and get the same output. - return []; - } else { - return [ - { - name: `param:exceptionsList_${index}`, - id: String(exceptionItem.id), - type: - exceptionItem.namespace_type === 'agnostic' - ? 'exception-list-agnostic' - : 'exception-list', - }, - ]; - } - } - ); - if (references == null && newReferences.length === 0) { - // Avoid adding an empty references array if the existing saved object never had one to begin with - return doc; - } else { - return { ...doc, references: [...(references ?? []), ...newReferences] }; - } - } -} - -/** - * This will do a flatMap reduce where we only return exceptionsLists and their items if: - * - exceptionLists are an array and not null, undefined, or malformed data. - * - The exceptionList item is an object and id is a string and not null, undefined, or malformed data - * - * Some of these issues could crop up during either user manual errors of modifying things, earlier migration - * issues, etc... - * @param exceptionsList The list of exceptions - * @returns The exception lists if they are a valid enough shape - */ -function removeMalformedExceptionsList( - exceptionsList: SavedObjectAttribute -): SavedObjectAttributes[] { - if (!Array.isArray(exceptionsList)) { - // early return if we are not an array such as being undefined or null or malformed. - return []; - } else { - return exceptionsList.flatMap((exceptionItem) => { - if (!(exceptionItem instanceof Object) || !isString(exceptionItem.id)) { - // return early if we are not an object such as being undefined or null or malformed - // or the exceptionItem.id is not a string from being malformed - return []; - } else { - return [exceptionItem]; - } - }); - } -} - -/** - * This migrates rule_id's within the legacy siem.notification to saved object references on an upgrade. - * We only migrate if we find these conditions: - * - ruleAlertId is a string and not null, undefined, or malformed data. - * - The existing references do not already have a ruleAlertId found within it. - * Some of these issues could crop up during either user manual errors of modifying things, earlier migration - * issues, etc... so we are safer to check them as possibilities - * @deprecated Once we are confident all rules relying on side-car actions SO's have been migrated to SO references we should remove this function - * @param doc The document that might have "ruleAlertId" to migrate into the references - * @returns The document migrated with saved object references - */ -function addRuleIdsToLegacyNotificationReferences( - doc: SavedObjectUnsanitizedDoc -): SavedObjectUnsanitizedDoc { - const { - attributes: { - params: { ruleAlertId }, - }, - references, - } = doc; - if (!isSecuritySolutionLegacyNotification(doc) || !isString(ruleAlertId)) { - // early return if we are not a string or if we are not a security solution notification saved object. - return doc; - } else { - const existingReferences = references ?? []; - const existingReferenceFound = existingReferences.find((reference) => { - return reference.id === ruleAlertId && reference.type === 'alert'; - }); - if (existingReferenceFound) { - // skip this if the references already exists for some uncommon reason so we do not add an additional one. - return doc; - } else { - const savedObjectReference: SavedObjectReference = { - id: ruleAlertId, - name: 'param:alert_0', - type: 'alert', - }; - const newReferences = [...existingReferences, savedObjectReference]; - return { ...doc, references: newReferences }; - } - } -} - -function setLegacyId(doc: SavedObjectUnsanitizedDoc): SavedObjectUnsanitizedDoc { - const { id } = doc; - return { - ...doc, - attributes: { - ...doc.attributes, - legacyId: id, - }, - }; -} - -function addSecuritySolutionAADRuleTypes( - doc: SavedObjectUnsanitizedDoc -): SavedObjectUnsanitizedDoc { - const ruleType = doc.attributes.params.type; - return isSiemSignalsRuleType(doc) && isRuleType(ruleType) - ? { - ...doc, - attributes: { - ...doc.attributes, - alertTypeId: ruleTypeMappings[ruleType], - enabled: false, - params: { - ...doc.attributes.params, - outputIndex: '', - }, - }, - } - : doc; -} - -function addSearchType(doc: SavedObjectUnsanitizedDoc) { - const searchType = doc.attributes.params.searchType; - - return isEsQueryRuleType(doc) && !searchType - ? { - ...doc, - attributes: { - ...doc.attributes, - params: { - ...doc.attributes.params, - searchType: 'esQuery', - }, - }, - } - : doc; -} - -function addSecuritySolutionAADRuleTypeTags( - doc: SavedObjectUnsanitizedDoc -): SavedObjectUnsanitizedDoc { - const ruleType = doc.attributes.params.type; - return isDetectionEngineAADRuleType(doc) && isRuleType(ruleType) - ? { - ...doc, - attributes: { - ...doc.attributes, - // If the rule is disabled at this point, then the rule has not been re-enabled after - // running the 8.0.0 migrations. If `doc.attributes.scheduledTaskId` exists, then the - // rule was enabled prior to running the migration. Thus we know we should add the - // tag to indicate it was auto-disabled. - tags: - !doc.attributes.enabled && doc.attributes.scheduledTaskId - ? [...(doc.attributes.tags ?? []), 'auto_disabled_8.0'] - : doc.attributes.tags ?? [], - }, - } - : doc; -} - -function stripOutRuntimeFieldsInOldESQuery( - doc: SavedObjectUnsanitizedDoc, - context: SavedObjectMigrationContext -): SavedObjectUnsanitizedDoc { - const isESDSLrule = - isEsQueryRuleType(doc) && !isSerializedSearchSource(doc.attributes.params.searchConfiguration); - - if (isESDSLrule) { - try { - const parsedQuery = JSON.parse(doc.attributes.params.esQuery as string); - // parsing and restringifying will cause us to lose the formatting so we only do so if this rule has - // fields other than `query` which is the only valid field at this stage - const hasFieldsOtherThanQuery = Object.keys(parsedQuery).some((key) => key !== 'query'); - return hasFieldsOtherThanQuery - ? { - ...doc, - attributes: { - ...doc.attributes, - params: { - ...doc.attributes.params, - esQuery: JSON.stringify(pick(parsedQuery, 'query'), null, 4), - }, - }, - } - : doc; - } catch (err) { - // Instead of failing the upgrade when an unparsable rule is encountered, we log that the rule caouldn't be migrated and - // as a result legacy parameters might cause the rule to behave differently if it is, in fact, still running at all - context.log.error( - `unable to migrate and remove legacy runtime fields in rule ${doc.id} due to invalid query: "${doc.attributes.params.esQuery}" - query must be JSON`, - { - migrations: { - alertDocument: doc, - }, - } - ); - } - } - return doc; -} - -function addThreatIndicatorPathToThreatMatchRules( - doc: SavedObjectUnsanitizedDoc -): SavedObjectUnsanitizedDoc { - return isSiemSignalsRuleType(doc) && - doc.attributes.params?.type === 'threat_match' && - !doc.attributes.params.threatIndicatorPath - ? { - ...doc, - attributes: { - ...doc.attributes, - params: { - ...doc.attributes.params, - threatIndicatorPath: FILEBEAT_7X_INDICATOR_PATH, - }, - }, - } - : doc; -} - -function getRemovePreconfiguredConnectorsFromReferencesFn( - isPreconfigured: (connectorId: string) => boolean -) { - return (doc: SavedObjectUnsanitizedDoc) => { - return removePreconfiguredConnectorsFromReferences(doc, isPreconfigured); - }; -} - -function removePreconfiguredConnectorsFromReferences( - doc: SavedObjectUnsanitizedDoc, - isPreconfigured: (connectorId: string) => boolean -): SavedObjectUnsanitizedDoc { - const { - attributes: { actions }, - references, - } = doc; - - // Look for connector references - const connectorReferences = (references ?? []).filter((ref: SavedObjectReference) => - ref.name.startsWith('action_') - ); - if (connectorReferences.length > 0) { - const restReferences = (references ?? []).filter( - (ref: SavedObjectReference) => !ref.name.startsWith('action_') - ); - - const updatedConnectorReferences: SavedObjectReference[] = []; - const updatedActions: RawRule['actions'] = []; - - // For each connector reference, check if connector is preconfigured - // If yes, we need to remove from the references array and update - // the corresponding action so it directly references the preconfigured connector id - connectorReferences.forEach((connectorRef: SavedObjectReference) => { - // Look for the corresponding entry in the actions array - const correspondingAction = getCorrespondingAction(actions, connectorRef.name); - if (correspondingAction) { - if (isPreconfigured(connectorRef.id)) { - updatedActions.push({ - ...correspondingAction, - actionRef: `preconfigured:${connectorRef.id}`, - }); - } else { - updatedActions.push(correspondingAction); - updatedConnectorReferences.push(connectorRef); - } - } else { - // Couldn't find the matching action, leave as is - updatedConnectorReferences.push(connectorRef); - } - }); - - return { - ...doc, - attributes: { - ...doc.attributes, - actions: [...updatedActions], - }, - references: [...updatedConnectorReferences, ...restReferences], - }; - } - return doc; -} - -// This fixes an issue whereby metrics.alert.inventory.threshold rules had the -// group for actions incorrectly spelt as metrics.invenotry_threshold.fired vs metrics.inventory_threshold.fired -function fixInventoryThresholdGroupId( - doc: SavedObjectUnsanitizedDoc -): SavedObjectUnsanitizedDoc { - if (doc.attributes.alertTypeId === 'metrics.alert.inventory.threshold') { - const { - attributes: { actions }, - } = doc; - - const updatedActions = actions - ? actions.map((action) => { - // Wrong spelling - if (action.group === 'metrics.invenotry_threshold.fired') { - return { - ...action, - group: 'metrics.inventory_threshold.fired', - }; - } else { - return action; - } - }) - : []; - - return { - ...doc, - attributes: { - ...doc.attributes, - actions: updatedActions, - }, - }; - } else { - return doc; - } -} - -function addMappedParams( - doc: SavedObjectUnsanitizedDoc -): SavedObjectUnsanitizedDoc { - const { - attributes: { params }, - } = doc; - - const mappedParams = getMappedParams(params); - - if (Object.keys(mappedParams).length) { - return { - ...doc, - attributes: { - ...doc.attributes, - mapped_params: mappedParams, - }, - }; - } - - return doc; -} - -function convertSnoozes( - doc: SavedObjectUnsanitizedDoc -): SavedObjectUnsanitizedDoc { - const { - attributes: { snoozeEndTime }, - } = doc; - - return { - ...doc, - attributes: { - ...(omit(doc.attributes, ['snoozeEndTime']) as RawRule), - snoozeSchedule: snoozeEndTime - ? [ - { - duration: Date.parse(snoozeEndTime as string) - Date.now(), - rRule: { - dtstart: new Date().toISOString(), - tzid: moment.tz.guess(), - count: 1, - }, - }, - ] - : [], - }, - }; -} - -function getCorrespondingAction( - actions: SavedObjectAttribute, - connectorRef: string -): RawRuleAction | null { - if (!Array.isArray(actions)) { - return null; - } else { - return actions.find( - (action) => (action as RawRuleAction)?.actionRef === connectorRef - ) as RawRuleAction; - } -} -/** - * removes internal tags(starts with '__internal') from Security Solution rules - * @param doc rule to be migrated - * @returns migrated rule if it's Security Solution rule or unchanged if not - */ -function removeInternalTags( - doc: SavedObjectUnsanitizedDoc -): SavedObjectUnsanitizedDoc { - if (!isDetectionEngineAADRuleType(doc)) { - return doc; - } - - const { - attributes: { tags }, - } = doc; - - const filteredTags = (tags ?? []).filter((tag) => !tag.startsWith('__internal_')); - - return { - ...doc, - attributes: { - ...doc.attributes, - tags: filteredTags, - }, - }; -} - -function pipeMigrations(...migrations: AlertMigration[]): AlertMigration { - return (doc: SavedObjectUnsanitizedDoc, context: SavedObjectMigrationContext) => - migrations.reduce((migratedDoc, nextMigration) => nextMigration(migratedDoc, context), doc); -} - -function mapSearchSourceMigrationFunc( - migrateSerializedSearchSourceFields: MigrateFunction -): MigrateFunction { - return (doc) => { - const _doc = doc as { attributes: RawRule }; - - const serializedSearchSource = _doc.attributes.params.searchConfiguration; - - if (isSerializedSearchSource(serializedSearchSource)) { - return { - ..._doc, - attributes: { - ..._doc.attributes, - params: { - ..._doc.attributes.params, - searchConfiguration: migrateSerializedSearchSourceFields(serializedSearchSource), - }, - }, - }; - } - return _doc; - }; -} - -/** - * This creates a migration map that applies search source migrations to legacy es query rules. - * It doesn't modify existing migrations. The following migrations will occur at minimum version of 8.3+. - */ -function getSearchSourceMigrations( - encryptedSavedObjects: EncryptedSavedObjectsPluginSetup, - searchSourceMigrations: MigrateFunctionsObject -) { - const filteredMigrations: SavedObjectMigrationMap = {}; - for (const versionKey in searchSourceMigrations) { - if (gte(versionKey, MINIMUM_SS_MIGRATION_VERSION)) { - const migrateSearchSource = mapSearchSourceMigrationFunc( - searchSourceMigrations[versionKey] - ) as unknown as AlertMigration; - - filteredMigrations[versionKey] = executeMigrationWithErrorHandling( - createEsoMigration( - encryptedSavedObjects, - (doc: SavedObjectUnsanitizedDoc): doc is SavedObjectUnsanitizedDoc => - isEsQueryRuleType(doc), - pipeMigrations(migrateSearchSource) - ), - versionKey - ); - } - } - return filteredMigrations; -} - -function removeIsSnoozedUntil( - doc: SavedObjectUnsanitizedDoc -): SavedObjectUnsanitizedDoc { - return { - ...doc, - attributes: { - ...(omit(doc.attributes, ['isSnoozedUntil']) as RawRule), - }, - }; -} diff --git a/x-pack/plugins/alerting/server/saved_objects/migrations/7.10/index.ts b/x-pack/plugins/alerting/server/saved_objects/migrations/7.10/index.ts new file mode 100644 index 0000000000000..b432ff01618df --- /dev/null +++ b/x-pack/plugins/alerting/server/saved_objects/migrations/7.10/index.ts @@ -0,0 +1,96 @@ +/* + * 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 { SavedObjectUnsanitizedDoc } from '@kbn/core-saved-objects-server'; +import { EncryptedSavedObjectsPluginSetup } from '@kbn/encrypted-saved-objects-plugin/server'; +import { RawRule, RawRuleExecutionStatus } from '../../../types'; +import { LEGACY_LAST_MODIFIED_VERSION, SIEM_APP_ID, SIEM_SERVER_APP_ID } from '../constants'; +import { createEsoMigration, pipeMigrations } from '../utils'; + +const consumersToChange: Map = new Map( + Object.entries({ + alerting: 'alerts', + metrics: 'infrastructure', + [SIEM_APP_ID]: SIEM_SERVER_APP_ID, + }) +); + +function markAsLegacyAndChangeConsumer( + doc: SavedObjectUnsanitizedDoc +): SavedObjectUnsanitizedDoc { + const { + attributes: { consumer }, + } = doc; + return { + ...doc, + attributes: { + ...doc.attributes, + consumer: consumersToChange.get(consumer) ?? consumer, + // mark any alert predating 7.10 as a legacy alert + meta: { + versionApiKeyLastmodified: LEGACY_LAST_MODIFIED_VERSION, + }, + }, + }; +} + +function setAlertIdAsDefaultDedupkeyOnPagerDutyActions( + doc: SavedObjectUnsanitizedDoc +): SavedObjectUnsanitizedDoc { + const { attributes } = doc; + return { + ...doc, + attributes: { + ...attributes, + ...(attributes.actions + ? { + actions: attributes.actions.map((action) => { + if (action.actionTypeId !== '.pagerduty' || action.params.eventAction === 'trigger') { + return action; + } + return { + ...action, + params: { + ...action.params, + dedupKey: action.params.dedupKey ?? '{{alertId}}', + }, + }; + }), + } + : {}), + }, + }; +} + +function initializeExecutionStatus( + doc: SavedObjectUnsanitizedDoc +): SavedObjectUnsanitizedDoc { + const { attributes } = doc; + return { + ...doc, + attributes: { + ...attributes, + executionStatus: { + status: 'pending', + lastExecutionDate: new Date().toISOString(), + error: null, + } as RawRuleExecutionStatus, + }, + }; +} + +export const getMigrations7100 = (encryptedSavedObjects: EncryptedSavedObjectsPluginSetup) => + createEsoMigration( + encryptedSavedObjects, + // migrate all documents in 7.10 in order to add the "meta" RBAC field + (doc): doc is SavedObjectUnsanitizedDoc => true, + pipeMigrations( + markAsLegacyAndChangeConsumer, + setAlertIdAsDefaultDedupkeyOnPagerDutyActions, + initializeExecutionStatus + ) + ); diff --git a/x-pack/plugins/alerting/server/saved_objects/migrations/7.11/index.ts b/x-pack/plugins/alerting/server/saved_objects/migrations/7.11/index.ts new file mode 100644 index 0000000000000..186b20679c00d --- /dev/null +++ b/x-pack/plugins/alerting/server/saved_objects/migrations/7.11/index.ts @@ -0,0 +1,200 @@ +/* + * 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 { SavedObjectAttributes } from '@kbn/core-saved-objects-common'; +import { SavedObjectUnsanitizedDoc } from '@kbn/core-saved-objects-server'; +import { EncryptedSavedObjectsPluginSetup } from '@kbn/encrypted-saved-objects-plugin/server'; +import { RawRule, RawRuleAction } from '../../../types'; +import { createEsoMigration, pipeMigrations } from '../utils'; + +const SUPPORT_INCIDENTS_ACTION_TYPES = ['.servicenow', '.jira', '.resilient']; +export const isAnyActionSupportIncidents = (doc: SavedObjectUnsanitizedDoc): boolean => + doc.attributes.actions.some((action) => + SUPPORT_INCIDENTS_ACTION_TYPES.includes(action.actionTypeId) + ); + +function isEmptyObject(obj: {}) { + for (const attr in obj) { + if (Object.prototype.hasOwnProperty.call(obj, attr)) { + return false; + } + } + return true; +} + +function setAlertUpdatedAtDate( + doc: SavedObjectUnsanitizedDoc +): SavedObjectUnsanitizedDoc { + const updatedAt = doc.updated_at || doc.attributes.createdAt; + return { + ...doc, + attributes: { + ...doc.attributes, + updatedAt, + }, + }; +} + +function setNotifyWhen( + doc: SavedObjectUnsanitizedDoc +): SavedObjectUnsanitizedDoc { + const notifyWhen = doc.attributes.throttle ? 'onThrottleInterval' : 'onActiveAlert'; + return { + ...doc, + attributes: { + ...doc.attributes, + notifyWhen, + }, + }; +} + +function restructureConnectorsThatSupportIncident( + doc: SavedObjectUnsanitizedDoc +): SavedObjectUnsanitizedDoc { + const { actions } = doc.attributes; + const newActions = actions.reduce((acc, action) => { + if ( + ['.servicenow', '.jira', '.resilient'].includes(action.actionTypeId) && + action.params.subAction === 'pushToService' + ) { + // Future developer, we needed to do that because when we created this migration + // we forget to think about user already using 7.11.0 and having an incident attribute build the right way + const subActionParamsIncident = + (action.params?.subActionParams as SavedObjectAttributes)?.incident ?? null; + if (subActionParamsIncident != null && !isEmptyObject(subActionParamsIncident)) { + return [...acc, action]; + } + if (action.actionTypeId === '.servicenow') { + const { + title, + comments, + comment, + description, + severity, + urgency, + impact, + short_description: shortDescription, + } = action.params.subActionParams as { + title: string; + description?: string; + severity?: string; + urgency?: string; + impact?: string; + comment?: string; + comments?: Array<{ commentId: string; comment: string }>; + short_description?: string; + }; + return [ + ...acc, + { + ...action, + params: { + subAction: 'pushToService', + subActionParams: { + incident: { + short_description: shortDescription ?? title, + description, + severity, + urgency, + impact, + }, + comments: [ + ...(comments ?? []), + ...(comment != null ? [{ commentId: '1', comment }] : []), + ], + }, + }, + }, + ] as RawRuleAction[]; + } else if (action.actionTypeId === '.jira') { + const { title, comments, description, issueType, priority, labels, parent, summary } = + action.params.subActionParams as { + title: string; + description: string; + issueType: string; + priority?: string; + labels?: string[]; + parent?: string; + comments?: unknown[]; + summary?: string; + }; + return [ + ...acc, + { + ...action, + params: { + subAction: 'pushToService', + subActionParams: { + incident: { + summary: summary ?? title, + description, + issueType, + priority, + labels, + parent, + }, + comments, + }, + }, + }, + ] as RawRuleAction[]; + } else if (action.actionTypeId === '.resilient') { + const { title, comments, description, incidentTypes, severityCode, name } = action.params + .subActionParams as { + title: string; + description: string; + incidentTypes?: number[]; + severityCode?: number; + comments?: unknown[]; + name?: string; + }; + return [ + ...acc, + { + ...action, + params: { + subAction: 'pushToService', + subActionParams: { + incident: { + name: name ?? title, + description, + incidentTypes, + severityCode, + }, + comments, + }, + }, + }, + ] as RawRuleAction[]; + } + } + + return [...acc, action]; + }, [] as RawRuleAction[]); + + return { + ...doc, + attributes: { + ...doc.attributes, + actions: newActions, + }, + }; +} + +export const getMigrations7110 = (encryptedSavedObjects: EncryptedSavedObjectsPluginSetup) => + createEsoMigration( + encryptedSavedObjects, + (doc): doc is SavedObjectUnsanitizedDoc => true, + pipeMigrations(setAlertUpdatedAtDate, setNotifyWhen) + ); + +export const getMigrations7112 = (encryptedSavedObjects: EncryptedSavedObjectsPluginSetup) => + createEsoMigration( + encryptedSavedObjects, + (doc): doc is SavedObjectUnsanitizedDoc => isAnyActionSupportIncidents(doc), + pipeMigrations(restructureConnectorsThatSupportIncident) + ); diff --git a/x-pack/plugins/alerting/server/saved_objects/migrations/7.13/index.ts b/x-pack/plugins/alerting/server/saved_objects/migrations/7.13/index.ts new file mode 100644 index 0000000000000..67b595531dfdb --- /dev/null +++ b/x-pack/plugins/alerting/server/saved_objects/migrations/7.13/index.ts @@ -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 { SavedObjectAttribute } from '@kbn/core-saved-objects-common'; +import { SavedObjectUnsanitizedDoc } from '@kbn/core-saved-objects-server'; +import { EncryptedSavedObjectsPluginSetup } from '@kbn/encrypted-saved-objects-plugin/server'; +import { RawRule } from '../../../types'; +import { createEsoMigration, isSiemSignalsRuleType, pipeMigrations } from '../utils'; + +function convertNullToUndefined(attribute: SavedObjectAttribute) { + return attribute != null ? attribute : undefined; +} + +function removeNullsFromSecurityRules( + doc: SavedObjectUnsanitizedDoc +): SavedObjectUnsanitizedDoc { + const { + attributes: { params }, + } = doc; + return { + ...doc, + attributes: { + ...doc.attributes, + params: { + ...params, + buildingBlockType: convertNullToUndefined(params.buildingBlockType), + note: convertNullToUndefined(params.note), + index: convertNullToUndefined(params.index), + language: convertNullToUndefined(params.language), + license: convertNullToUndefined(params.license), + outputIndex: convertNullToUndefined(params.outputIndex), + savedId: convertNullToUndefined(params.savedId), + timelineId: convertNullToUndefined(params.timelineId), + timelineTitle: convertNullToUndefined(params.timelineTitle), + meta: convertNullToUndefined(params.meta), + query: convertNullToUndefined(params.query), + filters: convertNullToUndefined(params.filters), + riskScoreMapping: params.riskScoreMapping != null ? params.riskScoreMapping : [], + ruleNameOverride: convertNullToUndefined(params.ruleNameOverride), + severityMapping: params.severityMapping != null ? params.severityMapping : [], + threat: params.threat != null ? params.threat : [], + threshold: + params.threshold != null && + typeof params.threshold === 'object' && + !Array.isArray(params.threshold) + ? { + field: Array.isArray(params.threshold.field) + ? params.threshold.field + : params.threshold.field === '' || params.threshold.field == null + ? [] + : [params.threshold.field], + value: params.threshold.value, + cardinality: + params.threshold.cardinality != null ? params.threshold.cardinality : [], + } + : undefined, + timestampOverride: convertNullToUndefined(params.timestampOverride), + exceptionsList: + params.exceptionsList != null + ? params.exceptionsList + : params.exceptions_list != null + ? params.exceptions_list + : params.lists != null + ? params.lists + : [], + threatFilters: convertNullToUndefined(params.threatFilters), + machineLearningJobId: + params.machineLearningJobId == null + ? undefined + : Array.isArray(params.machineLearningJobId) + ? params.machineLearningJobId + : [params.machineLearningJobId], + }, + }, + }; +} + +export const getMigrations7130 = (encryptedSavedObjects: EncryptedSavedObjectsPluginSetup) => + createEsoMigration( + encryptedSavedObjects, + (doc): doc is SavedObjectUnsanitizedDoc => isSiemSignalsRuleType(doc), + pipeMigrations(removeNullsFromSecurityRules) + ); diff --git a/x-pack/plugins/alerting/server/saved_objects/migrations/7.14/index.ts b/x-pack/plugins/alerting/server/saved_objects/migrations/7.14/index.ts new file mode 100644 index 0000000000000..8a4aa555127ce --- /dev/null +++ b/x-pack/plugins/alerting/server/saved_objects/migrations/7.14/index.ts @@ -0,0 +1,46 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { SavedObjectUnsanitizedDoc } from '@kbn/core-saved-objects-server'; +import { EncryptedSavedObjectsPluginSetup } from '@kbn/encrypted-saved-objects-plugin/server'; +import { RawRule } from '../../../types'; +import { createEsoMigration, isSiemSignalsRuleType, pipeMigrations } from '../utils'; + +/** + * The author field was introduced later and was not part of the original rules. We overlooked + * the filling in the author field as an empty array in an earlier upgrade routine from + * 'removeNullsFromSecurityRules' during the 7.13.0 upgrade. Since we don't change earlier migrations, + * but rather only move forward with the "arrow of time" we are going to upgrade and fix + * it if it is missing for anyone in 7.14.0 and above release. Earlier releases if we want to fix them, + * would have to be modified as a "7.13.1", etc... if we want to fix it there. + * @param doc The document that is not migrated and contains a "null" or "undefined" author field + * @returns The document with the author field fleshed in. + */ +function removeNullAuthorFromSecurityRules( + doc: SavedObjectUnsanitizedDoc +): SavedObjectUnsanitizedDoc { + const { + attributes: { params }, + } = doc; + return { + ...doc, + attributes: { + ...doc.attributes, + params: { + ...params, + author: params.author != null ? params.author : [], + }, + }, + }; +} + +export const getMigrations7140 = (encryptedSavedObjects: EncryptedSavedObjectsPluginSetup) => + createEsoMigration( + encryptedSavedObjects, + (doc): doc is SavedObjectUnsanitizedDoc => isSiemSignalsRuleType(doc), + pipeMigrations(removeNullAuthorFromSecurityRules) + ); diff --git a/x-pack/plugins/alerting/server/saved_objects/migrations/7.15/index.ts b/x-pack/plugins/alerting/server/saved_objects/migrations/7.15/index.ts new file mode 100644 index 0000000000000..a7b90ab347a71 --- /dev/null +++ b/x-pack/plugins/alerting/server/saved_objects/migrations/7.15/index.ts @@ -0,0 +1,115 @@ +/* + * 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 { + SavedObjectAttribute, + SavedObjectAttributes, + SavedObjectReference, +} from '@kbn/core-saved-objects-common'; +import { SavedObjectUnsanitizedDoc } from '@kbn/core-saved-objects-server'; +import { EncryptedSavedObjectsPluginSetup } from '@kbn/encrypted-saved-objects-plugin/server'; +import { isString } from 'lodash/fp'; +import { RawRule } from '../../../types'; +import { createEsoMigration, isSiemSignalsRuleType, pipeMigrations } from '../utils'; + +/** + * This will do a flatMap reduce where we only return exceptionsLists and their items if: + * - exceptionLists are an array and not null, undefined, or malformed data. + * - The exceptionList item is an object and id is a string and not null, undefined, or malformed data + * + * Some of these issues could crop up during either user manual errors of modifying things, earlier migration + * issues, etc... + * @param exceptionsList The list of exceptions + * @returns The exception lists if they are a valid enough shape + */ +function removeMalformedExceptionsList( + exceptionsList: SavedObjectAttribute +): SavedObjectAttributes[] { + if (!Array.isArray(exceptionsList)) { + // early return if we are not an array such as being undefined or null or malformed. + return []; + } else { + return exceptionsList.flatMap((exceptionItem) => { + if (!(exceptionItem instanceof Object) || !isString(exceptionItem.id)) { + // return early if we are not an object such as being undefined or null or malformed + // or the exceptionItem.id is not a string from being malformed + return []; + } else { + return [exceptionItem]; + } + }); + } +} + +/** + * This migrates exception list containers to saved object references on an upgrade. + * We only migrate if we find these conditions: + * - exceptionLists are an array and not null, undefined, or malformed data. + * - The exceptionList item is an object and id is a string and not null, undefined, or malformed data + * - The existing references do not already have an exceptionItem reference already found within it. + * Some of these issues could crop up during either user manual errors of modifying things, earlier migration + * issues, etc... + * @param doc The document that might have exceptionListItems to migrate + * @returns The document migrated with saved object references + */ +function addExceptionListsToReferences( + doc: SavedObjectUnsanitizedDoc +): SavedObjectUnsanitizedDoc { + const { + attributes: { + params: { exceptionsList }, + }, + references, + } = doc; + if (!Array.isArray(exceptionsList)) { + // early return if we are not an array such as being undefined or null or malformed. + return doc; + } else { + const exceptionsToTransform = removeMalformedExceptionsList(exceptionsList); + const newReferences = exceptionsToTransform.flatMap( + (exceptionItem, index) => { + const existingReferenceFound = references?.find((reference) => { + return ( + reference.id === exceptionItem.id && + ((reference.type === 'exception-list' && exceptionItem.namespace_type === 'single') || + (reference.type === 'exception-list-agnostic' && + exceptionItem.namespace_type === 'agnostic')) + ); + }); + if (existingReferenceFound) { + // skip if the reference already exists for some uncommon reason so we do not add an additional one. + // This enables us to be idempotent and you can run this migration multiple times and get the same output. + return []; + } else { + return [ + { + name: `param:exceptionsList_${index}`, + id: String(exceptionItem.id), + type: + exceptionItem.namespace_type === 'agnostic' + ? 'exception-list-agnostic' + : 'exception-list', + }, + ]; + } + } + ); + if (references == null && newReferences.length === 0) { + // Avoid adding an empty references array if the existing saved object never had one to begin with + return doc; + } else { + return { ...doc, references: [...(references ?? []), ...newReferences] }; + } + } +} + +export const getMigrations7150 = (encryptedSavedObjects: EncryptedSavedObjectsPluginSetup) => + createEsoMigration( + encryptedSavedObjects, + (doc): doc is SavedObjectUnsanitizedDoc => isSiemSignalsRuleType(doc), + pipeMigrations(addExceptionListsToReferences) + ); diff --git a/x-pack/plugins/alerting/server/saved_objects/migrations/7.16/index.ts b/x-pack/plugins/alerting/server/saved_objects/migrations/7.16/index.ts new file mode 100644 index 0000000000000..35aded8311803 --- /dev/null +++ b/x-pack/plugins/alerting/server/saved_objects/migrations/7.16/index.ts @@ -0,0 +1,159 @@ +/* + * 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 { SavedObjectAttribute, SavedObjectReference } from '@kbn/core-saved-objects-common'; +import { SavedObjectUnsanitizedDoc } from '@kbn/core-saved-objects-server'; +import { EncryptedSavedObjectsPluginSetup } from '@kbn/encrypted-saved-objects-plugin/server'; +import { isString } from 'lodash/fp'; +import { RawRule, RawRuleAction } from '../../../types'; +import { extractRefsFromGeoContainmentAlert } from '../../geo_containment/migrations'; +import { createEsoMigration, isSecuritySolutionLegacyNotification, pipeMigrations } from '../utils'; + +function setLegacyId(doc: SavedObjectUnsanitizedDoc): SavedObjectUnsanitizedDoc { + const { id } = doc; + return { + ...doc, + attributes: { + ...doc.attributes, + legacyId: id, + }, + }; +} + +function getRemovePreconfiguredConnectorsFromReferencesFn( + isPreconfigured: (connectorId: string) => boolean +) { + return (doc: SavedObjectUnsanitizedDoc) => { + return removePreconfiguredConnectorsFromReferences(doc, isPreconfigured); + }; +} + +function getCorrespondingAction( + actions: SavedObjectAttribute, + connectorRef: string +): RawRuleAction | null { + if (!Array.isArray(actions)) { + return null; + } else { + return actions.find( + (action) => (action as RawRuleAction)?.actionRef === connectorRef + ) as RawRuleAction; + } +} + +function removePreconfiguredConnectorsFromReferences( + doc: SavedObjectUnsanitizedDoc, + isPreconfigured: (connectorId: string) => boolean +): SavedObjectUnsanitizedDoc { + const { + attributes: { actions }, + references, + } = doc; + + // Look for connector references + const connectorReferences = (references ?? []).filter((ref: SavedObjectReference) => + ref.name.startsWith('action_') + ); + if (connectorReferences.length > 0) { + const restReferences = (references ?? []).filter( + (ref: SavedObjectReference) => !ref.name.startsWith('action_') + ); + + const updatedConnectorReferences: SavedObjectReference[] = []; + const updatedActions: RawRule['actions'] = []; + + // For each connector reference, check if connector is preconfigured + // If yes, we need to remove from the references array and update + // the corresponding action so it directly references the preconfigured connector id + connectorReferences.forEach((connectorRef: SavedObjectReference) => { + // Look for the corresponding entry in the actions array + const correspondingAction = getCorrespondingAction(actions, connectorRef.name); + if (correspondingAction) { + if (isPreconfigured(connectorRef.id)) { + updatedActions.push({ + ...correspondingAction, + actionRef: `preconfigured:${connectorRef.id}`, + }); + } else { + updatedActions.push(correspondingAction); + updatedConnectorReferences.push(connectorRef); + } + } else { + // Couldn't find the matching action, leave as is + updatedConnectorReferences.push(connectorRef); + } + }); + + return { + ...doc, + attributes: { + ...doc.attributes, + actions: [...updatedActions], + }, + references: [...updatedConnectorReferences, ...restReferences], + }; + } + return doc; +} + +/** + * This migrates rule_id's within the legacy siem.notification to saved object references on an upgrade. + * We only migrate if we find these conditions: + * - ruleAlertId is a string and not null, undefined, or malformed data. + * - The existing references do not already have a ruleAlertId found within it. + * Some of these issues could crop up during either user manual errors of modifying things, earlier migration + * issues, etc... so we are safer to check them as possibilities + * @deprecated Once we are confident all rules relying on side-car actions SO's have been migrated to SO references we should remove this function + * @param doc The document that might have "ruleAlertId" to migrate into the references + * @returns The document migrated with saved object references + */ +function addRuleIdsToLegacyNotificationReferences( + doc: SavedObjectUnsanitizedDoc +): SavedObjectUnsanitizedDoc { + const { + attributes: { + params: { ruleAlertId }, + }, + references, + } = doc; + if (!isSecuritySolutionLegacyNotification(doc) || !isString(ruleAlertId)) { + // early return if we are not a string or if we are not a security solution notification saved object. + return doc; + } else { + const existingReferences = references ?? []; + const existingReferenceFound = existingReferences.find((reference) => { + return reference.id === ruleAlertId && reference.type === 'alert'; + }); + if (existingReferenceFound) { + // skip this if the references already exists for some uncommon reason so we do not add an additional one. + return doc; + } else { + const savedObjectReference: SavedObjectReference = { + id: ruleAlertId, + name: 'param:alert_0', + type: 'alert', + }; + const newReferences = [...existingReferences, savedObjectReference]; + return { ...doc, references: newReferences }; + } + } +} + +export const getMigrations7160 = ( + encryptedSavedObjects: EncryptedSavedObjectsPluginSetup, + isPreconfigured: (connectorId: string) => boolean +) => + createEsoMigration( + encryptedSavedObjects, + (doc): doc is SavedObjectUnsanitizedDoc => true, + pipeMigrations( + setLegacyId, + getRemovePreconfiguredConnectorsFromReferencesFn(isPreconfigured), + addRuleIdsToLegacyNotificationReferences, + extractRefsFromGeoContainmentAlert + ) + ); diff --git a/x-pack/plugins/alerting/server/saved_objects/migrations/8.0/index.ts b/x-pack/plugins/alerting/server/saved_objects/migrations/8.0/index.ts new file mode 100644 index 0000000000000..5d8efd4585af7 --- /dev/null +++ b/x-pack/plugins/alerting/server/saved_objects/migrations/8.0/index.ts @@ -0,0 +1,133 @@ +/* + * 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 { SavedObjectUnsanitizedDoc } from '@kbn/core-saved-objects-server'; +import { EncryptedSavedObjectsPluginSetup } from '@kbn/encrypted-saved-objects-plugin/server'; +import { isRuleType, ruleTypeMappings } from '@kbn/securitysolution-rules'; +import { RawRule } from '../../../types'; +import { FILEBEAT_7X_INDICATOR_PATH } from '../constants'; +import { + createEsoMigration, + isDetectionEngineAADRuleType, + isSiemSignalsRuleType, + pipeMigrations, +} from '../utils'; + +function addThreatIndicatorPathToThreatMatchRules( + doc: SavedObjectUnsanitizedDoc +): SavedObjectUnsanitizedDoc { + return isSiemSignalsRuleType(doc) && + doc.attributes.params?.type === 'threat_match' && + !doc.attributes.params.threatIndicatorPath + ? { + ...doc, + attributes: { + ...doc.attributes, + params: { + ...doc.attributes.params, + threatIndicatorPath: FILEBEAT_7X_INDICATOR_PATH, + }, + }, + } + : doc; +} + +function addSecuritySolutionAADRuleTypes( + doc: SavedObjectUnsanitizedDoc +): SavedObjectUnsanitizedDoc { + const ruleType = doc.attributes.params.type; + return isSiemSignalsRuleType(doc) && isRuleType(ruleType) + ? { + ...doc, + attributes: { + ...doc.attributes, + alertTypeId: ruleTypeMappings[ruleType], + enabled: false, + params: { + ...doc.attributes.params, + outputIndex: '', + }, + }, + } + : doc; +} + +function addSecuritySolutionAADRuleTypeTags( + doc: SavedObjectUnsanitizedDoc +): SavedObjectUnsanitizedDoc { + const ruleType = doc.attributes.params.type; + return isDetectionEngineAADRuleType(doc) && isRuleType(ruleType) + ? { + ...doc, + attributes: { + ...doc.attributes, + // If the rule is disabled at this point, then the rule has not been re-enabled after + // running the 8.0.0 migrations. If `doc.attributes.scheduledTaskId` exists, then the + // rule was enabled prior to running the migration. Thus we know we should add the + // tag to indicate it was auto-disabled. + tags: + !doc.attributes.enabled && doc.attributes.scheduledTaskId + ? [...(doc.attributes.tags ?? []), 'auto_disabled_8.0'] + : doc.attributes.tags ?? [], + }, + } + : doc; +} + +// This fixes an issue whereby metrics.alert.inventory.threshold rules had the +// group for actions incorrectly spelt as metrics.invenotry_threshold.fired vs metrics.inventory_threshold.fired +function fixInventoryThresholdGroupId( + doc: SavedObjectUnsanitizedDoc +): SavedObjectUnsanitizedDoc { + if (doc.attributes.alertTypeId === 'metrics.alert.inventory.threshold') { + const { + attributes: { actions }, + } = doc; + + const updatedActions = actions + ? actions.map((action) => { + // Wrong spelling + if (action.group === 'metrics.invenotry_threshold.fired') { + return { + ...action, + group: 'metrics.inventory_threshold.fired', + }; + } else { + return action; + } + }) + : []; + + return { + ...doc, + attributes: { + ...doc.attributes, + actions: updatedActions, + }, + }; + } else { + return doc; + } +} + +export const getMigrations800 = (encryptedSavedObjects: EncryptedSavedObjectsPluginSetup) => + createEsoMigration( + encryptedSavedObjects, + (doc: SavedObjectUnsanitizedDoc): doc is SavedObjectUnsanitizedDoc => true, + pipeMigrations( + addThreatIndicatorPathToThreatMatchRules, + addSecuritySolutionAADRuleTypes, + fixInventoryThresholdGroupId + ) + ); + +export const getMigrations801 = (encryptedSavedObjects: EncryptedSavedObjectsPluginSetup) => + createEsoMigration( + encryptedSavedObjects, + (doc: SavedObjectUnsanitizedDoc): doc is SavedObjectUnsanitizedDoc => true, + pipeMigrations(addSecuritySolutionAADRuleTypeTags) + ); diff --git a/x-pack/plugins/alerting/server/saved_objects/migrations/8.2/index.ts b/x-pack/plugins/alerting/server/saved_objects/migrations/8.2/index.ts new file mode 100644 index 0000000000000..6de67875ba2eb --- /dev/null +++ b/x-pack/plugins/alerting/server/saved_objects/migrations/8.2/index.ts @@ -0,0 +1,41 @@ +/* + * 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 { SavedObjectUnsanitizedDoc } from '@kbn/core-saved-objects-server'; +import { EncryptedSavedObjectsPluginSetup } from '@kbn/encrypted-saved-objects-plugin/server'; +import { getMappedParams } from '../../../rules_client/lib/mapped_params_utils'; +import { RawRule } from '../../../types'; +import { createEsoMigration, pipeMigrations } from '../utils'; + +function addMappedParams( + doc: SavedObjectUnsanitizedDoc +): SavedObjectUnsanitizedDoc { + const { + attributes: { params }, + } = doc; + + const mappedParams = getMappedParams(params); + + if (Object.keys(mappedParams).length) { + return { + ...doc, + attributes: { + ...doc.attributes, + mapped_params: mappedParams, + }, + }; + } + + return doc; +} + +export const getMigrations820 = (encryptedSavedObjects: EncryptedSavedObjectsPluginSetup) => + createEsoMigration( + encryptedSavedObjects, + (doc: SavedObjectUnsanitizedDoc): doc is SavedObjectUnsanitizedDoc => true, + pipeMigrations(addMappedParams) + ); diff --git a/x-pack/plugins/alerting/server/saved_objects/migrations/8.3/index.ts b/x-pack/plugins/alerting/server/saved_objects/migrations/8.3/index.ts new file mode 100644 index 0000000000000..833971a71dbbe --- /dev/null +++ b/x-pack/plugins/alerting/server/saved_objects/migrations/8.3/index.ts @@ -0,0 +1,96 @@ +/* + * 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 { SavedObjectUnsanitizedDoc } from '@kbn/core-saved-objects-server'; +import { EncryptedSavedObjectsPluginSetup } from '@kbn/encrypted-saved-objects-plugin/server'; +import { omit } from 'lodash'; +import moment from 'moment-timezone'; +import { RawRule } from '../../../types'; +import { + createEsoMigration, + isDetectionEngineAADRuleType, + isEsQueryRuleType, + pipeMigrations, +} from '../utils'; + +function addSearchType(doc: SavedObjectUnsanitizedDoc) { + const searchType = doc.attributes.params.searchType; + + return isEsQueryRuleType(doc) && !searchType + ? { + ...doc, + attributes: { + ...doc.attributes, + params: { + ...doc.attributes.params, + searchType: 'esQuery', + }, + }, + } + : doc; +} + +/** + * removes internal tags(starts with '__internal') from Security Solution rules + * @param doc rule to be migrated + * @returns migrated rule if it's Security Solution rule or unchanged if not + */ +function removeInternalTags( + doc: SavedObjectUnsanitizedDoc +): SavedObjectUnsanitizedDoc { + if (!isDetectionEngineAADRuleType(doc)) { + return doc; + } + + const { + attributes: { tags }, + } = doc; + + const filteredTags = (tags ?? []).filter((tag) => !tag.startsWith('__internal_')); + + return { + ...doc, + attributes: { + ...doc.attributes, + tags: filteredTags, + }, + }; +} + +function convertSnoozes( + doc: SavedObjectUnsanitizedDoc +): SavedObjectUnsanitizedDoc { + const { + attributes: { snoozeEndTime }, + } = doc; + + return { + ...doc, + attributes: { + ...(omit(doc.attributes, ['snoozeEndTime']) as RawRule), + snoozeSchedule: snoozeEndTime + ? [ + { + duration: Date.parse(snoozeEndTime as string) - Date.now(), + rRule: { + dtstart: new Date().toISOString(), + tzid: moment.tz.guess(), + count: 1, + }, + }, + ] + : [], + }, + }; +} + +export const getMigrations830 = (encryptedSavedObjects: EncryptedSavedObjectsPluginSetup) => + createEsoMigration( + encryptedSavedObjects, + (doc: SavedObjectUnsanitizedDoc): doc is SavedObjectUnsanitizedDoc => true, + pipeMigrations(addSearchType, removeInternalTags, convertSnoozes) + ); diff --git a/x-pack/plugins/alerting/server/saved_objects/migrations/8.4/index.ts b/x-pack/plugins/alerting/server/saved_objects/migrations/8.4/index.ts new file mode 100644 index 0000000000000..3a02425a7c194 --- /dev/null +++ b/x-pack/plugins/alerting/server/saved_objects/migrations/8.4/index.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 { SavedObjectUnsanitizedDoc } from '@kbn/core-saved-objects-server'; +import { EncryptedSavedObjectsPluginSetup } from '@kbn/encrypted-saved-objects-plugin/server'; +import { omit } from 'lodash'; +import { RawRule } from '../../../types'; +import { createEsoMigration, pipeMigrations } from '../utils'; + +function removeIsSnoozedUntil( + doc: SavedObjectUnsanitizedDoc +): SavedObjectUnsanitizedDoc { + return { + ...doc, + attributes: { + ...(omit(doc.attributes, ['isSnoozedUntil']) as RawRule), + }, + }; +} + +export const getMigrations841 = (encryptedSavedObjects: EncryptedSavedObjectsPluginSetup) => + createEsoMigration( + encryptedSavedObjects, + (doc: SavedObjectUnsanitizedDoc): doc is SavedObjectUnsanitizedDoc => true, + pipeMigrations(removeIsSnoozedUntil) + ); diff --git a/x-pack/plugins/alerting/server/saved_objects/migrations/8.5/index.ts b/x-pack/plugins/alerting/server/saved_objects/migrations/8.5/index.ts new file mode 100644 index 0000000000000..a40bcafd0bf35 --- /dev/null +++ b/x-pack/plugins/alerting/server/saved_objects/migrations/8.5/index.ts @@ -0,0 +1,65 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { + SavedObjectMigrationContext, + SavedObjectUnsanitizedDoc, +} from '@kbn/core-saved-objects-server'; +import { EncryptedSavedObjectsPluginSetup } from '@kbn/encrypted-saved-objects-plugin/server'; +import { isSerializedSearchSource } from '@kbn/data-plugin/common'; +import { pick } from 'lodash'; +import { RawRule } from '../../../types'; +import { createEsoMigration, isEsQueryRuleType, pipeMigrations } from '../utils'; +import { AlertLogMeta } from '../types'; + +function stripOutRuntimeFieldsInOldESQuery( + doc: SavedObjectUnsanitizedDoc, + context: SavedObjectMigrationContext +): SavedObjectUnsanitizedDoc { + const isESDSLrule = + isEsQueryRuleType(doc) && !isSerializedSearchSource(doc.attributes.params.searchConfiguration); + + if (isESDSLrule) { + try { + const parsedQuery = JSON.parse(doc.attributes.params.esQuery as string); + // parsing and restringifying will cause us to lose the formatting so we only do so if this rule has + // fields other than `query` which is the only valid field at this stage + const hasFieldsOtherThanQuery = Object.keys(parsedQuery).some((key) => key !== 'query'); + return hasFieldsOtherThanQuery + ? { + ...doc, + attributes: { + ...doc.attributes, + params: { + ...doc.attributes.params, + esQuery: JSON.stringify(pick(parsedQuery, 'query'), null, 4), + }, + }, + } + : doc; + } catch (err) { + // Instead of failing the upgrade when an unparsable rule is encountered, we log that the rule caouldn't be migrated and + // as a result legacy parameters might cause the rule to behave differently if it is, in fact, still running at all + context.log.error( + `unable to migrate and remove legacy runtime fields in rule ${doc.id} due to invalid query: "${doc.attributes.params.esQuery}" - query must be JSON`, + { + migrations: { + alertDocument: doc, + }, + } + ); + } + } + return doc; +} + +export const getMigrations850 = (encryptedSavedObjects: EncryptedSavedObjectsPluginSetup) => + createEsoMigration( + encryptedSavedObjects, + (doc): doc is SavedObjectUnsanitizedDoc => isEsQueryRuleType(doc), + pipeMigrations(stripOutRuntimeFieldsInOldESQuery) + ); diff --git a/x-pack/plugins/alerting/server/saved_objects/migrations/constants.ts b/x-pack/plugins/alerting/server/saved_objects/migrations/constants.ts new file mode 100644 index 0000000000000..849021f3c58c3 --- /dev/null +++ b/x-pack/plugins/alerting/server/saved_objects/migrations/constants.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 const SIEM_APP_ID = 'securitySolution'; +export const SIEM_SERVER_APP_ID = 'siem'; +export const MINIMUM_SS_MIGRATION_VERSION = '8.3.0'; +export const LEGACY_LAST_MODIFIED_VERSION = 'pre-7.10.0'; +export const FILEBEAT_7X_INDICATOR_PATH = 'threatintel.indicator'; diff --git a/x-pack/plugins/alerting/server/saved_objects/migrations.test.ts b/x-pack/plugins/alerting/server/saved_objects/migrations/index.test.ts similarity index 99% rename from x-pack/plugins/alerting/server/saved_objects/migrations.test.ts rename to x-pack/plugins/alerting/server/saved_objects/migrations/index.test.ts index be9bee7634990..09f466a8e9a37 100644 --- a/x-pack/plugins/alerting/server/saved_objects/migrations.test.ts +++ b/x-pack/plugins/alerting/server/saved_objects/migrations/index.test.ts @@ -7,12 +7,13 @@ import sinon from 'sinon'; import uuid from 'uuid'; -import { getMigrations, isAnyActionSupportIncidents } from './migrations'; -import { RawRule } from '../types'; +import { getMigrations } from '.'; +import { RawRule } from '../../types'; import { SavedObjectMigrationContext, SavedObjectUnsanitizedDoc } from '@kbn/core/server'; import { encryptedSavedObjectsMock } from '@kbn/encrypted-saved-objects-plugin/server/mocks'; import { migrationMocks } from '@kbn/core/server/mocks'; import { RuleType, ruleTypeMappings } from '@kbn/securitysolution-rules'; +import { isAnyActionSupportIncidents } from './7.11'; const migrationContext = migrationMocks.createContext(); const encryptedSavedObjectsSetup = encryptedSavedObjectsMock.createSetup(); @@ -24,6 +25,7 @@ describe('successful migrations', () => { jest.resetAllMocks(); encryptedSavedObjectsSetup.createMigration.mockImplementation(({ migration }) => migration); }); + describe('7.10.0', () => { test('marks alerts as legacy', () => { const migration710 = getMigrations(encryptedSavedObjectsSetup, {}, isPreconfigured)['7.10.0']; diff --git a/x-pack/plugins/alerting/server/saved_objects/migrations/index.ts b/x-pack/plugins/alerting/server/saved_objects/migrations/index.ts new file mode 100644 index 0000000000000..a3a06614ec4c5 --- /dev/null +++ b/x-pack/plugins/alerting/server/saved_objects/migrations/index.ts @@ -0,0 +1,155 @@ +/* + * 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 { gte } from 'semver'; +import { + SavedObjectMigrationMap, + SavedObjectUnsanitizedDoc, + SavedObjectMigrationFn, + SavedObjectMigrationContext, +} from '@kbn/core/server'; +import { EncryptedSavedObjectsPluginSetup } from '@kbn/encrypted-saved-objects-plugin/server'; +import { MigrateFunctionsObject, MigrateFunction } from '@kbn/kibana-utils-plugin/common'; +import { mergeSavedObjectMigrationMaps } from '@kbn/core/server'; +import { isSerializedSearchSource, SerializedSearchSourceFields } from '@kbn/data-plugin/common'; +import { RawRule } from '../../types'; +import { getMigrations7100 } from './7.10'; +import { getMigrations7110, getMigrations7112 } from './7.11'; +import { getMigrations7130 } from './7.13'; +import { getMigrations7140 } from './7.14'; +import { getMigrations7150 } from './7.15'; +import { getMigrations7160 } from './7.16'; +import { getMigrations800, getMigrations801 } from './8.0'; +import { getMigrations820 } from './8.2'; +import { getMigrations830 } from './8.3'; +import { getMigrations841 } from './8.4'; +import { getMigrations850 } from './8.5'; +import { AlertLogMeta, AlertMigration } from './types'; +import { MINIMUM_SS_MIGRATION_VERSION } from './constants'; +import { createEsoMigration, isEsQueryRuleType, pipeMigrations } from './utils'; + +export { FILEBEAT_7X_INDICATOR_PATH } from './constants'; + +export function getMigrations( + encryptedSavedObjects: EncryptedSavedObjectsPluginSetup, + searchSourceMigrations: MigrateFunctionsObject, + isPreconfigured: (connectorId: string) => boolean +): SavedObjectMigrationMap { + return mergeSavedObjectMigrationMaps( + { + '7.10.0': executeMigrationWithErrorHandling( + getMigrations7100(encryptedSavedObjects), + '7.10.0' + ), + '7.11.0': executeMigrationWithErrorHandling( + getMigrations7110(encryptedSavedObjects), + '7.11.0' + ), + '7.11.2': executeMigrationWithErrorHandling( + getMigrations7112(encryptedSavedObjects), + '7.11.2' + ), + '7.13.0': executeMigrationWithErrorHandling( + getMigrations7130(encryptedSavedObjects), + '7.13.0' + ), + '7.14.1': executeMigrationWithErrorHandling( + getMigrations7140(encryptedSavedObjects), + '7.14.1' + ), + '7.15.0': executeMigrationWithErrorHandling( + getMigrations7150(encryptedSavedObjects), + '7.15.0' + ), + '7.16.0': executeMigrationWithErrorHandling( + getMigrations7160(encryptedSavedObjects, isPreconfigured), + '7.16.0' + ), + '8.0.0': executeMigrationWithErrorHandling(getMigrations800(encryptedSavedObjects), '8.0.0'), + '8.0.1': executeMigrationWithErrorHandling(getMigrations801(encryptedSavedObjects), '8.0.1'), + '8.2.0': executeMigrationWithErrorHandling(getMigrations820(encryptedSavedObjects), '8.2.0'), + '8.3.0': executeMigrationWithErrorHandling(getMigrations830(encryptedSavedObjects), '8.3.0'), + '8.4.1': executeMigrationWithErrorHandling(getMigrations841(encryptedSavedObjects), '8.4.1'), + '8.5.0': executeMigrationWithErrorHandling(getMigrations850(encryptedSavedObjects), '8.5.0'), + }, + getSearchSourceMigrations(encryptedSavedObjects, searchSourceMigrations) + ); +} + +function executeMigrationWithErrorHandling( + migrationFunc: SavedObjectMigrationFn, + version: string +) { + return (doc: SavedObjectUnsanitizedDoc, context: SavedObjectMigrationContext) => { + try { + return migrationFunc(doc, context); + } catch (ex) { + context.log.error( + `encryptedSavedObject ${version} migration failed for alert ${doc.id} with error: ${ex.message}`, + { + migrations: { + alertDocument: doc, + }, + } + ); + throw ex; + } + }; +} + +function mapSearchSourceMigrationFunc( + migrateSerializedSearchSourceFields: MigrateFunction +): MigrateFunction { + return (doc) => { + const _doc = doc as { attributes: RawRule }; + + const serializedSearchSource = _doc.attributes.params.searchConfiguration; + + if (isSerializedSearchSource(serializedSearchSource)) { + return { + ..._doc, + attributes: { + ..._doc.attributes, + params: { + ..._doc.attributes.params, + searchConfiguration: migrateSerializedSearchSourceFields(serializedSearchSource), + }, + }, + }; + } + return _doc; + }; +} + +/** + * This creates a migration map that applies search source migrations to legacy es query rules. + * It doesn't modify existing migrations. The following migrations will occur at minimum version of 8.3+. + */ +function getSearchSourceMigrations( + encryptedSavedObjects: EncryptedSavedObjectsPluginSetup, + searchSourceMigrations: MigrateFunctionsObject +) { + const filteredMigrations: SavedObjectMigrationMap = {}; + for (const versionKey in searchSourceMigrations) { + if (gte(versionKey, MINIMUM_SS_MIGRATION_VERSION)) { + const migrateSearchSource = mapSearchSourceMigrationFunc( + searchSourceMigrations[versionKey] + ) as unknown as AlertMigration; + + filteredMigrations[versionKey] = executeMigrationWithErrorHandling( + createEsoMigration( + encryptedSavedObjects, + (doc: SavedObjectUnsanitizedDoc): doc is SavedObjectUnsanitizedDoc => + isEsQueryRuleType(doc), + pipeMigrations(migrateSearchSource) + ), + versionKey + ); + } + } + return filteredMigrations; +} diff --git a/x-pack/plugins/alerting/server/saved_objects/migrations/types.ts b/x-pack/plugins/alerting/server/saved_objects/migrations/types.ts new file mode 100644 index 0000000000000..6d657e168187e --- /dev/null +++ b/x-pack/plugins/alerting/server/saved_objects/migrations/types.ts @@ -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. + */ + +import { LogMeta, SavedObjectMigrationContext, SavedObjectUnsanitizedDoc } from '@kbn/core/server'; +import { RawRule } from '../../types'; + +export interface AlertLogMeta extends LogMeta { + migrations: { alertDocument: SavedObjectUnsanitizedDoc }; +} + +export type AlertMigration = ( + doc: SavedObjectUnsanitizedDoc, + context: SavedObjectMigrationContext +) => SavedObjectUnsanitizedDoc; diff --git a/x-pack/plugins/alerting/server/saved_objects/migrations/utils.ts b/x-pack/plugins/alerting/server/saved_objects/migrations/utils.ts new file mode 100644 index 0000000000000..c96d0cfa5d7fc --- /dev/null +++ b/x-pack/plugins/alerting/server/saved_objects/migrations/utils.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ruleTypeMappings } from '@kbn/securitysolution-rules'; +import { + SavedObjectMigrationContext, + SavedObjectUnsanitizedDoc, +} from '@kbn/core-saved-objects-server'; +import { EncryptedSavedObjectsPluginSetup } from '@kbn/encrypted-saved-objects-plugin/server'; +import type { IsMigrationNeededPredicate } from '@kbn/encrypted-saved-objects-plugin/server'; + +import { RawRule } from '../../types'; + +type AlertMigration = ( + doc: SavedObjectUnsanitizedDoc, + context: SavedObjectMigrationContext +) => SavedObjectUnsanitizedDoc; + +export function createEsoMigration( + encryptedSavedObjects: EncryptedSavedObjectsPluginSetup, + isMigrationNeededPredicate: IsMigrationNeededPredicate, + migrationFunc: AlertMigration +) { + return encryptedSavedObjects.createMigration({ + isMigrationNeededPredicate, + migration: migrationFunc, + shouldMigrateIfDecryptionFails: true, // shouldMigrateIfDecryptionFails flag that applies the migration to undecrypted document if decryption fails + }); +} + +export function pipeMigrations(...migrations: AlertMigration[]): AlertMigration { + return (doc: SavedObjectUnsanitizedDoc, context: SavedObjectMigrationContext) => + migrations.reduce((migratedDoc, nextMigration) => nextMigration(migratedDoc, context), doc); +} + +// Deprecated in 8.0 +export const isSiemSignalsRuleType = (doc: SavedObjectUnsanitizedDoc): boolean => + doc.attributes.alertTypeId === 'siem.signals'; + +export const isEsQueryRuleType = (doc: SavedObjectUnsanitizedDoc) => + doc.attributes.alertTypeId === '.es-query'; + +export const isDetectionEngineAADRuleType = (doc: SavedObjectUnsanitizedDoc): boolean => + (Object.values(ruleTypeMappings) as string[]).includes(doc.attributes.alertTypeId); + +/** + * Returns true if the alert type is that of "siem.notifications" which is a legacy notification system that was deprecated in 7.16.0 + * in favor of using the newer alerting notifications system. + * @param doc The saved object alert type document + * @returns true if this is a legacy "siem.notifications" rule, otherwise false + * @deprecated Once we are confident all rules relying on side-car actions SO's have been migrated to SO references we should remove this function + */ +export const isSecuritySolutionLegacyNotification = ( + doc: SavedObjectUnsanitizedDoc +): boolean => doc.attributes.alertTypeId === 'siem.notifications'; diff --git a/x-pack/plugins/apm/dev_docs/apm_queries.md b/x-pack/plugins/apm/dev_docs/apm_queries.md index 4dd9a807eb249..952d38b42691a 100644 --- a/x-pack/plugins/apm/dev_docs/apm_queries.md +++ b/x-pack/plugins/apm/dev_docs/apm_queries.md @@ -1,17 +1,20 @@ ### Table of Contents - - [Transactions](#transactions) - - [System metrics](#system-metrics) - - [Transaction breakdown metrics](#transaction-breakdown-metrics) - - [Span breakdown metrics](#span-breakdown-metrics) - - [Service destination metrics](#service-destination-metrics) - - [Common filters](#common-filters) + +- [Transactions](#transactions) +- [System metrics](#system-metrics) +- [Transaction breakdown metrics](#transaction-breakdown-metrics) +- [Span breakdown metrics](#span-breakdown-metrics) +- [Service destination metrics](#service-destination-metrics) +- [Common filters](#common-filters) --- ### Data model + Elastic APM agents capture different types of information from within their instrumented applications. These are known as events, and can be spans, transactions, errors, or metrics. You can find more information [here](https://www.elastic.co/guide/en/apm/get-started/current/apm-data-model.html). ### Running examples + You can run the example queries on the [edge cluster](https://edge-oblt.elastic.dev/) or any another cluster that contains APM data. # Transactions @@ -34,7 +37,8 @@ A single transaction event where `transaction.duration.us` is the latency. or #### Aggregated (metric) document -A pre-aggregated document where `_doc_count` is the number of transaction events, and `transaction.duration.histogram` is the latency distribution. + +A pre-aggregated document where `_doc_count` is the number of transaction events, and `transaction.duration.histogram` is the latency distribution. ```json { @@ -52,7 +56,7 @@ A pre-aggregated document where `_doc_count` is the number of transaction events You can find all the APM transaction fields [here](https://www.elastic.co/guide/en/apm/server/current/exported-fields-apm-transaction.html). -The decision to use aggregated transactions or not is determined in [`getSearchAggregatedTransactions`](https://github.com/elastic/kibana/blob/a2ac439f56313b7a3fc4708f54a4deebf2615136/x-pack/plugins/apm/server/lib/helpers/aggregated_transactions/index.ts#L53-L79) and then used to specify [the transaction index](https://github.com/elastic/kibana/blob/a2ac439f56313b7a3fc4708f54a4deebf2615136/x-pack/plugins/apm/server/lib/suggestions/get_suggestions.ts#L30-L32) and [the latency field](https://github.com/elastic/kibana/blob/a2ac439f56313b7a3fc4708f54a4deebf2615136/x-pack/plugins/apm/server/lib/alerts/chart_preview/get_transaction_duration.ts#L62-L65) +The decision to use aggregated transactions or not is determined in [`getSearchTransactionsEvents`](https://github.com/elastic/kibana/blob/a2ac439f56313b7a3fc4708f54a4deebf2615136/x-pack/plugins/apm/server/lib/helpers/aggregated_transactions/index.ts#L53-L79) and then used to specify [the transaction index](https://github.com/elastic/kibana/blob/a2ac439f56313b7a3fc4708f54a4deebf2615136/x-pack/plugins/apm/server/lib/suggestions/get_suggestions.ts#L30-L32) and [the latency field](https://github.com/elastic/kibana/blob/a2ac439f56313b7a3fc4708f54a4deebf2615136/x-pack/plugins/apm/server/lib/alerts/chart_preview/get_transaction_duration.ts#L62-L65) ### Latency @@ -134,7 +138,6 @@ GET apm-*-transaction-*,traces-apm*/_search?terminate_after=1000 } ``` - #### Metric-based throughput ```json @@ -174,23 +177,23 @@ Noteworthy fields: `event.outcome` #### Transaction-based failed transaction rate - ```json +```json GET apm-*-transaction-*,traces-apm*/_search?terminate_after=1000 { - "size": 0, - "query": { - "bool": { - "filter": [{ "terms": { "processor.event": ["transaction"] } }] - } - }, - "aggs": { - "outcomes": { - "terms": { - "field": "event.outcome", - "include": ["failure", "success"] - } - } - } + "size": 0, + "query": { + "bool": { + "filter": [{ "terms": { "processor.event": ["transaction"] } }] + } + }, + "aggs": { + "outcomes": { + "terms": { + "field": "event.outcome", + "include": ["failure", "success"] + } + } + } } ``` @@ -219,6 +222,57 @@ GET apm-*-metric-*,metrics-apm*/_search?terminate_after=1000 } ``` +# Transactions in service inventory page + +Service metrics is an aggregated metric document that holds latency and throughput metrics pivoted by `service.name + service.environment + transaction.type` + +The decision to use service metrics aggregation or not is determined in [getServiceInventorySearchSource](https://github.com/elastic/kibana/blob/5d585ea375be551a169a0bea49b011819b9ac669/x-pack/plugins/apm/server/lib/helpers/get_service_inventory_search_source.ts#L12) and [getSearchServiceMetrics](https://github.com/elastic/kibana/blob/5d585ea375be551a169a0bea49b011819b9ac669/x-pack/plugins/apm/server/lib/helpers/service_metrics/index.ts#L38) + +A pre-aggregated document where `_doc_count` is the number of transaction events + +``` +{ + "_doc_count": 627, + "@timestamp": "2021-09-01T10:00:00.000Z", + "processor.event": "metric", + "metricset.name": "service", + "service": { + "environment": "production", + "name": "web-go" + }, + "transaction": { + "duration.summary": { + "sum": 376492831, + "value_count": 627 + }, + "success_count": 476, + "failure_count": 151, + "type": "request" + } +} +``` + +- `_doc_count` is the number of bucket counts +- `transaction.duration.summary` is an [aggregate_metric_double](https://www.elastic.co/guide/en/elasticsearch/reference/7.17/aggregate-metric-double.html) field and holds an aggregated transaction duration summary, for service metrics +- `failure_count` holds an aggregated count of transactions with the outcome "failure" +- `success_count` holds an aggregated count of transactions with the outcome "success" + +### Latency + +``` +{ + "size": 0, + "query": { + "bool": { + "filter": [{ "term": { "metricset.name": "service" } }] + } + }, + "aggs": { + "latency": { "avg": { "field": "transaction.duration.summary" }} + } +} +``` + # System metrics System metrics are captured periodically (every 60 seconds by default). You can find all the System Metrics fields [here](https://www.elastic.co/guide/en/apm/server/current/exported-fields-system.html). @@ -317,7 +371,7 @@ The above example is overly simplified. In reality [we do a bit more](https://gi # Span breakdown metrics -A pre-aggregations of span documents where `span.self_time.count` is the number of original spans. Measures the "self-time" for a span type, and optional subtype, within a transaction group. +A pre-aggregations of span documents where `span.self_time.count` is the number of original spans. Measures the "self-time" for a span type, and optional subtype, within a transaction group. Span breakdown metrics are used to power the "Time spent by span type" graph. Agents collect summarized metrics about the timings of spans, broken down by `span.type`. @@ -436,7 +490,6 @@ GET apm-*-metric-*,metrics-apm*/_search?terminate_after=1000 Captures the number of requests made from a service to an (external) endpoint - #### Query ```json diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/e2e/power_user/integration_settings/integration_policy.cy.ts b/x-pack/plugins/apm/ftr_e2e/cypress/e2e/power_user/integration_settings/integration_policy.cy.ts index 5d275770e462d..528e260940e3c 100644 --- a/x-pack/plugins/apm/ftr_e2e/cypress/e2e/power_user/integration_settings/integration_policy.cy.ts +++ b/x-pack/plugins/apm/ftr_e2e/cypress/e2e/power_user/integration_settings/integration_policy.cy.ts @@ -60,7 +60,7 @@ describe('when navigating to integration page', () => { cy.visitKibana(integrationsPath); // open integration policy form - cy.getByTestSubj('integration-card:epr:apm:featured').click(); + cy.getByTestSubj('integration-card:ui_link:apm').click(); cy.contains('Elastic APM in Fleet').click(); cy.contains('a', 'APM integration').click(); cy.getByTestSubj('addIntegrationPolicyButton').click(); diff --git a/x-pack/plugins/apm/public/components/app/metrics/index.tsx b/x-pack/plugins/apm/public/components/app/metrics/index.tsx new file mode 100644 index 0000000000000..3149a13b940f8 --- /dev/null +++ b/x-pack/plugins/apm/public/components/app/metrics/index.tsx @@ -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 React from 'react'; +import { isJavaAgentName, isJRubyAgent } from '../../../../common/agent_name'; +import { useApmServiceContext } from '../../../context/apm_service/use_apm_service_context'; +import { ServiceMetrics } from './service_metrics'; +import { JvmMetricsOverview } from './jvm_metrics_overview'; + +export function Metrics() { + const { agentName, runtimeName } = useApmServiceContext(); + + if (isJavaAgentName(agentName) || isJRubyAgent(agentName, runtimeName)) { + return ; + } + + return ; +} diff --git a/x-pack/plugins/apm/public/components/app/service_node_overview/index.tsx b/x-pack/plugins/apm/public/components/app/metrics/jvm_metrics_overview/index.tsx similarity index 85% rename from x-pack/plugins/apm/public/components/app/service_node_overview/index.tsx rename to x-pack/plugins/apm/public/components/app/metrics/jvm_metrics_overview/index.tsx index 99222394bcfe2..437ebd7e672ee 100644 --- a/x-pack/plugins/apm/public/components/app/service_node_overview/index.tsx +++ b/x-pack/plugins/apm/public/components/app/metrics/jvm_metrics_overview/index.tsx @@ -11,19 +11,19 @@ import { euiStyled } from '@kbn/kibana-react-plugin/common'; import { getServiceNodeName, SERVICE_NODE_NAME_MISSING, -} from '../../../../common/service_nodes'; +} from '../../../../../common/service_nodes'; import { asDynamicBytes, asInteger, asPercent, -} from '../../../../common/utils/formatters'; -import { useApmServiceContext } from '../../../context/apm_service/use_apm_service_context'; -import { useApmParams } from '../../../hooks/use_apm_params'; -import { useFetcher, FETCH_STATUS } from '../../../hooks/use_fetcher'; -import { useTimeRange } from '../../../hooks/use_time_range'; -import { truncate, unit } from '../../../utils/style'; -import { ServiceNodeMetricOverviewLink } from '../../shared/links/apm/service_node_metric_overview_link'; -import { ITableColumn, ManagedTable } from '../../shared/managed_table'; +} from '../../../../../common/utils/formatters'; +import { useApmServiceContext } from '../../../../context/apm_service/use_apm_service_context'; +import { useApmParams } from '../../../../hooks/use_apm_params'; +import { useFetcher, FETCH_STATUS } from '../../../../hooks/use_fetcher'; +import { useTimeRange } from '../../../../hooks/use_time_range'; +import { truncate, unit } from '../../../../utils/style'; +import { ServiceNodeMetricOverviewLink } from '../../../shared/links/apm/service_node_metric_overview_link'; +import { ITableColumn, ManagedTable } from '../../../shared/managed_table'; const INITIAL_SORT_FIELD = 'cpu'; const INITIAL_SORT_DIRECTION = 'desc'; @@ -32,10 +32,10 @@ const ServiceNodeName = euiStyled.div` ${truncate(8 * unit)} `; -function ServiceNodeOverview() { +export function JvmMetricsOverview() { const { query: { environment, kuery, rangeFrom, rangeTo }, - } = useApmParams('/services/{serviceName}/nodes'); + } = useApmParams('/services/{serviceName}/metrics'); const { start, end } = useTimeRange({ rangeFrom, rangeTo }); @@ -47,7 +47,7 @@ function ServiceNodeOverview() { return undefined; } return callApmApi( - 'GET /internal/apm/services/{serviceName}/serviceNodes', + 'GET /internal/apm/services/{serviceName}/metrics/nodes', { params: { path: { @@ -177,5 +177,3 @@ function ServiceNodeOverview() { /> ); } - -export { ServiceNodeOverview }; diff --git a/x-pack/plugins/apm/public/components/app/service_metrics/index.tsx b/x-pack/plugins/apm/public/components/app/metrics/service_metrics/index.tsx similarity index 74% rename from x-pack/plugins/apm/public/components/app/service_metrics/index.tsx rename to x-pack/plugins/apm/public/components/app/metrics/service_metrics/index.tsx index 557a4a81c647d..6d0ddcb61fad0 100644 --- a/x-pack/plugins/apm/public/components/app/service_metrics/index.tsx +++ b/x-pack/plugins/apm/public/components/app/metrics/service_metrics/index.tsx @@ -7,11 +7,11 @@ import { EuiFlexGrid, EuiFlexItem, EuiPanel, EuiSpacer } from '@elastic/eui'; import React from 'react'; -import { ChartPointerEventContextProvider } from '../../../context/chart_pointer_event/chart_pointer_event_context'; -import { useApmParams } from '../../../hooks/use_apm_params'; -import { useServiceMetricChartsFetcher } from '../../../hooks/use_service_metric_charts_fetcher'; -import { useTimeRange } from '../../../hooks/use_time_range'; -import { MetricsChart } from '../../shared/charts/metrics_chart'; +import { ChartPointerEventContextProvider } from '../../../../context/chart_pointer_event/chart_pointer_event_context'; +import { useApmParams } from '../../../../hooks/use_apm_params'; +import { useServiceMetricChartsFetcher } from '../../../../hooks/use_service_metric_charts_fetcher'; +import { useTimeRange } from '../../../../hooks/use_time_range'; +import { MetricsChart } from '../../../shared/charts/metrics_chart'; export function ServiceMetrics() { const { diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_details_page_header.tsx b/x-pack/plugins/apm/public/components/app/metrics_details/index.tsx similarity index 65% rename from x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_details_page_header.tsx rename to x-pack/plugins/apm/public/components/app/metrics_details/index.tsx index 0425ab3ce309e..4adbb25c26d1e 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_details_page_header.tsx +++ b/x-pack/plugins/apm/public/components/app/metrics_details/index.tsx @@ -4,10 +4,9 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - import React from 'react'; -import { MonitorDetailsTabs } from './monitor_detials_tabs'; +import { ServiceNodeMetrics } from './service_node_metrics'; -export const MonitorDetailsPageHeader = () => { - return ; -}; +export function MetricsDetails() { + return ; +} diff --git a/x-pack/plugins/apm/public/components/app/service_node_metrics/index.test.tsx b/x-pack/plugins/apm/public/components/app/metrics_details/service_node_metrics/index.test.tsx similarity index 86% rename from x-pack/plugins/apm/public/components/app/service_node_metrics/index.test.tsx rename to x-pack/plugins/apm/public/components/app/metrics_details/service_node_metrics/index.test.tsx index bff224cdc791c..9356cab2d1f9c 100644 --- a/x-pack/plugins/apm/public/components/app/service_node_metrics/index.test.tsx +++ b/x-pack/plugins/apm/public/components/app/metrics_details/service_node_metrics/index.test.tsx @@ -8,7 +8,7 @@ import React from 'react'; import { shallow } from 'enzyme'; import { ServiceNodeMetrics } from '.'; -import { MockApmPluginContextWrapper } from '../../../context/apm_plugin/mock_apm_plugin_context'; +import { MockApmPluginContextWrapper } from '../../../../context/apm_plugin/mock_apm_plugin_context'; describe('ServiceNodeMetrics', () => { describe('render', () => { diff --git a/x-pack/plugins/apm/public/components/app/service_node_metrics/index.tsx b/x-pack/plugins/apm/public/components/app/metrics_details/service_node_metrics/index.tsx similarity index 82% rename from x-pack/plugins/apm/public/components/app/service_node_metrics/index.tsx rename to x-pack/plugins/apm/public/components/app/metrics_details/service_node_metrics/index.tsx index b902c7f0f1cea..cc0703c036780 100644 --- a/x-pack/plugins/apm/public/components/app/service_node_metrics/index.tsx +++ b/x-pack/plugins/apm/public/components/app/metrics_details/service_node_metrics/index.tsx @@ -23,18 +23,18 @@ import { euiStyled } from '@kbn/kibana-react-plugin/common'; import { getServiceNodeName, SERVICE_NODE_NAME_MISSING, -} from '../../../../common/service_nodes'; -import { useApmServiceContext } from '../../../context/apm_service/use_apm_service_context'; -import { useApmPluginContext } from '../../../context/apm_plugin/use_apm_plugin_context'; -import { useBreadcrumb } from '../../../context/breadcrumbs/use_breadcrumb'; -import { ChartPointerEventContextProvider } from '../../../context/chart_pointer_event/chart_pointer_event_context'; -import { useApmParams } from '../../../hooks/use_apm_params'; -import { useApmRouter } from '../../../hooks/use_apm_router'; -import { FETCH_STATUS, useFetcher } from '../../../hooks/use_fetcher'; -import { useServiceMetricChartsFetcher } from '../../../hooks/use_service_metric_charts_fetcher'; -import { useTimeRange } from '../../../hooks/use_time_range'; -import { truncate, unit } from '../../../utils/style'; -import { MetricsChart } from '../../shared/charts/metrics_chart'; +} from '../../../../../common/service_nodes'; +import { useApmServiceContext } from '../../../../context/apm_service/use_apm_service_context'; +import { useApmPluginContext } from '../../../../context/apm_plugin/use_apm_plugin_context'; +import { useBreadcrumb } from '../../../../context/breadcrumbs/use_breadcrumb'; +import { ChartPointerEventContextProvider } from '../../../../context/chart_pointer_event/chart_pointer_event_context'; +import { useApmParams } from '../../../../hooks/use_apm_params'; +import { useApmRouter } from '../../../../hooks/use_apm_router'; +import { FETCH_STATUS, useFetcher } from '../../../../hooks/use_fetcher'; +import { useServiceMetricChartsFetcher } from '../../../../hooks/use_service_metric_charts_fetcher'; +import { useTimeRange } from '../../../../hooks/use_time_range'; +import { truncate, unit } from '../../../../utils/style'; +import { MetricsChart } from '../../../shared/charts/metrics_chart'; const INITIAL_DATA = { host: '', @@ -52,9 +52,9 @@ export function ServiceNodeMetrics() { const apmRouter = useApmRouter(); const { - path: { serviceNodeName }, + path: { id: serviceNodeName }, query, - } = useApmParams('/services/{serviceName}/nodes/{serviceNodeName}/metrics'); + } = useApmParams('/services/{serviceName}/metrics/{id}'); const { environment, kuery, rangeFrom, rangeTo } = query; @@ -63,16 +63,13 @@ export function ServiceNodeMetrics() { useBreadcrumb( () => ({ title: getServiceNodeName(serviceNodeName), - href: apmRouter.link( - '/services/{serviceName}/nodes/{serviceNodeName}/metrics', - { - path: { - serviceName, - serviceNodeName, - }, - query, - } - ), + href: apmRouter.link('/services/{serviceName}/metrics/{id}', { + path: { + serviceName, + id: serviceNodeName, + }, + query, + }), }), [apmRouter, query, serviceName, serviceNodeName] ); diff --git a/x-pack/plugins/apm/public/components/app/service_overview/service_overview_dependencies_table/index.tsx b/x-pack/plugins/apm/public/components/app/service_overview/service_overview_dependencies_table/index.tsx index 8e7c7a0336d30..c4c1690b6bb89 100644 --- a/x-pack/plugins/apm/public/components/app/service_overview/service_overview_dependencies_table/index.tsx +++ b/x-pack/plugins/apm/public/components/app/service_overview/service_overview_dependencies_table/index.tsx @@ -140,7 +140,7 @@ export function ServiceOverviewDependenciesTable({ 'xpack.apm.serviceOverview.dependenciesTableTitleTip', { defaultMessage: - 'Uninstrumented downstream services or external connections derived from the exit spans of instrumented services.', + 'Downstream services and external connections to uninstrumented services', } )} > diff --git a/x-pack/plugins/apm/public/components/app/settings/general_settings/index.tsx b/x-pack/plugins/apm/public/components/app/settings/general_settings/index.tsx index 9e6e09d525fb5..2faad60fb8b81 100644 --- a/x-pack/plugins/apm/public/components/app/settings/general_settings/index.tsx +++ b/x-pack/plugins/apm/public/components/app/settings/general_settings/index.tsx @@ -5,8 +5,10 @@ * 2.0. */ +import { EuiCallOut, EuiLink, EuiSpacer } from '@elastic/eui'; import { LazyField } from '@kbn/advanced-settings-plugin/public'; import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n-react'; import { apmLabsButton, apmProgressiveLoading, @@ -31,7 +33,7 @@ const apmSettingsKeys = [ ]; export function GeneralSettings() { - const { docLinks, notifications } = useApmPluginContext().core; + const { docLinks, notifications, application } = useApmPluginContext().core; const { handleFieldChange, settingsEditableConfig, @@ -63,6 +65,29 @@ export function GeneralSettings() { return ( <> + + {i18n.translate('xpack.apm.apmSettings.kibanaLink.label', { + defaultMessage: 'Kibana advanced settings', + })} + + ), + }} + /> + } + iconType="iInCircle" + /> + {apmSettingsKeys.map((settingKey) => { const editableConfig = settingsEditableConfig[settingKey]; return ( diff --git a/x-pack/plugins/apm/public/components/routing/service_detail/index.tsx b/x-pack/plugins/apm/public/components/routing/service_detail/index.tsx index 8068ee3baf5ef..fdd1aedfa0022 100644 --- a/x-pack/plugins/apm/public/components/routing/service_detail/index.tsx +++ b/x-pack/plugins/apm/public/components/routing/service_detail/index.tsx @@ -4,32 +4,34 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import * as t from 'io-ts'; import { i18n } from '@kbn/i18n'; -import React from 'react'; -import { Outlet } from '@kbn/typed-react-router-config'; import { toBooleanRt, toNumberRt } from '@kbn/io-ts-utils'; +import { Outlet } from '@kbn/typed-react-router-config'; +import * as t from 'io-ts'; +import qs from 'query-string'; +import React from 'react'; +import { Redirect } from 'react-router-dom'; +import { offsetRt } from '../../../../common/comparison_rt'; import { ENVIRONMENT_ALL } from '../../../../common/environment_filter_values'; import { environmentRt } from '../../../../common/environment_rt'; -import { ServiceOverview } from '../../app/service_overview'; -import { ApmServiceTemplate } from '../templates/apm_service_template'; -import { RedirectToDefaultServiceRouteView } from './redirect_to_default_service_route_view'; -import { TransactionOverview } from '../../app/transaction_overview'; -import { ApmServiceWrapper } from './apm_service_wrapper'; -import { ErrorGroupOverview } from '../../app/error_group_overview'; +import { LatencyAggregationType } from '../../../../common/latency_aggregation_types'; +import { TimeRangeMetadataContextProvider } from '../../../context/time_range_metadata/time_range_metadata_context'; +import { useApmParams } from '../../../hooks/use_apm_params'; +import { AlertsOverview } from '../../app/alerts_overview'; import { ErrorGroupDetails } from '../../app/error_group_details'; -import { ServiceMetrics } from '../../app/service_metrics'; -import { ServiceNodeOverview } from '../../app/service_node_overview'; -import { ServiceNodeMetrics } from '../../app/service_node_metrics'; -import { ServiceMapServiceDetail } from '../../app/service_map'; -import { TransactionDetails } from '../../app/transaction_details'; +import { ErrorGroupOverview } from '../../app/error_group_overview'; +import { InfraOverview } from '../../app/infra_overview'; +import { Metrics } from '../../app/metrics'; +import { MetricsDetails } from '../../app/metrics_details'; import { ServiceDependencies } from '../../app/service_dependencies'; import { ServiceLogs } from '../../app/service_logs'; -import { InfraOverview } from '../../app/infra_overview'; -import { AlertsOverview } from '../../app/alerts_overview'; -import { LatencyAggregationType } from '../../../../common/latency_aggregation_types'; -import { offsetRt } from '../../../../common/comparison_rt'; -import { TimeRangeMetadataContextProvider } from '../../../context/time_range_metadata/time_range_metadata_context'; +import { ServiceMapServiceDetail } from '../../app/service_map'; +import { ServiceOverview } from '../../app/service_overview'; +import { TransactionDetails } from '../../app/transaction_details'; +import { TransactionOverview } from '../../app/transaction_overview'; +import { ApmServiceTemplate } from '../templates/apm_service_template'; +import { ApmServiceWrapper } from './apm_service_wrapper'; +import { RedirectToDefaultServiceRouteView } from './redirect_to_default_service_route_view'; function page({ title, @@ -62,6 +64,31 @@ function page({ }; } +function RedirectNodesToMetrics() { + const { query, path } = useApmParams('/services/{serviceName}/nodes'); + const search = qs.stringify(query); + return ( + + ); +} + +function RedirectNodeMetricsToMetricsDetails() { + const { query, path } = useApmParams( + '/services/{serviceName}/nodes/{serviceNodeName}/metrics' + ); + const search = qs.stringify(query); + return ( + + ); +} + export const serviceDetail = { '/services/{serviceName}': { element: ( @@ -210,13 +237,29 @@ export const serviceDetail = { }, }, }, - '/services/{serviceName}/metrics': page({ - tab: 'metrics', - title: i18n.translate('xpack.apm.views.metrics.title', { - defaultMessage: 'Metrics', + '/services/{serviceName}/metrics': { + ...page({ + tab: 'metrics', + title: i18n.translate('xpack.apm.views.metrics.title', { + defaultMessage: 'Metrics', + }), + element: , }), - element: , - }), + children: { + '/services/{serviceName}/metrics': { + element: , + }, + '/services/{serviceName}/metrics/{id}': { + element: , + params: t.type({ + path: t.type({ + id: t.string, + }), + }), + }, + }, + }, + // Deprecated: redirect it to metrics '/services/{serviceName}/nodes': { ...page({ tab: 'nodes', @@ -227,7 +270,7 @@ export const serviceDetail = { }), children: { '/services/{serviceName}/nodes/{serviceNodeName}/metrics': { - element: , + element: , params: t.type({ path: t.type({ serviceNodeName: t.string, @@ -235,7 +278,7 @@ export const serviceDetail = { }), }, '/services/{serviceName}/nodes': { - element: , + element: , params: t.partial({ query: t.partial({ sortDirection: t.string, diff --git a/x-pack/plugins/apm/public/components/routing/templates/apm_service_template/index.test.tsx b/x-pack/plugins/apm/public/components/routing/templates/apm_service_template/index.test.tsx index c8ab3acd1a0af..37271e32c67e3 100644 --- a/x-pack/plugins/apm/public/components/routing/templates/apm_service_template/index.test.tsx +++ b/x-pack/plugins/apm/public/components/routing/templates/apm_service_template/index.test.tsx @@ -4,11 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { - isMetricsTabHidden, - isMetricsJVMsTabHidden, - isInfraTabHidden, -} from '.'; +import { isMetricsTabHidden, isInfraTabHidden } from '.'; describe('APM service template', () => { describe('isMetricsTabHidden', () => { @@ -18,10 +14,7 @@ describe('APM service template', () => { { agentName: 'js-base' }, { agentName: 'rum-js' }, { agentName: 'opentelemetry/webjs' }, - { agentName: 'java' }, - { agentName: 'opentelemetry/java' }, { agentName: 'ios/swift' }, - { agentName: 'ruby', runtimeName: 'jruby' }, { runtimeName: 'aws_lambda' }, ].map((input) => { it(`when input ${JSON.stringify(input)}`, () => { @@ -38,39 +31,12 @@ describe('APM service template', () => { { agentName: 'nodejs' }, { agentName: 'php' }, { agentName: 'python' }, - ].map((input) => { - it(`when input ${JSON.stringify(input)}`, () => { - expect(isMetricsTabHidden(input)).toBeFalsy(); - }); - }); - }); - }); - describe('isMetricsJVMsTabHidden', () => { - describe('hides metrics JVMs tab', () => { - [ - { agentName: undefined }, - { agentName: 'ruby', runtimeName: 'ruby' }, - { agentName: 'ruby' }, - { agentName: 'dotnet' }, - { agentName: 'go' }, - { agentName: 'nodejs' }, - { agentName: 'php' }, - { agentName: 'python' }, - { runtimeName: 'aws_lambda' }, - ].map((input) => { - it(`when input ${JSON.stringify(input)}`, () => { - expect(isMetricsJVMsTabHidden(input)).toBeTruthy(); - }); - }); - }); - describe('shows metrics JVMs tab', () => { - [ + { agentName: 'ruby', runtimeName: 'jruby' }, { agentName: 'java' }, { agentName: 'opentelemetry/java' }, - { agentName: 'ruby', runtimeName: 'jruby' }, ].map((input) => { it(`when input ${JSON.stringify(input)}`, () => { - expect(isMetricsJVMsTabHidden(input)).toBeFalsy(); + expect(isMetricsTabHidden(input)).toBeFalsy(); }); }); }); diff --git a/x-pack/plugins/apm/public/components/routing/templates/apm_service_template/index.tsx b/x-pack/plugins/apm/public/components/routing/templates/apm_service_template/index.tsx index c1bda0d2acfe6..6d3a6ff96b178 100644 --- a/x-pack/plugins/apm/public/components/routing/templates/apm_service_template/index.tsx +++ b/x-pack/plugins/apm/public/components/routing/templates/apm_service_template/index.tsx @@ -16,8 +16,6 @@ import { omit } from 'lodash'; import React from 'react'; import { enableAwsLambdaMetrics } from '@kbn/observability-plugin/common'; import { - isJavaAgentName, - isJRubyAgent, isMobileAgentName, isRumAgentName, isServerlessAgent, @@ -150,24 +148,7 @@ export function isMetricsTabHidden({ return !isAwsLambdaEnabled; } return ( - !agentName || - isRumAgentName(agentName) || - isJavaAgentName(agentName) || - isMobileAgentName(agentName) || - isJRubyAgent(agentName, runtimeName) - ); -} - -export function isMetricsJVMsTabHidden({ - agentName, - runtimeName, -}: { - agentName?: string; - runtimeName?: string; -}) { - return ( - !(isJavaAgentName(agentName) || isJRubyAgent(agentName, runtimeName)) || - isServerlessAgent(runtimeName) + !agentName || isRumAgentName(agentName) || isMobileAgentName(agentName) ); } @@ -276,17 +257,6 @@ function useTabs({ selectedTab }: { selectedTab: Tab['key'] }) { isAwsLambdaEnabled, }), }, - { - key: 'nodes', - href: router.link('/services/{serviceName}/nodes', { - path: { serviceName }, - query, - }), - label: i18n.translate('xpack.apm.serviceDetails.nodesTabLabel', { - defaultMessage: 'Metrics', - }), - hidden: isMetricsJVMsTabHidden({ agentName, runtimeName }), - }, { key: 'infrastructure', href: router.link('/services/{serviceName}/infrastructure', { diff --git a/x-pack/plugins/apm/public/components/shared/links/apm/service_node_metric_overview_link.tsx b/x-pack/plugins/apm/public/components/shared/links/apm/service_node_metric_overview_link.tsx index b8f0a0c53cb7d..8cb3bce94fc9d 100644 --- a/x-pack/plugins/apm/public/components/shared/links/apm/service_node_metric_overview_link.tsx +++ b/x-pack/plugins/apm/public/components/shared/links/apm/service_node_metric_overview_link.tsx @@ -30,9 +30,9 @@ export function useServiceNodeMetricOverviewHref({ serviceNodeName: string; }) { return useAPMHref({ - path: `/services/${serviceName}/nodes/${encodeURIComponent( + path: `/services/${serviceName}/metrics/${encodeURIComponent( serviceNodeName - )}/metrics`, + )}`, persistedFilters, }); } diff --git a/x-pack/plugins/apm/server/lib/apm_telemetry/collect_data_telemetry/tasks.ts b/x-pack/plugins/apm/server/lib/apm_telemetry/collect_data_telemetry/tasks.ts index 2235de6c0be9f..d114b31d75e3c 100644 --- a/x-pack/plugins/apm/server/lib/apm_telemetry/collect_data_telemetry/tasks.ts +++ b/x-pack/plugins/apm/server/lib/apm_telemetry/collect_data_telemetry/tasks.ts @@ -1159,13 +1159,16 @@ export const tasks: TelemetryTask[] = [ name: 'per_service', executor: async ({ indices, search }) => { const response = await search({ - index: [indices.metric], + index: [indices.transaction], body: { size: 0, timeout, query: { bool: { - filter: [{ range: { '@timestamp': { gte: 'now-1h' } } }], + filter: [ + { range: { '@timestamp': { gte: 'now-1h' } } }, + { term: { [PROCESSOR_EVENT]: ProcessorEvent.transaction } }, + ], }, }, aggs: { diff --git a/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/fake_synthetic_source.test.ts b/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/fake_synthetic_source.test.ts deleted file mode 100644 index e29c9714be4b6..0000000000000 --- a/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/fake_synthetic_source.test.ts +++ /dev/null @@ -1,92 +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 { fakeSyntheticSource } from './fake_synthetic_source'; - -describe('fakeSyntheticSource', () => { - it('flattens and unflattens objects', () => { - const obj = { - service: { - name: 'my-service', - }, - transaction: { - type: 'request', - name: 'GET /api/my-transaction', - }, - }; - - expect(fakeSyntheticSource(obj)).toEqual(obj); - }); - - it('drops null and undefined values', () => { - const obj = { - service: { - name: null, - }, - transaction: { - type: 'request', - name: 'GET /api/my-transaction', - }, - }; - - expect(fakeSyntheticSource(obj)).toEqual({ - transaction: { - type: 'request', - name: 'GET /api/my-transaction', - }, - }); - }); - - it('only wraps multiple values in an array', () => { - const obj = { - span: { - links: [ - { trace: { id: '1' }, span: { id: '1' } }, - { trace: { id: '2' }, span: { id: '2' } }, - ], - }, - }; - - expect(fakeSyntheticSource(obj)).toEqual({ - span: { - links: { - trace: { - id: ['1', '2'], - }, - span: { - id: ['1', '2'], - }, - }, - }, - }); - }); - - it('deduplicates and sorts array values', () => { - const obj = { - span: { - links: [ - { trace: { id: '3' }, span: { id: '1' } }, - { trace: { id: '1' }, span: { id: '1' } }, - { trace: { id: '1' }, span: { id: '4' } }, - ], - }, - }; - - expect(fakeSyntheticSource(obj)).toEqual({ - span: { - links: { - trace: { - id: ['1', '3'], - }, - span: { - id: ['1', '4'], - }, - }, - }, - }); - }); -}); diff --git a/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/fake_synthetic_source.ts b/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/fake_synthetic_source.ts deleted file mode 100644 index 4068691296e74..0000000000000 --- a/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/fake_synthetic_source.ts +++ /dev/null @@ -1,56 +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 { isArray, isObjectLike, set, uniq } from 'lodash'; - -function flatten( - target: Record, - source: Record, - toArray: boolean, - prefix: string = '' -) { - for (const key in source) { - if (!Object.hasOwn(source, key)) { - continue; - } - const value = source[key]; - if (value === undefined || value === null) { - continue; - } - const nextKey = `${prefix}${key}`; - if (isArray(value)) { - value.forEach((val) => { - flatten(target, val, true, `${nextKey}.`); - }); - } else if (isObjectLike(value)) { - flatten(target, value, toArray, `${nextKey}.`); - } else if (toArray && Array.isArray(target[nextKey])) { - target[nextKey].push(value); - } else if (toArray) { - target[nextKey] = [value]; - } else { - target[nextKey] = value; - } - } - return target; -} - -export function fakeSyntheticSource(object: Record) { - const flattened = flatten({}, object, false, ''); - - const unflattened = {}; - for (const key in flattened) { - if (!Object.hasOwn(flattened, key)) { - continue; - } - let val = flattened[key]; - if (Array.isArray(val)) { - val = uniq(val).sort(); - } - set(unflattened, key, val); - } - return unflattened; -} diff --git a/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/index.ts b/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/index.ts index 773d11f2ed139..f013448d6abe5 100644 --- a/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/index.ts +++ b/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/index.ts @@ -34,7 +34,6 @@ import { unpackProcessorEvents, processorEventsToIndex, } from './unpack_processor_events'; -import { fakeSyntheticSource } from './fake_synthetic_source'; export type APMEventESSearchRequest = Omit & { apm: { @@ -159,48 +158,9 @@ export class APMEventClient { return this.callAsyncWithDebug({ cb: (opts) => - ( - this.esClient.search(searchParams, opts) as unknown as Promise<{ - body: TypedSearchResponse; - }> - ).then((response) => { - // ensure metric data is compatible with synthetic source - // enabled - const metricEventsOnly = params.apm.events.every( - (event) => event === ProcessorEvent.metric - ); - - if (!response.body?.hits?.hits) { - return response; - } - - const hits = response.body.hits.hits.map((hit) => { - if ( - metricEventsOnly || - // take filter_path etc into account - (hit._source && - 'processor' in hit._source && - hit._source.processor?.event === ProcessorEvent.metric) - ) { - return { - ...hit, - _source: fakeSyntheticSource(hit._source), - }; - } - return hit; - }); - - return { - ...response, - body: { - ...response.body, - hits: { - ...response.body.hits, - hits, - }, - }, - }; - }), + this.esClient.search(searchParams, opts) as unknown as Promise<{ + body: TypedSearchResponse; + }>, operationName, params: searchParams, requestType: 'search', diff --git a/x-pack/plugins/apm/server/lib/helpers/get_service_inventory_search_source.ts b/x-pack/plugins/apm/server/lib/helpers/get_service_inventory_search_source.ts index 459eddfbdcc1f..c378e00c39253 100644 --- a/x-pack/plugins/apm/server/lib/helpers/get_service_inventory_search_source.ts +++ b/x-pack/plugins/apm/server/lib/helpers/get_service_inventory_search_source.ts @@ -5,8 +5,8 @@ * 2.0. */ import { APMEventClient } from './create_es_client/create_apm_event_client'; -import { getSearchAggregatedTransactions } from './transactions'; -import { getSearchAggregatedServiceMetrics } from './service_metrics'; +import { getSearchTransactionsEvents } from './transactions'; +import { getSearchServiceMetrics } from './service_metrics'; import { APMConfig } from '../..'; export async function getServiceInventorySearchSource({ @@ -35,8 +35,8 @@ export async function getServiceInventorySearchSource({ }; const [searchAggregatedTransactions, searchAggregatedServiceMetrics] = await Promise.all([ - getSearchAggregatedTransactions({ ...commonProps, config }), - getSearchAggregatedServiceMetrics({ + getSearchTransactionsEvents({ ...commonProps, config }), + getSearchServiceMetrics({ ...commonProps, serviceMetricsEnabled, }), diff --git a/x-pack/plugins/apm/server/lib/helpers/service_metrics/index.ts b/x-pack/plugins/apm/server/lib/helpers/service_metrics/index.ts index d0ba695c2240e..48936b644c2af 100644 --- a/x-pack/plugins/apm/server/lib/helpers/service_metrics/index.ts +++ b/x-pack/plugins/apm/server/lib/helpers/service_metrics/index.ts @@ -10,7 +10,7 @@ import { ProcessorEvent } from '@kbn/observability-plugin/common'; import { METRICSET_NAME } from '../../../../common/elasticsearch_fieldnames'; import { APMEventClient } from '../create_es_client/create_apm_event_client'; -export async function getSearchAggregatedServiceMetrics({ +export async function getSearchServiceMetrics({ serviceMetricsEnabled, start, end, @@ -24,7 +24,7 @@ export async function getSearchAggregatedServiceMetrics({ kuery: string; }): Promise { if (serviceMetricsEnabled) { - return getHasAggregatedServicesMetrics({ + return getHasServicesMetrics({ start, end, apmEventClient, @@ -35,7 +35,7 @@ export async function getSearchAggregatedServiceMetrics({ return false; } -export async function getHasAggregatedServicesMetrics({ +export async function getHasServicesMetrics({ start, end, apmEventClient, diff --git a/x-pack/plugins/apm/server/lib/helpers/transactions/get_is_using_transaction_events.ts b/x-pack/plugins/apm/server/lib/helpers/transactions/get_is_using_transaction_events.ts index f64b7f08e9077..409010d3c695d 100644 --- a/x-pack/plugins/apm/server/lib/helpers/transactions/get_is_using_transaction_events.ts +++ b/x-pack/plugins/apm/server/lib/helpers/transactions/get_is_using_transaction_events.ts @@ -7,7 +7,7 @@ import { kqlQuery, rangeQuery } from '@kbn/observability-plugin/server'; import { ProcessorEvent } from '@kbn/observability-plugin/common'; -import { getSearchAggregatedTransactions } from '.'; +import { getSearchTransactionsEvents } from '.'; import { Setup } from '../setup_request'; import { APMEventClient } from '../create_es_client/create_apm_event_client'; import { SearchAggregatedTransactionSetting } from '../../../../common/aggregated_transactions'; @@ -23,7 +23,7 @@ export async function getIsUsingTransactionEvents({ start?: number; end?: number; }): Promise { - const searchesAggregatedTransactions = await getSearchAggregatedTransactions({ + const searchesAggregatedTransactions = await getSearchTransactionsEvents({ config, start, end, diff --git a/x-pack/plugins/apm/server/lib/helpers/transactions/index.ts b/x-pack/plugins/apm/server/lib/helpers/transactions/index.ts index 6a52b2c39f59a..b6f7dfa4083e1 100644 --- a/x-pack/plugins/apm/server/lib/helpers/transactions/index.ts +++ b/x-pack/plugins/apm/server/lib/helpers/transactions/index.ts @@ -17,7 +17,7 @@ import { import { APMConfig } from '../../..'; import { APMEventClient } from '../create_es_client/create_apm_event_client'; -export async function getHasAggregatedTransactions({ +export async function getHasTransactionsEvents({ start, end, apmEventClient, @@ -54,7 +54,7 @@ export async function getHasAggregatedTransactions({ return response.hits.total.value > 0; } -export async function getSearchAggregatedTransactions({ +export async function getSearchTransactionsEvents({ config, start, end, @@ -70,11 +70,11 @@ export async function getSearchAggregatedTransactions({ switch (config.searchAggregatedTransactions) { case SearchAggregatedTransactionSetting.always: return kuery - ? getHasAggregatedTransactions({ start, end, apmEventClient, kuery }) + ? getHasTransactionsEvents({ start, end, apmEventClient, kuery }) : true; case SearchAggregatedTransactionSetting.auto: - return getHasAggregatedTransactions({ + return getHasTransactionsEvents({ start, end, apmEventClient, diff --git a/x-pack/plugins/apm/server/routes/alerts/chart_preview/get_transaction_duration.ts b/x-pack/plugins/apm/server/routes/alerts/chart_preview/get_transaction_duration.ts index 9636098fbbee5..06e5c29cdca18 100644 --- a/x-pack/plugins/apm/server/routes/alerts/chart_preview/get_transaction_duration.ts +++ b/x-pack/plugins/apm/server/routes/alerts/chart_preview/get_transaction_duration.ts @@ -14,7 +14,7 @@ import { import { environmentQuery } from '../../../../common/utils/environment_query'; import { AlertParams } from '../route'; import { - getSearchAggregatedTransactions, + getSearchTransactionsEvents, getDocumentTypeFilterForTransactions, getDurationFieldForTransactions, getProcessorEventForTransactions, @@ -38,7 +38,7 @@ export async function getTransactionDurationChartPreview({ start, end, } = alertParams; - const searchAggregatedTransactions = await getSearchAggregatedTransactions({ + const searchAggregatedTransactions = await getSearchTransactionsEvents({ ...setup, kuery: '', }); diff --git a/x-pack/plugins/apm/server/routes/alerts/chart_preview/get_transaction_error_rate.ts b/x-pack/plugins/apm/server/routes/alerts/chart_preview/get_transaction_error_rate.ts index 16ee19e3bce8b..48d04a856cb55 100644 --- a/x-pack/plugins/apm/server/routes/alerts/chart_preview/get_transaction_error_rate.ts +++ b/x-pack/plugins/apm/server/routes/alerts/chart_preview/get_transaction_error_rate.ts @@ -13,7 +13,7 @@ import { import { environmentQuery } from '../../../../common/utils/environment_query'; import { AlertParams } from '../route'; import { - getSearchAggregatedTransactions, + getSearchTransactionsEvents, getDocumentTypeFilterForTransactions, getProcessorEventForTransactions, } from '../../../lib/helpers/transactions'; @@ -34,7 +34,7 @@ export async function getTransactionErrorRateChartPreview({ const { serviceName, environment, transactionType, interval, start, end } = alertParams; - const searchAggregatedTransactions = await getSearchAggregatedTransactions({ + const searchAggregatedTransactions = await getSearchTransactionsEvents({ ...setup, kuery: '', start, diff --git a/x-pack/plugins/apm/server/routes/apm_routes/get_global_apm_server_route_repository.ts b/x-pack/plugins/apm/server/routes/apm_routes/get_global_apm_server_route_repository.ts index 0a6beb7f992d6..03971c6d115bf 100644 --- a/x-pack/plugins/apm/server/routes/apm_routes/get_global_apm_server_route_repository.ts +++ b/x-pack/plugins/apm/server/routes/apm_routes/get_global_apm_server_route_repository.ts @@ -29,7 +29,6 @@ import { observabilityOverviewRouteRepository } from '../observability_overview/ import { serviceRouteRepository } from '../services/route'; import { serviceGroupRouteRepository } from '../service_groups/route'; import { serviceMapRouteRepository } from '../service_map/route'; -import { serviceNodeRouteRepository } from '../service_nodes/route'; import { agentConfigurationRouteRepository } from '../settings/agent_configuration/route'; import { anomalyDetectionRouteRepository } from '../settings/anomaly_detection/route'; import { apmIndicesRouteRepository } from '../settings/apm_indices/route'; @@ -52,7 +51,6 @@ function getTypedGlobalApmServerRouteRepository() { ...metricsRouteRepository, ...observabilityOverviewRouteRepository, ...serviceMapRouteRepository, - ...serviceNodeRouteRepository, ...serviceRouteRepository, ...serviceGroupRouteRepository, ...suggestionsRouteRepository, diff --git a/x-pack/plugins/apm/server/routes/environments/route.ts b/x-pack/plugins/apm/server/routes/environments/route.ts index 03fb07fd51cb8..4a7755230754c 100644 --- a/x-pack/plugins/apm/server/routes/environments/route.ts +++ b/x-pack/plugins/apm/server/routes/environments/route.ts @@ -7,7 +7,7 @@ import * as t from 'io-ts'; import { maxSuggestions } from '@kbn/observability-plugin/common'; -import { getSearchAggregatedTransactions } from '../../lib/helpers/transactions'; +import { getSearchTransactionsEvents } from '../../lib/helpers/transactions'; import { setupRequest } from '../../lib/helpers/setup_request'; import { getEnvironments } from './get_environments'; import { rangeRt } from '../default_api_types'; @@ -39,7 +39,7 @@ const environmentsRoute = createApmServerRoute({ const setup = await setupRequest(resources); const { context, params } = resources; const { serviceName, start, end } = params.query; - const searchAggregatedTransactions = await getSearchAggregatedTransactions({ + const searchAggregatedTransactions = await getSearchTransactionsEvents({ apmEventClient: setup.apmEventClient, config: setup.config, start, diff --git a/x-pack/plugins/apm/server/routes/fleet/get_latest_apm_package.ts b/x-pack/plugins/apm/server/routes/fleet/get_latest_apm_package.ts index c7cd083fbda80..671b4d56dad94 100644 --- a/x-pack/plugins/apm/server/routes/fleet/get_latest_apm_package.ts +++ b/x-pack/plugins/apm/server/routes/fleet/get_latest_apm_package.ts @@ -20,7 +20,7 @@ export async function getLatestApmPackage({ const { name, version } = await packageClient.fetchFindLatestPackage( APM_PACKAGE_NAME ); - const registryPackage = await packageClient.getRegistryPackage(name, version); + const registryPackage = await packageClient.getPackage(name, version); const { title, policy_templates: policyTemplates } = registryPackage.packageInfo; const firstTemplate = policyTemplates?.[0]; diff --git a/x-pack/plugins/apm/server/routes/latency_distribution/route.ts b/x-pack/plugins/apm/server/routes/latency_distribution/route.ts index 7eaaa6e641030..ac0e65abe3157 100644 --- a/x-pack/plugins/apm/server/routes/latency_distribution/route.ts +++ b/x-pack/plugins/apm/server/routes/latency_distribution/route.ts @@ -11,7 +11,7 @@ import { termQuery } from '@kbn/observability-plugin/server'; import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { getOverallLatencyDistribution } from './get_overall_latency_distribution'; import { setupRequest } from '../../lib/helpers/setup_request'; -import { getSearchAggregatedTransactions } from '../../lib/helpers/transactions'; +import { getSearchTransactionsEvents } from '../../lib/helpers/transactions'; import { createApmServerRoute } from '../apm_routes/create_apm_server_route'; import { environmentRt, kueryRt, rangeRt } from '../default_api_types'; import { @@ -74,7 +74,7 @@ const latencyOverallTransactionDistributionRoute = createApmServerRoute({ // only the transaction latency distribution chart can use metrics data const searchAggregatedTransactions = chartType === LatencyDistributionChartType.transactionLatency - ? await getSearchAggregatedTransactions({ + ? await getSearchTransactionsEvents({ ...setup, kuery, start, diff --git a/x-pack/plugins/apm/server/routes/metrics/by_agent/serverless/index.ts b/x-pack/plugins/apm/server/routes/metrics/by_agent/serverless/index.ts index 9200e9d07e1ce..5635dd5c0e50b 100644 --- a/x-pack/plugins/apm/server/routes/metrics/by_agent/serverless/index.ts +++ b/x-pack/plugins/apm/server/routes/metrics/by_agent/serverless/index.ts @@ -13,7 +13,7 @@ import { getMemoryChartData } from '../shared/memory'; import { getComputeUsage } from './compute_usage'; import { getActiveInstances } from './active_instances'; import { getColdStartCount } from './cold_start_count'; -import { getSearchAggregatedTransactions } from '../../../../lib/helpers/transactions'; +import { getSearchTransactionsEvents } from '../../../../lib/helpers/transactions'; export function getServerlessAgentMetricCharts({ environment, @@ -31,7 +31,7 @@ export function getServerlessAgentMetricCharts({ end: number; }) { return withApmSpan('get_serverless_agent_metric_charts', async () => { - const searchAggregatedTransactions = await getSearchAggregatedTransactions({ + const searchAggregatedTransactions = await getSearchTransactionsEvents({ ...setup, kuery, start, diff --git a/x-pack/plugins/apm/server/routes/service_nodes/get_service_nodes.ts b/x-pack/plugins/apm/server/routes/metrics/get_service_nodes.ts similarity index 100% rename from x-pack/plugins/apm/server/routes/service_nodes/get_service_nodes.ts rename to x-pack/plugins/apm/server/routes/metrics/get_service_nodes.ts diff --git a/x-pack/plugins/apm/server/routes/metrics/route.ts b/x-pack/plugins/apm/server/routes/metrics/route.ts index 5d6b4f245c568..8aea9cc5a981c 100644 --- a/x-pack/plugins/apm/server/routes/metrics/route.ts +++ b/x-pack/plugins/apm/server/routes/metrics/route.ts @@ -11,6 +11,7 @@ import { createApmServerRoute } from '../apm_routes/create_apm_server_route'; import { environmentRt, kueryRt, rangeRt } from '../default_api_types'; import { FetchAndTransformMetrics } from './fetch_and_transform_metrics'; import { getMetricsChartDataByAgent } from './get_metrics_chart_data_by_agent'; +import { getServiceNodes } from './get_service_nodes'; const metricsChartsRoute = createApmServerRoute({ endpoint: 'GET /internal/apm/services/{serviceName}/metrics/charts', @@ -66,4 +67,45 @@ const metricsChartsRoute = createApmServerRoute({ }, }); -export const metricsRouteRepository = metricsChartsRoute; +const serviceMetricsJvm = createApmServerRoute({ + endpoint: 'GET /internal/apm/services/{serviceName}/metrics/nodes', + params: t.type({ + path: t.type({ + serviceName: t.string, + }), + query: t.intersection([kueryRt, rangeRt, environmentRt]), + }), + options: { tags: ['access:apm'] }, + handler: async ( + resources + ): Promise<{ + serviceNodes: Array<{ + name: string; + cpu: number | null; + heapMemory: number | null; + hostName: string | null | undefined; + nonHeapMemory: number | null; + threadCount: number | null; + }>; + }> => { + const setup = await setupRequest(resources); + const { params } = resources; + const { serviceName } = params.path; + const { kuery, environment, start, end } = params.query; + + const serviceNodes = await getServiceNodes({ + kuery, + setup, + serviceName, + environment, + start, + end, + }); + return { serviceNodes }; + }, +}); + +export const metricsRouteRepository = { + ...metricsChartsRoute, + ...serviceMetricsJvm, +}; diff --git a/x-pack/plugins/apm/server/routes/observability_overview/route.ts b/x-pack/plugins/apm/server/routes/observability_overview/route.ts index e32c04b849664..4ed5332801ef3 100644 --- a/x-pack/plugins/apm/server/routes/observability_overview/route.ts +++ b/x-pack/plugins/apm/server/routes/observability_overview/route.ts @@ -12,7 +12,7 @@ import { getServiceCount } from './get_service_count'; import { getTransactionsPerMinute } from './get_transactions_per_minute'; import { getHasData } from './has_data'; import { rangeRt } from '../default_api_types'; -import { getSearchAggregatedTransactions } from '../../lib/helpers/transactions'; +import { getSearchTransactionsEvents } from '../../lib/helpers/transactions'; import { withApmSpan } from '../../utils/with_apm_span'; import { createApmServerRoute } from '../apm_routes/create_apm_server_route'; @@ -50,7 +50,7 @@ const observabilityOverviewRoute = createApmServerRoute({ const setup = await setupRequest(resources); const { bucketSize, intervalString, start, end } = resources.params.query; - const searchAggregatedTransactions = await getSearchAggregatedTransactions({ + const searchAggregatedTransactions = await getSearchTransactionsEvents({ apmEventClient: setup.apmEventClient, config: setup.config, start, diff --git a/x-pack/plugins/apm/server/routes/service_map/route.ts b/x-pack/plugins/apm/server/routes/service_map/route.ts index 5c07b68fb0bd2..c2de9bf956a85 100644 --- a/x-pack/plugins/apm/server/routes/service_map/route.ts +++ b/x-pack/plugins/apm/server/routes/service_map/route.ts @@ -12,7 +12,7 @@ import { apmServiceGroupMaxNumberOfServices } from '@kbn/observability-plugin/co import { isActivePlatinumLicense } from '../../../common/license_check'; import { invalidLicenseMessage } from '../../../common/service_map'; import { notifyFeatureUsage } from '../../feature'; -import { getSearchAggregatedTransactions } from '../../lib/helpers/transactions'; +import { getSearchTransactionsEvents } from '../../lib/helpers/transactions'; import { setupRequest } from '../../lib/helpers/setup_request'; import { getServiceMap } from './get_service_map'; import { getServiceMapDependencyNodeInfo } from './get_service_map_dependency_node_info'; @@ -128,7 +128,7 @@ const serviceMapRoute = createApmServerRoute({ const serviceNames = compact([serviceName]); - const searchAggregatedTransactions = await getSearchAggregatedTransactions({ + const searchAggregatedTransactions = await getSearchTransactionsEvents({ apmEventClient: setup.apmEventClient, config: setup.config, start, @@ -183,7 +183,7 @@ const serviceMapServiceNodeRoute = createApmServerRoute({ query: { environment, start, end, offset }, } = params; - const searchAggregatedTransactions = await getSearchAggregatedTransactions({ + const searchAggregatedTransactions = await getSearchTransactionsEvents({ apmEventClient: setup.apmEventClient, config: setup.config, start, diff --git a/x-pack/plugins/apm/server/routes/service_nodes/__snapshots__/queries.test.ts.snap b/x-pack/plugins/apm/server/routes/service_nodes/__snapshots__/queries.test.ts.snap deleted file mode 100644 index 38719f84994a3..0000000000000 --- a/x-pack/plugins/apm/server/routes/service_nodes/__snapshots__/queries.test.ts.snap +++ /dev/null @@ -1,200 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`service node queries fetches metadata for a service node 1`] = ` -Object { - "apm": Object { - "events": Array [ - "metric", - ], - }, - "body": Object { - "aggs": Object { - "containerId": Object { - "terms": Object { - "field": "container.id", - "size": 1, - }, - }, - "host": Object { - "terms": Object { - "field": "host.name", - "size": 1, - }, - }, - "nodes": Object { - "terms": Object { - "field": "service.node.name", - }, - }, - }, - "query": Object { - "bool": Object { - "filter": Array [ - Object { - "term": Object { - "service.name": "foo", - }, - }, - Object { - "range": Object { - "@timestamp": Object { - "format": "epoch_millis", - "gte": 0, - "lte": 50000, - }, - }, - }, - Object { - "term": Object { - "service.node.name": "bar", - }, - }, - ], - }, - }, - "size": 0, - "track_total_hits": false, - }, -} -`; - -exports[`service node queries fetches metadata for unidentified service nodes 1`] = ` -Object { - "apm": Object { - "events": Array [ - "metric", - ], - }, - "body": Object { - "aggs": Object { - "containerId": Object { - "terms": Object { - "field": "container.id", - "size": 1, - }, - }, - "host": Object { - "terms": Object { - "field": "host.name", - "size": 1, - }, - }, - "nodes": Object { - "terms": Object { - "field": "service.node.name", - }, - }, - }, - "query": Object { - "bool": Object { - "filter": Array [ - Object { - "term": Object { - "service.name": "foo", - }, - }, - Object { - "range": Object { - "@timestamp": Object { - "format": "epoch_millis", - "gte": 0, - "lte": 50000, - }, - }, - }, - Object { - "bool": Object { - "must_not": Array [ - Object { - "exists": Object { - "field": "service.node.name", - }, - }, - ], - }, - }, - ], - }, - }, - "size": 0, - "track_total_hits": false, - }, -} -`; - -exports[`service node queries fetches services nodes 1`] = ` -Object { - "apm": Object { - "events": Array [ - "metric", - ], - }, - "body": Object { - "aggs": Object { - "nodes": Object { - "aggs": Object { - "cpu": Object { - "avg": Object { - "field": "system.process.cpu.total.norm.pct", - }, - }, - "heapMemory": Object { - "avg": Object { - "field": "jvm.memory.heap.used", - }, - }, - "latest": Object { - "top_metrics": Object { - "metrics": Array [ - Object { - "field": "host.name", - }, - ], - "sort": Object { - "@timestamp": "desc", - }, - }, - }, - "nonHeapMemory": Object { - "avg": Object { - "field": "jvm.memory.non_heap.used", - }, - }, - "threadCount": Object { - "max": Object { - "field": "jvm.thread.count", - }, - }, - }, - "terms": Object { - "field": "service.node.name", - "missing": "_service_node_name_missing_", - "size": 10000, - }, - }, - }, - "query": Object { - "bool": Object { - "filter": Array [ - Object { - "term": Object { - "service.name": "foo", - }, - }, - Object { - "range": Object { - "@timestamp": Object { - "format": "epoch_millis", - "gte": 0, - "lte": 50000, - }, - }, - }, - ], - }, - }, - "size": 0, - "track_total_hits": false, - }, -} -`; diff --git a/x-pack/plugins/apm/server/routes/service_nodes/queries.test.ts b/x-pack/plugins/apm/server/routes/service_nodes/queries.test.ts deleted file mode 100644 index 470be6142aaed..0000000000000 --- a/x-pack/plugins/apm/server/routes/service_nodes/queries.test.ts +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { getServiceNodes } from './get_service_nodes'; -import { - SearchParamsMock, - inspectSearchParams, -} from '../../utils/test_helpers'; -import { getServiceNodeMetadata } from '../services/get_service_node_metadata'; -import { SERVICE_NODE_NAME_MISSING } from '../../../common/service_nodes'; -import { ENVIRONMENT_ALL } from '../../../common/environment_filter_values'; - -describe('service node queries', () => { - let mock: SearchParamsMock; - - afterEach(() => { - mock.teardown(); - }); - - it('fetches services nodes', async () => { - mock = await inspectSearchParams((setup) => - getServiceNodes({ - setup, - serviceName: 'foo', - kuery: '', - environment: ENVIRONMENT_ALL.value, - start: 0, - end: 50000, - }) - ); - - expect(mock.params).toMatchSnapshot(); - }); - - it('fetches metadata for a service node', async () => { - mock = await inspectSearchParams((setup) => - getServiceNodeMetadata({ - setup, - serviceName: 'foo', - serviceNodeName: 'bar', - kuery: '', - start: 0, - end: 50000, - }) - ); - - expect(mock.params).toMatchSnapshot(); - }); - - it('fetches metadata for unidentified service nodes', async () => { - mock = await inspectSearchParams((setup) => - getServiceNodeMetadata({ - setup, - serviceName: 'foo', - serviceNodeName: SERVICE_NODE_NAME_MISSING, - kuery: '', - start: 0, - end: 50000, - }) - ); - - expect(mock.params).toMatchSnapshot(); - }); -}); diff --git a/x-pack/plugins/apm/server/routes/service_nodes/route.ts b/x-pack/plugins/apm/server/routes/service_nodes/route.ts deleted file mode 100644 index eef2b29b1e373..0000000000000 --- a/x-pack/plugins/apm/server/routes/service_nodes/route.ts +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import * as t from 'io-ts'; -import { createApmServerRoute } from '../apm_routes/create_apm_server_route'; -import { setupRequest } from '../../lib/helpers/setup_request'; -import { getServiceNodes } from './get_service_nodes'; -import { rangeRt, kueryRt } from '../default_api_types'; -import { environmentRt } from '../../../common/environment_rt'; - -const serviceNodesRoute = createApmServerRoute({ - endpoint: 'GET /internal/apm/services/{serviceName}/serviceNodes', - params: t.type({ - path: t.type({ - serviceName: t.string, - }), - query: t.intersection([kueryRt, rangeRt, environmentRt]), - }), - options: { tags: ['access:apm'] }, - handler: async ( - resources - ): Promise<{ - serviceNodes: Array<{ - name: string; - cpu: number | null; - heapMemory: number | null; - hostName: string | null | undefined; - nonHeapMemory: number | null; - threadCount: number | null; - }>; - }> => { - const setup = await setupRequest(resources); - const { params } = resources; - const { serviceName } = params.path; - const { kuery, environment, start, end } = params.query; - - const serviceNodes = await getServiceNodes({ - kuery, - setup, - serviceName, - environment, - start, - end, - }); - return { serviceNodes }; - }, -}); - -export const serviceNodeRouteRepository = serviceNodesRoute; diff --git a/x-pack/plugins/apm/server/routes/services/route.ts b/x-pack/plugins/apm/server/routes/services/route.ts index 79ff09101aeca..1f1cac260331f 100644 --- a/x-pack/plugins/apm/server/routes/services/route.ts +++ b/x-pack/plugins/apm/server/routes/services/route.ts @@ -19,7 +19,7 @@ import { ScopedAnnotationsClient } from '@kbn/observability-plugin/server'; import { Annotation } from '@kbn/observability-plugin/common/annotations'; import { apmServiceGroupMaxNumberOfServices } from '@kbn/observability-plugin/common'; import { latencyAggregationTypeRt } from '../../../common/latency_aggregation_types'; -import { getSearchAggregatedTransactions } from '../../lib/helpers/transactions'; +import { getSearchTransactionsEvents } from '../../lib/helpers/transactions'; import { getServiceInventorySearchSource } from '../../lib/helpers/get_service_inventory_search_source'; import { setupRequest } from '../../lib/helpers/setup_request'; import { getServiceAnnotations } from './annotations'; @@ -280,7 +280,7 @@ const serviceMetadataDetailsRoute = createApmServerRoute({ const { serviceName } = params.path; const { start, end } = params.query; - const searchAggregatedTransactions = await getSearchAggregatedTransactions({ + const searchAggregatedTransactions = await getSearchTransactionsEvents({ apmEventClient: setup.apmEventClient, config: setup.config, start, @@ -326,7 +326,7 @@ const serviceMetadataIconsRoute = createApmServerRoute({ const { serviceName } = params.path; const { start, end } = params.query; - const searchAggregatedTransactions = await getSearchAggregatedTransactions({ + const searchAggregatedTransactions = await getSearchTransactionsEvents({ apmEventClient: setup.apmEventClient, config: setup.config, start, @@ -391,7 +391,7 @@ const serviceTransactionTypesRoute = createApmServerRoute({ return getServiceTransactionTypes({ serviceName, setup, - searchAggregatedTransactions: await getSearchAggregatedTransactions({ + searchAggregatedTransactions: await getSearchTransactionsEvents({ apmEventClient: setup.apmEventClient, config: setup.config, start, @@ -465,7 +465,7 @@ const serviceAnnotationsRoute = createApmServerRoute({ observability.setup.getScopedAnnotationsClient(context, request) ) : undefined, - getSearchAggregatedTransactions({ + getSearchTransactionsEvents({ apmEventClient: setup.apmEventClient, config: setup.config, start, @@ -598,7 +598,7 @@ const serviceThroughputRoute = createApmServerRoute({ start, end, } = params.query; - const searchAggregatedTransactions = await getSearchAggregatedTransactions({ + const searchAggregatedTransactions = await getSearchTransactionsEvents({ ...setup, kuery, start, @@ -693,7 +693,7 @@ const serviceInstancesMainStatisticsRoute = createApmServerRoute({ end, } = params.query; - const searchAggregatedTransactions = await getSearchAggregatedTransactions({ + const searchAggregatedTransactions = await getSearchTransactionsEvents({ ...setup, kuery, start, @@ -815,7 +815,7 @@ const serviceInstancesDetailedStatisticsRoute = createApmServerRoute({ end, } = params.query; - const searchAggregatedTransactions = await getSearchAggregatedTransactions({ + const searchAggregatedTransactions = await getSearchTransactionsEvents({ ...setup, kuery, start, diff --git a/x-pack/plugins/apm/server/routes/settings/agent_configuration/route.ts b/x-pack/plugins/apm/server/routes/settings/agent_configuration/route.ts index 5c247d469bfda..eb04de4430381 100644 --- a/x-pack/plugins/apm/server/routes/settings/agent_configuration/route.ts +++ b/x-pack/plugins/apm/server/routes/settings/agent_configuration/route.ts @@ -23,7 +23,7 @@ import { serviceRt, agentConfigurationIntakeRt, } from '../../../../common/agent_configuration/runtime_types/agent_configuration_intake_rt'; -import { getSearchAggregatedTransactions } from '../../../lib/helpers/transactions'; +import { getSearchTransactionsEvents } from '../../../lib/helpers/transactions'; import { syncAgentConfigsToApmPackagePolicies } from '../../fleet/sync_agent_configs_to_apm_package_policies'; // get list of configurations @@ -274,7 +274,7 @@ const listAgentConfigurationEnvironmentsRoute = createApmServerRoute({ const coreContext = await context.core; const { serviceName, start, end } = params.query; - const searchAggregatedTransactions = await getSearchAggregatedTransactions({ + const searchAggregatedTransactions = await getSearchTransactionsEvents({ apmEventClient: setup.apmEventClient, config: setup.config, kuery: '', diff --git a/x-pack/plugins/apm/server/routes/settings/anomaly_detection/route.ts b/x-pack/plugins/apm/server/routes/settings/anomaly_detection/route.ts index fa15ef06ff16a..e30f669b9cd7b 100644 --- a/x-pack/plugins/apm/server/routes/settings/anomaly_detection/route.ts +++ b/x-pack/plugins/apm/server/routes/settings/anomaly_detection/route.ts @@ -15,7 +15,7 @@ import { createApmServerRoute } from '../../apm_routes/create_apm_server_route'; import { createAnomalyDetectionJobs } from '../../../lib/anomaly_detection/create_anomaly_detection_jobs'; import { setupRequest } from '../../../lib/helpers/setup_request'; import { getAllEnvironments } from '../../environments/get_all_environments'; -import { getSearchAggregatedTransactions } from '../../../lib/helpers/transactions'; +import { getSearchTransactionsEvents } from '../../../lib/helpers/transactions'; import { notifyFeatureUsage } from '../../../feature'; import { updateToV3 } from './update_to_v3'; import { environmentStringRt } from '../../../../common/environment_rt'; @@ -97,7 +97,7 @@ const anomalyDetectionEnvironmentsRoute = createApmServerRoute({ const setup = await setupRequest(resources); const coreContext = await resources.context.core; - const searchAggregatedTransactions = await getSearchAggregatedTransactions({ + const searchAggregatedTransactions = await getSearchTransactionsEvents({ apmEventClient: setup.apmEventClient, config: setup.config, kuery: '', diff --git a/x-pack/plugins/apm/server/routes/storage_explorer/route.ts b/x-pack/plugins/apm/server/routes/storage_explorer/route.ts index 7ee36fae5493c..9d817efbf34f5 100644 --- a/x-pack/plugins/apm/server/routes/storage_explorer/route.ts +++ b/x-pack/plugins/apm/server/routes/storage_explorer/route.ts @@ -10,7 +10,7 @@ import { ProcessorEvent } from '@kbn/observability-plugin/common'; import Boom from '@hapi/boom'; import { i18n } from '@kbn/i18n'; import { createApmServerRoute } from '../apm_routes/create_apm_server_route'; -import { getSearchAggregatedTransactions } from '../../lib/helpers/transactions'; +import { getSearchTransactionsEvents } from '../../lib/helpers/transactions'; import { setupRequest } from '../../lib/helpers/setup_request'; import { indexLifecyclePhaseRt } from '../../../common/storage_explorer_types'; import { getServiceStatistics } from './get_service_statistics'; @@ -76,7 +76,7 @@ const storageExplorerRoute = createApmServerRoute({ getRandomSampler({ security, request, probability }), ]); - const searchAggregatedTransactions = await getSearchAggregatedTransactions({ + const searchAggregatedTransactions = await getSearchTransactionsEvents({ apmEventClient: setup.apmEventClient, config: setup.config, kuery, @@ -211,7 +211,7 @@ const storageChartRoute = createApmServerRoute({ getRandomSampler({ security, request, probability }), ]); - const searchAggregatedTransactions = await getSearchAggregatedTransactions({ + const searchAggregatedTransactions = await getSearchTransactionsEvents({ apmEventClient: setup.apmEventClient, config: setup.config, kuery, @@ -300,7 +300,7 @@ const storageExplorerSummaryStatsRoute = createApmServerRoute({ getRandomSampler({ security, request, probability }), ]); - const searchAggregatedTransactions = await getSearchAggregatedTransactions({ + const searchAggregatedTransactions = await getSearchTransactionsEvents({ apmEventClient: setup.apmEventClient, config: setup.config, kuery, diff --git a/x-pack/plugins/apm/server/routes/suggestions/route.ts b/x-pack/plugins/apm/server/routes/suggestions/route.ts index 68f94634a5ded..92a64da42eca3 100644 --- a/x-pack/plugins/apm/server/routes/suggestions/route.ts +++ b/x-pack/plugins/apm/server/routes/suggestions/route.ts @@ -9,7 +9,7 @@ import * as t from 'io-ts'; import { maxSuggestions } from '@kbn/observability-plugin/common'; import { getSuggestions } from './get_suggestions'; import { getSuggestionsWithTermsAggregation } from './get_suggestions_with_terms_aggregation'; -import { getSearchAggregatedTransactions } from '../../lib/helpers/transactions'; +import { getSearchTransactionsEvents } from '../../lib/helpers/transactions'; import { setupRequest } from '../../lib/helpers/setup_request'; import { createApmServerRoute } from '../apm_routes/create_apm_server_route'; import { rangeRt } from '../default_api_types'; @@ -31,7 +31,7 @@ const suggestionsRoute = createApmServerRoute({ const setup = await setupRequest(resources); const { context, params } = resources; const { fieldName, fieldValue, serviceName, start, end } = params.query; - const searchAggregatedTransactions = await getSearchAggregatedTransactions({ + const searchAggregatedTransactions = await getSearchTransactionsEvents({ apmEventClient: setup.apmEventClient, config: setup.config, kuery: '', diff --git a/x-pack/plugins/apm/server/routes/traces/route.ts b/x-pack/plugins/apm/server/routes/traces/route.ts index 9884aafaf25f3..4036495a18076 100644 --- a/x-pack/plugins/apm/server/routes/traces/route.ts +++ b/x-pack/plugins/apm/server/routes/traces/route.ts @@ -8,7 +8,7 @@ import * as t from 'io-ts'; import { TraceSearchType } from '../../../common/trace_explorer'; import { setupRequest } from '../../lib/helpers/setup_request'; -import { getSearchAggregatedTransactions } from '../../lib/helpers/transactions'; +import { getSearchTransactionsEvents } from '../../lib/helpers/transactions'; import { createApmServerRoute } from '../apm_routes/create_apm_server_route'; import { environmentRt, @@ -56,7 +56,7 @@ const tracesRoute = createApmServerRoute({ getRandomSampler({ security, request, probability }), ]); - const searchAggregatedTransactions = await getSearchAggregatedTransactions({ + const searchAggregatedTransactions = await getSearchTransactionsEvents({ ...setup, kuery, start, diff --git a/x-pack/plugins/apm/server/routes/transactions/route.ts b/x-pack/plugins/apm/server/routes/transactions/route.ts index a96e4416e49e8..3bc4dbfe7aae7 100644 --- a/x-pack/plugins/apm/server/routes/transactions/route.ts +++ b/x-pack/plugins/apm/server/routes/transactions/route.ts @@ -11,7 +11,7 @@ import { LatencyAggregationType, latencyAggregationTypeRt, } from '../../../common/latency_aggregation_types'; -import { getSearchAggregatedTransactions } from '../../lib/helpers/transactions'; +import { getSearchTransactionsEvents } from '../../lib/helpers/transactions'; import { setupRequest } from '../../lib/helpers/setup_request'; import { getServiceTransactionGroups } from '../services/get_service_transaction_groups'; import { getServiceTransactionGroupDetailedStatisticsPeriods } from '../services/get_service_transaction_group_detailed_statistics'; @@ -70,7 +70,7 @@ const transactionGroupsMainStatisticsRoute = createApmServerRoute({ }, } = params; - const searchAggregatedTransactions = await getSearchAggregatedTransactions({ + const searchAggregatedTransactions = await getSearchTransactionsEvents({ ...setup, kuery, start, @@ -157,7 +157,7 @@ const transactionGroupsDetailedStatisticsRoute = createApmServerRoute({ }, } = params; - const searchAggregatedTransactions = await getSearchAggregatedTransactions({ + const searchAggregatedTransactions = await getSearchTransactionsEvents({ ...setup, kuery, start, @@ -236,7 +236,7 @@ const transactionLatencyChartsRoute = createApmServerRoute({ offset, } = params.query; - const searchAggregatedTransactions = await getSearchAggregatedTransactions({ + const searchAggregatedTransactions = await getSearchTransactionsEvents({ ...setup, kuery, start, @@ -430,7 +430,7 @@ const transactionChartsErrorRateRoute = createApmServerRoute({ offset, } = params.query; - const searchAggregatedTransactions = await getSearchAggregatedTransactions({ + const searchAggregatedTransactions = await getSearchTransactionsEvents({ ...setup, kuery, start, @@ -497,7 +497,7 @@ const transactionChartsColdstartRateRoute = createApmServerRoute({ const { environment, kuery, transactionType, start, end, offset } = params.query; - const searchAggregatedTransactions = await getSearchAggregatedTransactions({ + const searchAggregatedTransactions = await getSearchTransactionsEvents({ ...setup, kuery, start, @@ -571,13 +571,12 @@ const transactionChartsColdstartRateByTransactionNameRoute = offset, } = params.query; - const searchAggregatedTransactions = - await getSearchAggregatedTransactions({ - ...setup, - kuery, - start, - end, - }); + const searchAggregatedTransactions = await getSearchTransactionsEvents({ + ...setup, + kuery, + start, + end, + }); return getColdstartRatePeriods({ environment, diff --git a/x-pack/plugins/cases/common/api/cases/status.ts b/x-pack/plugins/cases/common/api/cases/status.ts index fa3b584f07286..0f06712e7f925 100644 --- a/x-pack/plugins/cases/common/api/cases/status.ts +++ b/x-pack/plugins/cases/common/api/cases/status.ts @@ -6,12 +6,9 @@ */ import * as rt from 'io-ts'; +import { CaseStatuses } from '@kbn/cases-components'; -export enum CaseStatuses { - open = 'open', - 'in-progress' = 'in-progress', - closed = 'closed', -} +export { CaseStatuses }; export const CaseStatusRt = rt.union([ rt.literal(CaseStatuses.open), diff --git a/x-pack/plugins/cases/common/constants.ts b/x-pack/plugins/cases/common/constants.ts index e7b7f565ad599..3c8f422d4eb7a 100644 --- a/x-pack/plugins/cases/common/constants.ts +++ b/x-pack/plugins/cases/common/constants.ts @@ -4,6 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ +import { CASE_VIEW_PAGE_TABS } from './types'; import { CasesFeaturesAllRequired } from './ui/types'; export const DEFAULT_DATE_FORMAT = 'dateFormat' as const; @@ -17,6 +18,14 @@ export const APP_ID = 'cases' as const; export const FEATURE_ID = 'generalCases' as const; export const APP_OWNER = 'cases' as const; export const APP_PATH = '/app/management/insightsAndAlerting/cases' as const; +export const CASES_CREATE_PATH = '/create' as const; +export const CASES_CONFIGURE_PATH = '/configure' as const; +export const CASE_VIEW_PATH = '/:detailName' as const; +export const CASE_VIEW_COMMENT_PATH = `${CASE_VIEW_PATH}/:commentId` as const; +export const CASE_VIEW_ALERT_TABLE_PATH = + `${CASE_VIEW_PATH}/?tabId=${CASE_VIEW_PAGE_TABS.ALERTS}` as const; +export const CASE_VIEW_TAB_PATH = `${CASE_VIEW_PATH}/?tabId=:tabId` as const; + /** * The main Cases application is in the stack management under the * Alerts and Insights section. To do that, Cases registers to the management @@ -106,16 +115,19 @@ export const OWNER_INFO = { appId: 'securitySolutionUI', label: 'Security', iconType: 'logoSecurity', + appRoute: '/app/security', }, [OBSERVABILITY_OWNER]: { appId: 'observability-overview', label: 'Observability', iconType: 'logoObservability', + appRoute: '/app/observability', }, [GENERAL_CASES_OWNER]: { appId: 'management', label: 'Stack', iconType: 'casesApp', + appRoute: '/app/management/insightsAndAlerting', }, } as const; diff --git a/x-pack/plugins/cases/common/types.ts b/x-pack/plugins/cases/common/types.ts index b6fb90d2923fd..95525bd980927 100644 --- a/x-pack/plugins/cases/common/types.ts +++ b/x-pack/plugins/cases/common/types.ts @@ -14,3 +14,8 @@ export type SnakeToCamelCase = T extends Record [K in keyof T as SnakeToCamelCaseString]: SnakeToCamelCase; } : T; + +export enum CASE_VIEW_PAGE_TABS { + ALERTS = 'alerts', + ACTIVITY = 'activity', +} diff --git a/x-pack/plugins/cases/common/utils/owner.test.ts b/x-pack/plugins/cases/common/utils/owner.test.ts new file mode 100644 index 0000000000000..09016880c0a95 --- /dev/null +++ b/x-pack/plugins/cases/common/utils/owner.test.ts @@ -0,0 +1,21 @@ +/* + * 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 { OWNER_INFO } from '../constants'; +import { isValidOwner } from './owner'; + +describe('isValidOwner', () => { + const owners = Object.keys(OWNER_INFO) as Array; + + it.each(owners)('returns true for valid owner: %s', (owner) => { + expect(isValidOwner(owner)).toBe(true); + }); + + it('return false for invalid owner', () => { + expect(isValidOwner('not-valid')).toBe(false); + }); +}); diff --git a/x-pack/plugins/cases/common/utils/owner.ts b/x-pack/plugins/cases/common/utils/owner.ts new file mode 100644 index 0000000000000..44068f36f0d3f --- /dev/null +++ b/x-pack/plugins/cases/common/utils/owner.ts @@ -0,0 +1,11 @@ +/* + * 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 { OWNER_INFO } from '../constants'; + +export const isValidOwner = (owner: string): owner is keyof typeof OWNER_INFO => + Object.keys(OWNER_INFO).includes(owner); diff --git a/x-pack/plugins/cases/public/api/__mocks__/index.ts b/x-pack/plugins/cases/public/api/__mocks__/index.ts index 1632394338a47..16707fb6aa959 100644 --- a/x-pack/plugins/cases/public/api/__mocks__/index.ts +++ b/x-pack/plugins/cases/public/api/__mocks__/index.ts @@ -5,10 +5,10 @@ * 2.0. */ -import { CasesFindRequest, CasesMetricsRequest } from '../../../common/api'; -import { HTTPService } from '..'; +import type { CasesFindRequest, CasesMetricsRequest } from '../../../common/api'; +import type { HTTPService } from '..'; import { casesMetrics, casesStatus } from '../../containers/mock'; -import { CasesMetrics, CasesStatus } from '../../containers/types'; +import type { CasesMetrics, CasesStatus } from '../../containers/types'; export const getCasesStatus = async ({ http, diff --git a/x-pack/plugins/cases/public/api/decoders.ts b/x-pack/plugins/cases/public/api/decoders.ts index 6b9cfdb21742c..1022e0583f8dc 100644 --- a/x-pack/plugins/cases/public/api/decoders.ts +++ b/x-pack/plugins/cases/public/api/decoders.ts @@ -11,12 +11,14 @@ import { pipe } from 'fp-ts/lib/pipeable'; import { createToasterPlainError } from '../containers/utils'; import { throwErrors } from '../../common'; -import { +import type { CasesFindResponse, - CasesFindResponseRt, CasesStatusResponse, - CasesStatusResponseRt, CasesMetricsResponse, +} from '../../common/api'; +import { + CasesFindResponseRt, + CasesStatusResponseRt, CasesMetricsResponseRt, } from '../../common/api'; diff --git a/x-pack/plugins/cases/public/api/index.ts b/x-pack/plugins/cases/public/api/index.ts index 209c0ad619d4b..47cc0b6f108a8 100644 --- a/x-pack/plugins/cases/public/api/index.ts +++ b/x-pack/plugins/cases/public/api/index.ts @@ -5,10 +5,10 @@ * 2.0. */ -import { HttpStart } from '@kbn/core/public'; -import { Cases, CasesStatus, CasesMetrics } from '../../common/ui'; +import type { HttpStart } from '@kbn/core/public'; +import type { Cases, CasesStatus, CasesMetrics } from '../../common/ui'; import { CASE_FIND_URL, CASE_METRICS_URL, CASE_STATUS_URL } from '../../common/constants'; -import { +import type { CasesFindRequest, CasesFindResponse, CasesMetricsRequest, diff --git a/x-pack/plugins/cases/public/api/utils.ts b/x-pack/plugins/cases/public/api/utils.ts index 992f078bfb7f1..87b48a0df9c58 100644 --- a/x-pack/plugins/cases/public/api/utils.ts +++ b/x-pack/plugins/cases/public/api/utils.ts @@ -10,7 +10,7 @@ import { isCommentRequestTypeExternalReference, isCommentRequestTypePersistableState, } from '../../common/utils/attachments'; -import { +import type { CasesFindResponse, CaseResponse, CaseUserActionsResponse, @@ -20,7 +20,7 @@ import { CasesResponse, } from '../../common/api'; import { isCommentUserAction } from '../../common/utils/user_actions'; -import { Cases, Case, Comment, ResolvedCase } from '../containers/types'; +import type { Cases, Case, Comment, ResolvedCase } from '../containers/types'; export const convertArrayToCamelCase = (arrayOfSnakes: unknown[]): unknown[] => arrayOfSnakes.reduce((acc: unknown[], value) => { diff --git a/x-pack/plugins/cases/public/application.tsx b/x-pack/plugins/cases/public/application.tsx index 5acf288d3bc34..360a9ce15476d 100644 --- a/x-pack/plugins/cases/public/application.tsx +++ b/x-pack/plugins/cases/public/application.tsx @@ -17,10 +17,10 @@ import { useUiSetting$, } from '@kbn/kibana-react-plugin/public'; import { EuiThemeProvider as StyledComponentsThemeProvider } from '@kbn/kibana-react-plugin/common'; -import { RenderAppProps } from './types'; +import type { RenderAppProps } from './types'; import { CasesApp } from './components/app'; -import { ExternalReferenceAttachmentTypeRegistry } from './client/attachment_framework/external_reference_registry'; -import { PersistableStateAttachmentTypeRegistry } from './client/attachment_framework/persistable_state_registry'; +import type { ExternalReferenceAttachmentTypeRegistry } from './client/attachment_framework/external_reference_registry'; +import type { PersistableStateAttachmentTypeRegistry } from './client/attachment_framework/persistable_state_registry'; export const renderApp = (deps: RenderAppProps) => { const { mountParams } = deps; diff --git a/x-pack/plugins/cases/public/client/api/index.ts b/x-pack/plugins/cases/public/client/api/index.ts index e9caee514a9cd..6d902940c2200 100644 --- a/x-pack/plugins/cases/public/client/api/index.ts +++ b/x-pack/plugins/cases/public/client/api/index.ts @@ -5,18 +5,18 @@ * 2.0. */ -import { HttpStart } from '@kbn/core/public'; -import { +import type { HttpStart } from '@kbn/core/public'; +import type { CasesByAlertId, CasesByAlertIDRequest, CasesFindRequest, - getCasesFromAlertsUrl, CasesStatusRequest, CasesMetricsRequest, } from '../../../common/api'; -import { Cases, CasesStatus, CasesMetrics } from '../../../common/ui'; +import { getCasesFromAlertsUrl } from '../../../common/api'; +import type { Cases, CasesStatus, CasesMetrics } from '../../../common/ui'; import { getCases, getCasesMetrics, getCasesStatus } from '../../api'; -import { CasesUiStart } from '../../types'; +import type { CasesUiStart } from '../../types'; export const createClientAPI = ({ http }: { http: HttpStart }): CasesUiStart['api'] => { return { diff --git a/x-pack/plugins/cases/public/client/attachment_framework/external_reference_registry.ts b/x-pack/plugins/cases/public/client/attachment_framework/external_reference_registry.ts index ed3eada182b0f..8d413dd393926 100644 --- a/x-pack/plugins/cases/public/client/attachment_framework/external_reference_registry.ts +++ b/x-pack/plugins/cases/public/client/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/public/client/attachment_framework/persistable_state_registry.ts b/x-pack/plugins/cases/public/client/attachment_framework/persistable_state_registry.ts index 1b8c5a1e40529..d867bbfdf1d4d 100644 --- a/x-pack/plugins/cases/public/client/attachment_framework/persistable_state_registry.ts +++ b/x-pack/plugins/cases/public/client/attachment_framework/persistable_state_registry.ts @@ -6,7 +6,7 @@ */ import { AttachmentTypeRegistry } from '../../../common/registry'; -import { PersistableStateAttachmentType } from './types'; +import type { PersistableStateAttachmentType } from './types'; export class PersistableStateAttachmentTypeRegistry extends AttachmentTypeRegistry { constructor() { diff --git a/x-pack/plugins/cases/public/client/attachment_framework/types.ts b/x-pack/plugins/cases/public/client/attachment_framework/types.ts index 2f8d7eacb0553..ea5c046a37e7c 100644 --- a/x-pack/plugins/cases/public/client/attachment_framework/types.ts +++ b/x-pack/plugins/cases/public/client/attachment_framework/types.ts @@ -6,12 +6,12 @@ */ import type React from 'react'; -import { EuiCommentProps, IconType } from '@elastic/eui'; -import { +import type { EuiCommentProps, IconType } from '@elastic/eui'; +import type { CommentRequestExternalReferenceType, CommentRequestPersistableStateType, } from '../../../common/api'; -import { Case } from '../../containers/types'; +import type { Case } from '../../containers/types'; export interface AttachmentViewObject { timelineAvatar?: EuiCommentProps['timelineAvatar']; diff --git a/x-pack/plugins/cases/public/client/helpers/can_use_cases.ts b/x-pack/plugins/cases/public/client/helpers/can_use_cases.ts index 13504cb2605cf..34af1c3865da5 100644 --- a/x-pack/plugins/cases/public/client/helpers/can_use_cases.ts +++ b/x-pack/plugins/cases/public/client/helpers/can_use_cases.ts @@ -13,7 +13,7 @@ import { SECURITY_SOLUTION_OWNER, } from '../../../common/constants'; import { getUICapabilities } from './capabilities'; -import { CasesPermissions } from '../../../common'; +import type { CasesPermissions } from '../../../common'; export type CasesOwners = | typeof SECURITY_SOLUTION_OWNER diff --git a/x-pack/plugins/cases/public/client/helpers/capabilities.ts b/x-pack/plugins/cases/public/client/helpers/capabilities.ts index 918f0c73c8ebd..f09ac84448952 100644 --- a/x-pack/plugins/cases/public/client/helpers/capabilities.ts +++ b/x-pack/plugins/cases/public/client/helpers/capabilities.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { CasesPermissions } from '../../../common'; +import type { CasesPermissions } from '../../../common'; import { CREATE_CASES_CAPABILITY, DELETE_CASES_CAPABILITY, diff --git a/x-pack/plugins/cases/public/client/helpers/get_rule_id_from_event.ts b/x-pack/plugins/cases/public/client/helpers/get_rule_id_from_event.ts index 0f8cbfe68e1f4..424eedca0ef76 100644 --- a/x-pack/plugins/cases/public/client/helpers/get_rule_id_from_event.ts +++ b/x-pack/plugins/cases/public/client/helpers/get_rule_id_from_event.ts @@ -7,7 +7,7 @@ import { ALERT_RULE_NAME, ALERT_RULE_UUID } from '@kbn/rule-data-utils'; import { get } from 'lodash/fp'; -import { Ecs } from '../../../common'; +import type { Ecs } from '../../../common'; type Maybe = T | null; interface Event { diff --git a/x-pack/plugins/cases/public/client/helpers/group_alerts_by_rule.ts b/x-pack/plugins/cases/public/client/helpers/group_alerts_by_rule.ts index 09e334cb3c848..965495e39eaf8 100644 --- a/x-pack/plugins/cases/public/client/helpers/group_alerts_by_rule.ts +++ b/x-pack/plugins/cases/public/client/helpers/group_alerts_by_rule.ts @@ -5,10 +5,11 @@ * 2.0. */ -import { CommentRequestAlertType } from '../../../common/api'; -import { CommentType, Ecs } from '../../../common'; +import type { CommentRequestAlertType } from '../../../common/api'; +import type { Ecs } from '../../../common'; +import { CommentType } from '../../../common'; import { getRuleIdFromEvent } from './get_rule_id_from_event'; -import { CaseAttachmentsWithoutOwner } from '../../types'; +import type { CaseAttachmentsWithoutOwner } from '../../types'; type Maybe = T | null; interface Event { diff --git a/x-pack/plugins/cases/public/client/ui/get_all_cases_selector_modal.tsx b/x-pack/plugins/cases/public/client/ui/get_all_cases_selector_modal.tsx index 93c107f8cc726..b0807b0509135 100644 --- a/x-pack/plugins/cases/public/client/ui/get_all_cases_selector_modal.tsx +++ b/x-pack/plugins/cases/public/client/ui/get_all_cases_selector_modal.tsx @@ -7,8 +7,9 @@ import React, { lazy, Suspense } from 'react'; import { EuiLoadingSpinner } from '@elastic/eui'; -import { AllCasesSelectorModalProps } from '../../components/all_cases/selector_modal'; -import { CasesProvider, CasesContextProps } from '../../components/cases_context'; +import type { AllCasesSelectorModalProps } from '../../components/all_cases/selector_modal'; +import type { CasesContextProps } from '../../components/cases_context'; +import { CasesProvider } from '../../components/cases_context'; type GetAllCasesSelectorModalPropsInternal = AllCasesSelectorModalProps & CasesContextProps; export type GetAllCasesSelectorModalProps = Omit< diff --git a/x-pack/plugins/cases/public/client/ui/get_cases.tsx b/x-pack/plugins/cases/public/client/ui/get_cases.tsx index d22c23fb0251e..45c9f30b984d2 100644 --- a/x-pack/plugins/cases/public/client/ui/get_cases.tsx +++ b/x-pack/plugins/cases/public/client/ui/get_cases.tsx @@ -8,7 +8,8 @@ import { EuiLoadingSpinner } from '@elastic/eui'; import React, { lazy, Suspense } from 'react'; import type { CasesProps } from '../../components/app'; -import { CasesProvider, CasesContextProps } from '../../components/cases_context'; +import type { CasesContextProps } from '../../components/cases_context'; +import { CasesProvider } from '../../components/cases_context'; type GetCasesPropsInternal = CasesProps & CasesContextProps; export type GetCasesProps = Omit< diff --git a/x-pack/plugins/cases/public/client/ui/get_cases_context.tsx b/x-pack/plugins/cases/public/client/ui/get_cases_context.tsx index fe0193ab184a1..77e6ca3c87e24 100644 --- a/x-pack/plugins/cases/public/client/ui/get_cases_context.tsx +++ b/x-pack/plugins/cases/public/client/ui/get_cases_context.tsx @@ -6,8 +6,9 @@ */ import { EuiLoadingSpinner } from '@elastic/eui'; -import React, { lazy, ReactNode, Suspense } from 'react'; -import { CasesContextProps } from '../../components/cases_context'; +import type { ReactNode } from 'react'; +import React, { lazy, Suspense } from 'react'; +import type { CasesContextProps } from '../../components/cases_context'; export type GetCasesContextPropsInternal = CasesContextProps; export type GetCasesContextProps = Omit< diff --git a/x-pack/plugins/cases/public/client/ui/get_create_case_flyout.tsx b/x-pack/plugins/cases/public/client/ui/get_create_case_flyout.tsx index e6f6b5465173e..af932b53e1dde 100644 --- a/x-pack/plugins/cases/public/client/ui/get_create_case_flyout.tsx +++ b/x-pack/plugins/cases/public/client/ui/get_create_case_flyout.tsx @@ -8,7 +8,8 @@ import React, { lazy, Suspense } from 'react'; import { EuiLoadingSpinner } from '@elastic/eui'; import type { CreateCaseFlyoutProps } from '../../components/create/flyout'; -import { CasesProvider, CasesContextProps } from '../../components/cases_context'; +import type { CasesContextProps } from '../../components/cases_context'; +import { CasesProvider } from '../../components/cases_context'; type GetCreateCaseFlyoutPropsInternal = CreateCaseFlyoutProps & CasesContextProps; export type GetCreateCaseFlyoutProps = Omit< diff --git a/x-pack/plugins/cases/public/client/ui/get_recent_cases.tsx b/x-pack/plugins/cases/public/client/ui/get_recent_cases.tsx index 021ad4233931c..a047c106246da 100644 --- a/x-pack/plugins/cases/public/client/ui/get_recent_cases.tsx +++ b/x-pack/plugins/cases/public/client/ui/get_recent_cases.tsx @@ -7,8 +7,9 @@ import { EuiLoadingSpinner } from '@elastic/eui'; import React, { lazy, Suspense } from 'react'; -import { CasesProvider, CasesContextProps } from '../../components/cases_context'; -import { RecentCasesProps } from '../../components/recent_cases'; +import type { CasesContextProps } from '../../components/cases_context'; +import { CasesProvider } from '../../components/cases_context'; +import type { RecentCasesProps } from '../../components/recent_cases'; type GetRecentCasesPropsInternal = RecentCasesProps & CasesContextProps; export type GetRecentCasesProps = Omit< diff --git a/x-pack/plugins/cases/public/common/apm/use_cases_transactions.test.ts b/x-pack/plugins/cases/public/common/apm/use_cases_transactions.test.ts index 3b0ba69ae8560..5438258187a2f 100644 --- a/x-pack/plugins/cases/public/common/apm/use_cases_transactions.test.ts +++ b/x-pack/plugins/cases/public/common/apm/use_cases_transactions.test.ts @@ -6,10 +6,12 @@ */ import { renderHook } from '@testing-library/react-hooks'; -import { CaseAttachmentsWithoutOwner } from '../../types'; -import { +import type { CaseAttachmentsWithoutOwner } from '../../types'; +import type { StartAddAttachmentToExistingCaseTransaction, StartCreateCaseWithAttachmentsTransaction, +} from './use_cases_transactions'; +import { useAddAttachmentToExistingCaseTransaction, useCreateCaseWithAttachmentsTransaction, } from './use_cases_transactions'; diff --git a/x-pack/plugins/cases/public/common/apm/use_cases_transactions.ts b/x-pack/plugins/cases/public/common/apm/use_cases_transactions.ts index 1f7b77c32df99..1a4be4053b7ef 100644 --- a/x-pack/plugins/cases/public/common/apm/use_cases_transactions.ts +++ b/x-pack/plugins/cases/public/common/apm/use_cases_transactions.ts @@ -5,10 +5,10 @@ * 2.0. */ -import { Transaction } from '@elastic/apm-rum'; +import type { Transaction } from '@elastic/apm-rum'; import { useCallback } from 'react'; import { CommentType } from '../../../common'; -import { CaseAttachmentsWithoutOwner } from '../../types'; +import type { CaseAttachmentsWithoutOwner } from '../../types'; import { useStartTransaction } from './use_start_transaction'; const CREATE_CASE = 'createCase' as const; diff --git a/x-pack/plugins/cases/public/common/lib/kibana/hooks.ts b/x-pack/plugins/cases/public/common/lib/kibana/hooks.ts index 86d137f55dc93..812840b1553e3 100644 --- a/x-pack/plugins/cases/public/common/lib/kibana/hooks.ts +++ b/x-pack/plugins/cases/public/common/lib/kibana/hooks.ts @@ -10,8 +10,8 @@ import moment from 'moment-timezone'; import { useCallback, useEffect, useMemo, useState } from 'react'; import { i18n } from '@kbn/i18n'; -import { AuthenticatedUser } from '@kbn/security-plugin/common/model'; -import { NavigateToAppOptions } from '@kbn/core/public'; +import type { AuthenticatedUser } from '@kbn/security-plugin/common/model'; +import type { NavigateToAppOptions } from '@kbn/core/public'; import { getUICapabilities } from '../../../client/helpers/capabilities'; import { convertToCamelCase } from '../../../api/utils'; import { @@ -19,8 +19,8 @@ import { DEFAULT_DATE_FORMAT, DEFAULT_DATE_FORMAT_TZ, } from '../../../../common/constants'; -import { CasesPermissions } from '../../../../common'; -import { StartServices } from '../../../types'; +import type { CasesPermissions } from '../../../../common'; +import type { StartServices } from '../../../types'; import { useUiSetting, useKibana } from './kibana_react'; export const useDateFormat = (): string => useUiSetting(DEFAULT_DATE_FORMAT); diff --git a/x-pack/plugins/cases/public/common/lib/kibana/kibana_react.mock.ts b/x-pack/plugins/cases/public/common/lib/kibana/kibana_react.mock.ts index 792379af1b532..68ad770d0a8bf 100644 --- a/x-pack/plugins/cases/public/common/lib/kibana/kibana_react.mock.ts +++ b/x-pack/plugins/cases/public/common/lib/kibana/kibana_react.mock.ts @@ -10,13 +10,13 @@ import React from 'react'; import { BehaviorSubject } from 'rxjs'; -import { PublicAppInfo } from '@kbn/core/public'; -import { RecursivePartial } from '@elastic/eui/src/components/common'; +import type { PublicAppInfo } from '@kbn/core/public'; +import type { RecursivePartial } from '@elastic/eui/src/components/common'; import { coreMock } from '@kbn/core/public/mocks'; import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; -import { ILicense } from '@kbn/licensing-plugin/public'; -import { StartServices } from '../../../types'; -import { EuiTheme } from '@kbn/kibana-react-plugin/common'; +import type { ILicense } from '@kbn/licensing-plugin/public'; +import type { StartServices } from '../../../types'; +import type { EuiTheme } from '@kbn/kibana-react-plugin/common'; import { securityMock } from '@kbn/security-plugin/public/mocks'; import { spacesPluginMock } from '@kbn/spaces-plugin/public/mocks'; import { triggersActionsUiMock } from '@kbn/triggers-actions-ui-plugin/public/mocks'; diff --git a/x-pack/plugins/cases/public/common/lib/kibana/kibana_react.ts b/x-pack/plugins/cases/public/common/lib/kibana/kibana_react.ts index 0884b57048e78..062e0e362f75c 100644 --- a/x-pack/plugins/cases/public/common/lib/kibana/kibana_react.ts +++ b/x-pack/plugins/cases/public/common/lib/kibana/kibana_react.ts @@ -11,7 +11,7 @@ import { useUiSetting, useUiSetting$, } from '@kbn/kibana-react-plugin/public'; -import { StartServices } from '../../../types'; +import type { StartServices } from '../../../types'; const useTypedKibana = () => useKibana(); diff --git a/x-pack/plugins/cases/public/common/lib/kibana/services.ts b/x-pack/plugins/cases/public/common/lib/kibana/services.ts index 30198b812e4aa..f4c546a553881 100644 --- a/x-pack/plugins/cases/public/common/lib/kibana/services.ts +++ b/x-pack/plugins/cases/public/common/lib/kibana/services.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { CoreStart } from '@kbn/core/public'; -import { CasesUiConfigType } from '../../../../common/ui/types'; +import type { CoreStart } from '@kbn/core/public'; +import type { CasesUiConfigType } from '../../../../common/ui/types'; type GlobalServices = Pick; diff --git a/x-pack/plugins/cases/public/common/mock/connectors.ts b/x-pack/plugins/cases/public/common/mock/connectors.ts index 575cb7a83f9d2..e0b7b26a4c8a4 100644 --- a/x-pack/plugins/cases/public/common/mock/connectors.ts +++ b/x-pack/plugins/cases/public/common/mock/connectors.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { ActionConnector, ActionTypeConnector } from '../../../common/api'; +import type { ActionConnector, ActionTypeConnector } from '../../../common/api'; export const connectorsMock: ActionConnector[] = [ { diff --git a/x-pack/plugins/cases/public/common/mock/permissions.ts b/x-pack/plugins/cases/public/common/mock/permissions.ts index 7395e966037ea..01d1dc64952ed 100644 --- a/x-pack/plugins/cases/public/common/mock/permissions.ts +++ b/x-pack/plugins/cases/public/common/mock/permissions.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { CasesCapabilities, CasesPermissions } from '../../containers/types'; +import type { CasesCapabilities, CasesPermissions } from '../../containers/types'; export const allCasesPermissions = () => buildCasesPermissions(); export const noCasesPermissions = () => diff --git a/x-pack/plugins/cases/public/common/mock/register_connectors.ts b/x-pack/plugins/cases/public/common/mock/register_connectors.ts index 594f4f96b4c8e..8bc05351d4833 100644 --- a/x-pack/plugins/cases/public/common/mock/register_connectors.ts +++ b/x-pack/plugins/cases/public/common/mock/register_connectors.ts @@ -5,9 +5,9 @@ * 2.0. */ -import { TriggersAndActionsUIPublicPluginStart } from '@kbn/triggers-actions-ui-plugin/public'; +import type { TriggersAndActionsUIPublicPluginStart } from '@kbn/triggers-actions-ui-plugin/public'; import { actionTypeRegistryMock } from '@kbn/triggers-actions-ui-plugin/public/application/action_type_registry.mock'; -import { CaseActionConnector } from '../../../common/ui/types'; +import type { CaseActionConnector } from '../../../common/ui/types'; const getUniqueActionTypeIds = (connectors: CaseActionConnector[]) => new Set(connectors.map((connector) => connector.actionTypeId)); 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 571825a21474b..99ed0c274199c 100644 --- a/x-pack/plugins/cases/public/common/mock/test_providers.tsx +++ b/x-pack/plugins/cases/public/common/mock/test_providers.tsx @@ -13,16 +13,17 @@ import { I18nProvider } from '@kbn/i18n-react'; import { ThemeProvider } from 'styled-components'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; -import { render as reactRender, RenderOptions, RenderResult } from '@testing-library/react'; +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 { ILicense } from '@kbn/licensing-plugin/public'; +import type { ILicense } from '@kbn/licensing-plugin/public'; import { SECURITY_SOLUTION_OWNER } from '../../../common/constants'; -import { CasesFeatures, CasesPermissions } from '../../../common/ui/types'; +import type { CasesFeatures, CasesPermissions } from '../../../common/ui/types'; import { CasesProvider } from '../../components/cases_context'; import { createStartServicesMock } from '../lib/kibana/kibana_react.mock'; -import { FieldHook } from '../shared_imports'; -import { StartServices } from '../../types'; -import { ReleasePhase } from '../../components/types'; +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'; import { PersistableStateAttachmentTypeRegistry } from '../../client/attachment_framework/persistable_state_registry'; import { allCasesPermissions } from './permissions'; diff --git a/x-pack/plugins/cases/public/common/navigation/hooks.ts b/x-pack/plugins/cases/public/common/navigation/hooks.ts index 1197ef0c5cf11..81b59c9b42637 100644 --- a/x-pack/plugins/cases/public/common/navigation/hooks.ts +++ b/x-pack/plugins/cases/public/common/navigation/hooks.ts @@ -9,17 +9,12 @@ import { useCallback, useEffect, useState } from 'react'; import { useLocation, useParams } from 'react-router-dom'; import { parse, stringify } from 'query-string'; -import { APP_ID } from '../../../common/constants'; +import { APP_ID, CASES_CONFIGURE_PATH, CASES_CREATE_PATH } from '../../../common/constants'; import { useNavigation } from '../lib/kibana'; import { useCasesContext } from '../../components/cases_context/use_cases_context'; -import { ICasesDeepLinkId } from './deep_links'; -import { - CASES_CONFIGURE_PATH, - CASES_CREATE_PATH, - CaseViewPathParams, - CaseViewPathSearchParams, - generateCaseViewPath, -} from './paths'; +import type { ICasesDeepLinkId } from './deep_links'; +import type { CaseViewPathParams, CaseViewPathSearchParams } from './paths'; +import { generateCaseViewPath } from './paths'; export const useCaseViewParams = () => useParams(); diff --git a/x-pack/plugins/cases/public/common/navigation/paths.ts b/x-pack/plugins/cases/public/common/navigation/paths.ts index 857f832f7aed3..24db617799996 100644 --- a/x-pack/plugins/cases/public/common/navigation/paths.ts +++ b/x-pack/plugins/cases/public/common/navigation/paths.ts @@ -6,7 +6,14 @@ */ import { generatePath } from 'react-router-dom'; -import { CASE_VIEW_PAGE_TABS } from '../../components/case_view/types'; +import { + CASES_CREATE_PATH, + CASES_CONFIGURE_PATH, + CASE_VIEW_PATH, + CASE_VIEW_COMMENT_PATH, + CASE_VIEW_TAB_PATH, +} from '../../../common/constants'; +import type { CASE_VIEW_PAGE_TABS } from '../../../common/types'; export const DEFAULT_BASE_PATH = '/cases'; @@ -19,14 +26,6 @@ export type CaseViewPathParams = { commentId?: string; } & CaseViewPathSearchParams; -export const CASES_CREATE_PATH = '/create' as const; -export const CASES_CONFIGURE_PATH = '/configure' as const; -export const CASE_VIEW_PATH = '/:detailName' as const; -export const CASE_VIEW_COMMENT_PATH = `${CASE_VIEW_PATH}/:commentId` as const; -export const CASE_VIEW_ALERT_TABLE_PATH = - `${CASE_VIEW_PATH}/?tabId=${CASE_VIEW_PAGE_TABS.ALERTS}` as const; -export const CASE_VIEW_TAB_PATH = `${CASE_VIEW_PATH}/?tabId=:tabId` as const; - const normalizePath = (path: string): string => path.replaceAll('//', '/'); export const getCreateCasePath = (casesBasePath: string) => diff --git a/x-pack/plugins/cases/public/common/test_utils.ts b/x-pack/plugins/cases/public/common/test_utils.ts index a7d4405ced030..db6dfaaf11c31 100644 --- a/x-pack/plugins/cases/public/common/test_utils.ts +++ b/x-pack/plugins/cases/public/common/test_utils.ts @@ -5,9 +5,9 @@ * 2.0. */ -import { ReactWrapper } from 'enzyme'; +import type { ReactWrapper } from 'enzyme'; import { act } from 'react-dom/test-utils'; -import { MatcherFunction } from '@testing-library/react'; +import type { MatcherFunction } from '@testing-library/react'; /** * Convenience utility to remove text appended to links by EUI diff --git a/x-pack/plugins/cases/public/common/use_cases_features.test.tsx b/x-pack/plugins/cases/public/common/use_cases_features.test.tsx index e64bc61acf91d..973ed1326baa8 100644 --- a/x-pack/plugins/cases/public/common/use_cases_features.test.tsx +++ b/x-pack/plugins/cases/public/common/use_cases_features.test.tsx @@ -8,10 +8,12 @@ import React from 'react'; import { renderHook } from '@testing-library/react-hooks'; import { licensingMock } from '@kbn/licensing-plugin/public/mocks'; -import { CasesContextFeatures } from '../../common/ui'; -import { useCasesFeatures, UseCasesFeatures } from './use_cases_features'; +import type { CasesContextFeatures } from '../../common/ui'; +import type { UseCasesFeatures } from './use_cases_features'; +import { useCasesFeatures } from './use_cases_features'; import { TestProviders } from './mock/test_providers'; -import { LicenseType, LICENSE_TYPE } from '@kbn/licensing-plugin/common/types'; +import type { LicenseType } from '@kbn/licensing-plugin/common/types'; +import { LICENSE_TYPE } from '@kbn/licensing-plugin/common/types'; describe('useCasesFeatures', () => { // isAlertsEnabled, isSyncAlertsEnabled, alerts diff --git a/x-pack/plugins/cases/public/common/use_cases_features.tsx b/x-pack/plugins/cases/public/common/use_cases_features.tsx index 064fe89fb90df..2f064df9a97a9 100644 --- a/x-pack/plugins/cases/public/common/use_cases_features.tsx +++ b/x-pack/plugins/cases/public/common/use_cases_features.tsx @@ -6,7 +6,7 @@ */ import { useMemo } from 'react'; -import { SingleCaseMetricsFeature } from '../../common/ui'; +import type { SingleCaseMetricsFeature } from '../../common/ui'; import { useCasesContext } from '../components/cases_context/use_cases_context'; import { useLicense } from './use_license'; diff --git a/x-pack/plugins/cases/public/common/use_cases_toast.test.tsx b/x-pack/plugins/cases/public/common/use_cases_toast.test.tsx index cfa2d3a6e0052..cabca3ea69f7a 100644 --- a/x-pack/plugins/cases/public/common/use_cases_toast.test.tsx +++ b/x-pack/plugins/cases/public/common/use_cases_toast.test.tsx @@ -7,12 +7,13 @@ import { renderHook } from '@testing-library/react-hooks'; import { useKibana, useToasts } from './lib/kibana'; -import { AppMockRenderer, createAppMockRenderer, TestProviders } from './mock'; +import type { AppMockRenderer } from './mock'; +import { createAppMockRenderer, TestProviders } from './mock'; import { CaseToastSuccessContent, useCasesToast } from './use_cases_toast'; import { alertComment, basicComment, mockCase } from '../containers/mock'; import React from 'react'; import userEvent from '@testing-library/user-event'; -import { SupportedCaseAttachment } from '../types'; +import type { SupportedCaseAttachment } from '../types'; import { getByTestId } from '@testing-library/dom'; import { OWNER_INFO } from '../../common/constants'; diff --git a/x-pack/plugins/cases/public/common/use_cases_toast.tsx b/x-pack/plugins/cases/public/common/use_cases_toast.tsx index 42a358897bc62..984a5ed607351 100644 --- a/x-pack/plugins/cases/public/common/use_cases_toast.tsx +++ b/x-pack/plugins/cases/public/common/use_cases_toast.tsx @@ -10,10 +10,12 @@ import { EuiButtonEmpty, EuiText } from '@elastic/eui'; import React from 'react'; import styled from 'styled-components'; import { toMountPoint } from '@kbn/kibana-react-plugin/public'; -import { Case, CommentType } from '../../common'; +import { isValidOwner } from '../../common/utils/owner'; +import type { Case } from '../../common'; +import { CommentType } from '../../common'; import { useKibana, useToasts } from './lib/kibana'; import { generateCaseViewPath } from './navigation'; -import { CaseAttachmentsWithoutOwner, ServerError } from '../types'; +import type { CaseAttachmentsWithoutOwner, ServerError } from '../types'; import { CASE_ALERT_SUCCESS_SYNC_TEXT, CASE_ALERT_SUCCESS_TOAST, @@ -96,9 +98,6 @@ function getToastContent({ return undefined; } -const isValidOwner = (owner: string): owner is keyof typeof OWNER_INFO => - Object.keys(OWNER_INFO).includes(owner); - const isServerError = (error: Error | ServerError): error is ServerError => Object.hasOwn(error, 'body'); diff --git a/x-pack/plugins/cases/public/common/use_license.tsx b/x-pack/plugins/cases/public/common/use_license.tsx index f8bdddf2bf956..9d02aa59f37b3 100644 --- a/x-pack/plugins/cases/public/common/use_license.tsx +++ b/x-pack/plugins/cases/public/common/use_license.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import { ILicense, LicenseType } from '@kbn/licensing-plugin/public'; +import type { ILicense, LicenseType } from '@kbn/licensing-plugin/public'; import { useCallback } from 'react'; import useObservable from 'react-use/lib/useObservable'; import { Observable } from 'rxjs'; diff --git a/x-pack/plugins/cases/public/components/actions/delete/use_delete_action.test.tsx b/x-pack/plugins/cases/public/components/actions/delete/use_delete_action.test.tsx index 747aa0e84e1d7..3e89fc83ca92b 100644 --- a/x-pack/plugins/cases/public/components/actions/delete/use_delete_action.test.tsx +++ b/x-pack/plugins/cases/public/components/actions/delete/use_delete_action.test.tsx @@ -5,7 +5,8 @@ * 2.0. */ -import { AppMockRenderer, createAppMockRenderer } from '../../../common/mock'; +import type { AppMockRenderer } from '../../../common/mock'; +import { createAppMockRenderer } from '../../../common/mock'; import { act, renderHook } from '@testing-library/react-hooks'; import { useDeleteAction } from './use_delete_action'; diff --git a/x-pack/plugins/cases/public/components/actions/delete/use_delete_action.tsx b/x-pack/plugins/cases/public/components/actions/delete/use_delete_action.tsx index 92184dbd64648..608af0e66444b 100644 --- a/x-pack/plugins/cases/public/components/actions/delete/use_delete_action.tsx +++ b/x-pack/plugins/cases/public/components/actions/delete/use_delete_action.tsx @@ -7,11 +7,11 @@ import React, { useCallback, useState } from 'react'; import { EuiIcon, EuiTextColor, useEuiTheme } from '@elastic/eui'; -import { Case } from '../../../../common'; +import type { Case } from '../../../../common'; import { useDeleteCases } from '../../../containers/use_delete_cases'; import * as i18n from './translations'; -import { UseActionProps } from '../types'; +import type { UseActionProps } from '../types'; import { useCasesContext } from '../../cases_context/use_cases_context'; const getDeleteActionTitle = (totalCases: number): string => diff --git a/x-pack/plugins/cases/public/components/actions/severity/use_severity_action.test.tsx b/x-pack/plugins/cases/public/components/actions/severity/use_severity_action.test.tsx index 9705d5ffeb2b2..42fea8e679608 100644 --- a/x-pack/plugins/cases/public/components/actions/severity/use_severity_action.test.tsx +++ b/x-pack/plugins/cases/public/components/actions/severity/use_severity_action.test.tsx @@ -5,7 +5,8 @@ * 2.0. */ -import { AppMockRenderer, createAppMockRenderer } from '../../../common/mock'; +import type { AppMockRenderer } from '../../../common/mock'; +import { createAppMockRenderer } from '../../../common/mock'; import { act, renderHook } from '@testing-library/react-hooks'; import { useSeverityAction } from './use_severity_action'; diff --git a/x-pack/plugins/cases/public/components/actions/severity/use_severity_action.tsx b/x-pack/plugins/cases/public/components/actions/severity/use_severity_action.tsx index a4651cee82612..614bb0cbef77c 100644 --- a/x-pack/plugins/cases/public/components/actions/severity/use_severity_action.tsx +++ b/x-pack/plugins/cases/public/components/actions/severity/use_severity_action.tsx @@ -6,13 +6,13 @@ */ import { useCallback } from 'react'; -import { EuiContextMenuPanelItemDescriptor } from '@elastic/eui'; +import type { EuiContextMenuPanelItemDescriptor } from '@elastic/eui'; import { CaseSeverity } from '../../../../common/api'; import { useUpdateCases } from '../../../containers/use_bulk_update_case'; -import { Case } from '../../../../common'; +import type { Case } from '../../../../common'; import * as i18n from './translations'; -import { UseActionProps } from '../types'; +import type { UseActionProps } from '../types'; import { useCasesContext } from '../../cases_context/use_cases_context'; import { severities } from '../../severity/config'; diff --git a/x-pack/plugins/cases/public/components/actions/status/use_status_action.test.tsx b/x-pack/plugins/cases/public/components/actions/status/use_status_action.test.tsx index a0f16dbaa1760..03d3da5101d38 100644 --- a/x-pack/plugins/cases/public/components/actions/status/use_status_action.test.tsx +++ b/x-pack/plugins/cases/public/components/actions/status/use_status_action.test.tsx @@ -5,7 +5,8 @@ * 2.0. */ -import { AppMockRenderer, createAppMockRenderer } from '../../../common/mock'; +import type { AppMockRenderer } from '../../../common/mock'; +import { createAppMockRenderer } from '../../../common/mock'; import { act, renderHook } from '@testing-library/react-hooks'; import { useStatusAction } from './use_status_action'; diff --git a/x-pack/plugins/cases/public/components/actions/status/use_status_action.tsx b/x-pack/plugins/cases/public/components/actions/status/use_status_action.tsx index 8f1100aaab90d..6b9fe58c15105 100644 --- a/x-pack/plugins/cases/public/components/actions/status/use_status_action.tsx +++ b/x-pack/plugins/cases/public/components/actions/status/use_status_action.tsx @@ -6,12 +6,13 @@ */ import { useCallback } from 'react'; -import { EuiContextMenuPanelItemDescriptor } from '@elastic/eui'; +import type { EuiContextMenuPanelItemDescriptor } from '@elastic/eui'; import { useUpdateCases } from '../../../containers/use_bulk_update_case'; -import { Case, CaseStatuses } from '../../../../common'; +import type { Case } from '../../../../common'; +import { CaseStatuses } from '../../../../common'; import * as i18n from './translations'; -import { UseActionProps } from '../types'; +import type { UseActionProps } from '../types'; import { statuses } from '../../status'; import { useCasesContext } from '../../cases_context/use_cases_context'; diff --git a/x-pack/plugins/cases/public/components/add_comment/index.test.tsx b/x-pack/plugins/cases/public/components/add_comment/index.test.tsx index d8bb10fce78fc..17045ab21686c 100644 --- a/x-pack/plugins/cases/public/components/add_comment/index.test.tsx +++ b/x-pack/plugins/cases/public/components/add_comment/index.test.tsx @@ -15,10 +15,11 @@ import { noCreateCasesPermissions, TestProviders } from '../../common/mock'; import { CommentType } from '../../../common/api'; import { SECURITY_SOLUTION_OWNER } from '../../../common/constants'; import { useCreateAttachments } from '../../containers/use_create_attachments'; -import { AddComment, AddCommentProps, AddCommentRefObject } from '.'; +import type { AddCommentProps, AddCommentRefObject } from '.'; +import { AddComment } from '.'; import { CasesTimelineIntegrationProvider } from '../timeline_context'; import { timelineIntegrationMock } from '../__mock__/timeline'; -import { CaseAttachmentWithoutOwner } from '../../types'; +import type { CaseAttachmentWithoutOwner } from '../../types'; jest.mock('../../containers/use_create_attachments'); 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 6710a4a4471e0..84715324bee92 100644 --- a/x-pack/plugins/cases/public/components/add_comment/index.tsx +++ b/x-pack/plugins/cases/public/components/add_comment/index.tsx @@ -19,12 +19,14 @@ import { isEmpty } from 'lodash'; import { CommentType } from '../../../common/api'; import { useCreateAttachments } from '../../containers/use_create_attachments'; -import { Case } from '../../containers/types'; -import { EuiMarkdownEditorRef, MarkdownEditorForm } from '../markdown_editor'; +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 { schema, AddCommentFormSchema } from './schema'; +import type { AddCommentFormSchema } from './schema'; +import { schema } from './schema'; import { InsertTimeline } from '../insert_timeline'; import { useCasesContext } from '../cases_context/use_cases_context'; 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 3e32c8a938b68..7f8da37aeedc6 100644 --- a/x-pack/plugins/cases/public/components/add_comment/schema.tsx +++ b/x-pack/plugins/cases/public/components/add_comment/schema.tsx @@ -5,8 +5,9 @@ * 2.0. */ -import { CommentRequestUserType } from '../../../common/api'; -import { FIELD_TYPES, fieldValidators, FormSchema } from '../../common/shared_imports'; +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/all_cases/all_cases_list.test.tsx b/x-pack/plugins/cases/public/components/all_cases/all_cases_list.test.tsx index 63ef59d695d80..48cd41dd2fb7d 100644 --- a/x-pack/plugins/cases/public/components/all_cases/all_cases_list.test.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/all_cases_list.test.tsx @@ -14,8 +14,8 @@ import userEvent from '@testing-library/user-event'; import { waitForEuiPopoverOpen } from '@elastic/eui/lib/test/rtl'; import '../../common/mock/match_media'; +import type { AppMockRenderer } from '../../common/mock'; import { - AppMockRenderer, createAppMockRenderer, noDeleteCasesPermissions, readCasesPermissions, @@ -29,7 +29,8 @@ import { SECURITY_SOLUTION_OWNER } from '../../../common/constants'; import { getEmptyTagValue } from '../empty_value'; import { useKibana } from '../../common/lib/kibana'; import { AllCasesList } from './all_cases_list'; -import { GetCasesColumn, useCasesColumns, UseCasesColumnsReturnValue } from './use_cases_columns'; +import type { GetCasesColumn, UseCasesColumnsReturnValue } from './use_cases_columns'; +import { useCasesColumns } from './use_cases_columns'; import { triggersActionsUiMock } from '@kbn/triggers-actions-ui-plugin/public/mocks'; import { registerConnectorsToMockActionRegistry } from '../../common/mock/register_connectors'; import { createStartServicesMock } from '../../common/lib/kibana/kibana_react.mock'; @@ -477,7 +478,7 @@ describe('AllCasesListGeneric', () => { ); - expect(wrapper.find('[data-test-subj="status-badge-in-progress"]').exists()).toBeTruthy(); + expect(wrapper.find('[data-test-subj="case-status-badge-in-progress"]').exists()).toBeTruthy(); }); it('shows Solution column if there are no set owners', async () => { diff --git a/x-pack/plugins/cases/public/components/all_cases/all_cases_list.tsx b/x-pack/plugins/cases/public/components/all_cases/all_cases_list.tsx index 0d2cff95c4919..f4449c3949003 100644 --- a/x-pack/plugins/cases/public/components/all_cases/all_cases_list.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/all_cases_list.tsx @@ -6,24 +6,24 @@ */ import React, { useCallback, useMemo, useRef, useState } from 'react'; -import { EuiProgress, EuiBasicTable, EuiTableSelectionType } from '@elastic/eui'; +import type { EuiBasicTable, EuiTableSelectionType } from '@elastic/eui'; +import { EuiProgress } from '@elastic/eui'; import { difference, head, isEmpty } from 'lodash/fp'; import styled, { css } from 'styled-components'; -import { +import type { Case, CaseStatusWithAllStatus, FilterOptions, QueryParams, - SortFieldCase, - StatusAll, } from '../../../common/ui/types'; +import { SortFieldCase, StatusAll } from '../../../common/ui/types'; import { CaseStatuses, caseStatuses } from '../../../common/api'; import { useAvailableCasesOwners } from '../app/use_available_owners'; import { useCasesColumns } from './use_cases_columns'; import { CasesTableFilters } from './table_filters'; -import { EuiBasicTableOnChange } from './types'; +import type { EuiBasicTableOnChange } from './types'; import { CasesTable } from './table'; import { useCasesContext } from '../cases_context/use_cases_context'; diff --git a/x-pack/plugins/cases/public/components/all_cases/assignees_filter.test.tsx b/x-pack/plugins/cases/public/components/all_cases/assignees_filter.test.tsx index 2f51b5d574e1b..0f50eb0421093 100644 --- a/x-pack/plugins/cases/public/components/all_cases/assignees_filter.test.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/assignees_filter.test.tsx @@ -8,8 +8,10 @@ import React from 'react'; import userEvent from '@testing-library/user-event'; import { screen, fireEvent, waitFor, within } from '@testing-library/react'; -import { AppMockRenderer, createAppMockRenderer } from '../../common/mock'; -import { AssigneesFilterPopover, AssigneesFilterPopoverProps } from './assignees_filter'; +import type { AppMockRenderer } from '../../common/mock'; +import { createAppMockRenderer } from '../../common/mock'; +import type { AssigneesFilterPopoverProps } from './assignees_filter'; +import { AssigneesFilterPopover } from './assignees_filter'; import { userProfiles } from '../../containers/user_profiles/api.mock'; import { waitForEuiPopoverOpen } from '@elastic/eui/lib/test/rtl'; diff --git a/x-pack/plugins/cases/public/components/all_cases/assignees_filter.tsx b/x-pack/plugins/cases/public/components/all_cases/assignees_filter.tsx index 6ffa18cfa8073..1cf4f2c9a2bd4 100644 --- a/x-pack/plugins/cases/public/components/all_cases/assignees_filter.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/assignees_filter.tsx @@ -6,13 +6,14 @@ */ import { EuiFilterButton } from '@elastic/eui'; -import { UserProfilesPopover, UserProfileWithAvatar } from '@kbn/user-profile-components'; +import type { UserProfileWithAvatar } from '@kbn/user-profile-components'; +import { UserProfilesPopover } from '@kbn/user-profile-components'; import { isEmpty } from 'lodash'; import React, { useCallback, useMemo, useState } from 'react'; import { useSuggestUserProfiles } from '../../containers/user_profiles/use_suggest_user_profiles'; import { useAvailableCasesOwners } from '../app/use_available_owners'; import { useCasesContext } from '../cases_context/use_cases_context'; -import { CurrentUserProfile } from '../types'; +import type { CurrentUserProfile } from '../types'; import { EmptyMessage } from '../user_profiles/empty_message'; import { NoMatches } from '../user_profiles/no_matches'; import { SelectedStatusMessage } from '../user_profiles/selected_status_message'; diff --git a/x-pack/plugins/cases/public/components/all_cases/cases_metrics.test.tsx b/x-pack/plugins/cases/public/components/all_cases/cases_metrics.test.tsx index 323f9deead3eb..4a10df984c07d 100644 --- a/x-pack/plugins/cases/public/components/all_cases/cases_metrics.test.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/cases_metrics.test.tsx @@ -7,7 +7,8 @@ import { waitFor, within } from '@testing-library/react'; import React from 'react'; -import { AppMockRenderer, createAppMockRenderer } from '../../common/mock'; +import type { AppMockRenderer } from '../../common/mock'; +import { createAppMockRenderer } from '../../common/mock'; import { CasesMetrics } from './cases_metrics'; jest.mock('../../api'); diff --git a/x-pack/plugins/cases/public/components/all_cases/header.test.tsx b/x-pack/plugins/cases/public/components/all_cases/header.test.tsx index 64e84affe14d5..08bd228b32e11 100644 --- a/x-pack/plugins/cases/public/components/all_cases/header.test.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/header.test.tsx @@ -7,7 +7,8 @@ import React from 'react'; -import { AppMockRenderer, buildCasesPermissions, createAppMockRenderer } from '../../common/mock'; +import type { AppMockRenderer } from '../../common/mock'; +import { buildCasesPermissions, createAppMockRenderer } from '../../common/mock'; import { CasesTableHeader } from './header'; describe('CasesTableHeader', () => { diff --git a/x-pack/plugins/cases/public/components/all_cases/header.tsx b/x-pack/plugins/cases/public/components/all_cases/header.tsx index a40a38a3be581..c16bf0951ed60 100644 --- a/x-pack/plugins/cases/public/components/all_cases/header.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/header.tsx @@ -5,11 +5,12 @@ * 2.0. */ -import React, { FunctionComponent } from 'react'; +import type { FunctionComponent } from 'react'; +import React from 'react'; import { EuiFlexGroup } from '@elastic/eui'; import { HeaderPage } from '../header_page'; import * as i18n from './translations'; -import { ErrorMessage } from '../use_push_to_service/callout/types'; +import type { ErrorMessage } from '../use_push_to_service/callout/types'; import { NavButtons } from './nav_buttons'; interface OwnProps { diff --git a/x-pack/plugins/cases/public/components/all_cases/index.test.tsx b/x-pack/plugins/cases/public/components/all_cases/index.test.tsx index 55777dd5bd34c..72cdbc0c0ed5b 100644 --- a/x-pack/plugins/cases/public/components/all_cases/index.test.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/index.test.tsx @@ -9,11 +9,8 @@ import React from 'react'; import { waitFor } from '@testing-library/react'; import { AllCases } from '.'; -import { - AppMockRenderer, - createAppMockRenderer, - noCreateCasesPermissions, -} from '../../common/mock'; +import type { AppMockRenderer } from '../../common/mock'; +import { createAppMockRenderer, noCreateCasesPermissions } from '../../common/mock'; import { useGetActionLicense } from '../../containers/use_get_action_license'; import { connectorsMock, useGetCasesMockState } from '../../containers/mock'; import { useGetConnectors } from '../../containers/configure/use_connectors'; diff --git a/x-pack/plugins/cases/public/components/all_cases/nav_buttons.tsx b/x-pack/plugins/cases/public/components/all_cases/nav_buttons.tsx index 5217c7022d907..59b26b921eae0 100644 --- a/x-pack/plugins/cases/public/components/all_cases/nav_buttons.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/nav_buttons.tsx @@ -5,13 +5,14 @@ * 2.0. */ -import React, { FunctionComponent, useCallback } from 'react'; +import type { FunctionComponent } from 'react'; +import React, { useCallback } from 'react'; import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { isEmpty } from 'lodash/fp'; import styled, { css } from 'styled-components'; import * as i18n from './translations'; import { ConfigureCaseButton, LinkButton } from '../links'; -import { ErrorMessage } from '../use_push_to_service/callout/types'; +import type { ErrorMessage } from '../use_push_to_service/callout/types'; import { useCreateCaseNavigation } from '../../common/navigation'; import { useCasesContext } from '../cases_context/use_cases_context'; diff --git a/x-pack/plugins/cases/public/components/all_cases/selector_modal/all_cases_selector_modal.test.tsx b/x-pack/plugins/cases/public/components/all_cases/selector_modal/all_cases_selector_modal.test.tsx index e26831266d65f..8708e5cec06d6 100644 --- a/x-pack/plugins/cases/public/components/all_cases/selector_modal/all_cases_selector_modal.test.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/selector_modal/all_cases_selector_modal.test.tsx @@ -8,7 +8,8 @@ import React from 'react'; import { AllCasesSelectorModal } from '.'; -import { AppMockRenderer, createAppMockRenderer } from '../../../common/mock'; +import type { AppMockRenderer } from '../../../common/mock'; +import { createAppMockRenderer } from '../../../common/mock'; import userEvent from '@testing-library/user-event'; import { act, waitFor } from '@testing-library/react'; diff --git a/x-pack/plugins/cases/public/components/all_cases/selector_modal/all_cases_selector_modal.tsx b/x-pack/plugins/cases/public/components/all_cases/selector_modal/all_cases_selector_modal.tsx index f5007fcd5a092..217893b0923e0 100644 --- a/x-pack/plugins/cases/public/components/all_cases/selector_modal/all_cases_selector_modal.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/selector_modal/all_cases_selector_modal.tsx @@ -16,7 +16,7 @@ import { } from '@elastic/eui'; import styled from 'styled-components'; import { QueryClientProvider } from '@tanstack/react-query'; -import { Case, CaseStatusWithAllStatus } from '../../../../common/ui/types'; +import type { Case, CaseStatusWithAllStatus } from '../../../../common/ui/types'; import * as i18n from '../../../common/translations'; import { AllCasesList } from '../all_cases_list'; import { casesQueryClient } from '../../cases_context/query_client'; diff --git a/x-pack/plugins/cases/public/components/all_cases/selector_modal/index.tsx b/x-pack/plugins/cases/public/components/all_cases/selector_modal/index.tsx index 77e8ebc1a8071..d1d88e9f5b4a4 100644 --- a/x-pack/plugins/cases/public/components/all_cases/selector_modal/index.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/selector_modal/index.tsx @@ -4,7 +4,8 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { AllCasesSelectorModal, AllCasesSelectorModalProps } from './all_cases_selector_modal'; +import type { AllCasesSelectorModalProps } from './all_cases_selector_modal'; +import { AllCasesSelectorModal } from './all_cases_selector_modal'; export type { AllCasesSelectorModalProps }; export { AllCasesSelectorModal }; diff --git a/x-pack/plugins/cases/public/components/all_cases/selector_modal/use_cases_add_to_existing_case_modal.test.tsx b/x-pack/plugins/cases/public/components/all_cases/selector_modal/use_cases_add_to_existing_case_modal.test.tsx index 5dacedf15abc7..d14787fee4a53 100644 --- a/x-pack/plugins/cases/public/components/all_cases/selector_modal/use_cases_add_to_existing_case_modal.test.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/selector_modal/use_cases_add_to_existing_case_modal.test.tsx @@ -10,8 +10,10 @@ import { act, renderHook } from '@testing-library/react-hooks'; import userEvent from '@testing-library/user-event'; import React from 'react'; import AllCasesSelectorModal from '.'; -import { Case, CaseStatuses, StatusAll } from '../../../../common'; -import { allCasesPermissions, AppMockRenderer, createAppMockRenderer } from '../../../common/mock'; +import type { Case } from '../../../../common'; +import { CaseStatuses, StatusAll } from '../../../../common'; +import type { AppMockRenderer } from '../../../common/mock'; +import { allCasesPermissions, createAppMockRenderer } from '../../../common/mock'; import { useCasesToast } from '../../../common/use_cases_toast'; import { alertComment } from '../../../containers/mock'; import { useCreateAttachments } from '../../../containers/use_create_attachments'; diff --git a/x-pack/plugins/cases/public/components/all_cases/selector_modal/use_cases_add_to_existing_case_modal.tsx b/x-pack/plugins/cases/public/components/all_cases/selector_modal/use_cases_add_to_existing_case_modal.tsx index f9f27ebe780d3..2936ebf56d1e3 100644 --- a/x-pack/plugins/cases/public/components/all_cases/selector_modal/use_cases_add_to_existing_case_modal.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/selector_modal/use_cases_add_to_existing_case_modal.tsx @@ -7,13 +7,13 @@ import { useCallback } from 'react'; import { CaseStatuses, StatusAll } from '../../../../common'; -import { AllCasesSelectorModalProps } from '.'; +import type { AllCasesSelectorModalProps } from '.'; import { useCasesToast } from '../../../common/use_cases_toast'; -import { Case } from '../../../containers/types'; +import type { Case } from '../../../containers/types'; import { CasesContextStoreActionsList } from '../../cases_context/cases_context_reducer'; import { useCasesContext } from '../../cases_context/use_cases_context'; import { useCasesAddToNewCaseFlyout } from '../../create/flyout/use_cases_add_to_new_case_flyout'; -import { CaseAttachmentsWithoutOwner } from '../../../types'; +import type { CaseAttachmentsWithoutOwner } from '../../../types'; import { useCreateAttachments } from '../../../containers/use_create_attachments'; import { useAddAttachmentToExistingCaseTransaction } from '../../../common/apm/use_cases_transactions'; diff --git a/x-pack/plugins/cases/public/components/all_cases/severity_filter.test.tsx b/x-pack/plugins/cases/public/components/all_cases/severity_filter.test.tsx index cd2c21e1473a1..3cd200a5ab8ac 100644 --- a/x-pack/plugins/cases/public/components/all_cases/severity_filter.test.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/severity_filter.test.tsx @@ -7,7 +7,8 @@ import { CaseSeverity } from '../../../common/api'; import React from 'react'; -import { AppMockRenderer, createAppMockRenderer } from '../../common/mock'; +import type { AppMockRenderer } from '../../common/mock'; +import { createAppMockRenderer } from '../../common/mock'; import userEvent from '@testing-library/user-event'; import { waitFor } from '@testing-library/dom'; import { waitForEuiPopoverOpen } from '@elastic/eui/lib/test/rtl'; diff --git a/x-pack/plugins/cases/public/components/all_cases/severity_filter.tsx b/x-pack/plugins/cases/public/components/all_cases/severity_filter.tsx index a9f4a6565c318..f421d8828dc20 100644 --- a/x-pack/plugins/cases/public/components/all_cases/severity_filter.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/severity_filter.tsx @@ -5,16 +5,11 @@ * 2.0. */ -import { - EuiFlexGroup, - EuiFlexItem, - EuiHealth, - EuiSuperSelect, - EuiSuperSelectOption, - EuiText, -} from '@elastic/eui'; +import type { EuiSuperSelectOption } from '@elastic/eui'; +import { EuiFlexGroup, EuiFlexItem, EuiHealth, EuiSuperSelect, EuiText } from '@elastic/eui'; import React from 'react'; -import { CaseSeverityWithAll, SeverityAll } from '../../containers/types'; +import type { CaseSeverityWithAll } from '../../containers/types'; +import { SeverityAll } from '../../containers/types'; import { severitiesWithAll } from '../severity/config'; interface Props { diff --git a/x-pack/plugins/cases/public/components/all_cases/status_filter.tsx b/x-pack/plugins/cases/public/components/all_cases/status_filter.tsx index ca211107bcf9a..06a45ee6b5ea3 100644 --- a/x-pack/plugins/cases/public/components/all_cases/status_filter.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/status_filter.tsx @@ -6,9 +6,12 @@ */ import React, { memo } from 'react'; -import { EuiSuperSelect, EuiSuperSelectOption, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; -import { Status, statuses } from '../status'; -import { CaseStatusWithAllStatus, StatusAll } from '../../../common/ui/types'; +import type { EuiSuperSelectOption } from '@elastic/eui'; +import { EuiSuperSelect, EuiFlexGroup, EuiFlexItem, EuiBadge } from '@elastic/eui'; +import { Status } from '@kbn/cases-components'; +import { allCaseStatus, statuses } from '../status'; +import type { CaseStatusWithAllStatus } from '../../../common/ui/types'; +import { StatusAll } from '../../../common/ui/types'; interface Props { stats: Record; @@ -17,6 +20,16 @@ interface Props { hiddenStatuses?: CaseStatusWithAllStatus[]; } +const AllStatusBadge = () => { + return ( + + {allCaseStatus[StatusAll].label} + + ); +}; + +AllStatusBadge.displayName = 'AllStatusBadge'; + const StatusFilterComponent: React.FC = ({ stats, selectedStatus, @@ -31,9 +44,7 @@ const StatusFilterComponent: React.FC = ({ inputDisplay: ( - - - + {status === 'all' ? : } {status !== StatusAll && {` (${stats[status]})`}} diff --git a/x-pack/plugins/cases/public/components/all_cases/table.tsx b/x-pack/plugins/cases/public/components/all_cases/table.tsx index 1f7382351e802..61fb081a0dd9a 100644 --- a/x-pack/plugins/cases/public/components/all_cases/table.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/table.tsx @@ -5,21 +5,16 @@ * 2.0. */ -import React, { FunctionComponent, MutableRefObject, useCallback } from 'react'; -import { - EuiEmptyPrompt, - EuiLoadingContent, - EuiTableSelectionType, - EuiBasicTable, - EuiBasicTableProps, - Pagination, -} from '@elastic/eui'; +import type { FunctionComponent, MutableRefObject } from 'react'; +import React, { useCallback } from 'react'; +import type { EuiTableSelectionType, EuiBasicTableProps, Pagination } from '@elastic/eui'; +import { EuiEmptyPrompt, EuiLoadingContent, EuiBasicTable } from '@elastic/eui'; import classnames from 'classnames'; import styled from 'styled-components'; import { CasesTableUtilityBar } from './utility_bar'; import { LinkButton } from '../links'; -import { Cases, Case } from '../../../common/ui/types'; +import type { Cases, Case } from '../../../common/ui/types'; import * as i18n from './translations'; import { useCreateCaseNavigation } from '../../common/navigation'; import { useCasesContext } from '../cases_context/use_cases_context'; diff --git a/x-pack/plugins/cases/public/components/all_cases/table_filters.test.tsx b/x-pack/plugins/cases/public/components/all_cases/table_filters.test.tsx index 1f43bc2a5636b..416f5ee7f75c2 100644 --- a/x-pack/plugins/cases/public/components/all_cases/table_filters.test.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/table_filters.test.tsx @@ -14,7 +14,8 @@ import { licensingMock } from '@kbn/licensing-plugin/public/mocks'; import { CaseStatuses } from '../../../common/api'; import { OBSERVABILITY_OWNER, SECURITY_SOLUTION_OWNER } from '../../../common/constants'; -import { AppMockRenderer, createAppMockRenderer, TestProviders } from '../../common/mock'; +import type { AppMockRenderer } from '../../common/mock'; +import { createAppMockRenderer, TestProviders } from '../../common/mock'; import { DEFAULT_FILTER_OPTIONS } from '../../containers/use_get_cases'; import { CasesTableFilters } from './table_filters'; import { useGetTags } from '../../containers/use_get_tags'; diff --git a/x-pack/plugins/cases/public/components/all_cases/table_filters.tsx b/x-pack/plugins/cases/public/components/all_cases/table_filters.tsx index 75fc22a9fee27..553132e606aa6 100644 --- a/x-pack/plugins/cases/public/components/all_cases/table_filters.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/table_filters.tsx @@ -10,10 +10,11 @@ import { isEqual } from 'lodash/fp'; import styled from 'styled-components'; import { EuiFlexGroup, EuiFlexItem, EuiFieldSearch, EuiFilterGroup, EuiButton } from '@elastic/eui'; -import { UserProfileWithAvatar } from '@kbn/user-profile-components'; -import { StatusAll, CaseStatusWithAllStatus, CaseSeverityWithAll } from '../../../common/ui/types'; +import type { UserProfileWithAvatar } from '@kbn/user-profile-components'; +import type { CaseStatusWithAllStatus, CaseSeverityWithAll } from '../../../common/ui/types'; +import { StatusAll } from '../../../common/ui/types'; import { CaseStatuses } from '../../../common/api'; -import { FilterOptions } from '../../containers/types'; +import type { FilterOptions } from '../../containers/types'; import { FilterPopover } from '../filter_popover'; import { StatusFilter } from './status_filter'; import * as i18n from './translations'; @@ -21,7 +22,7 @@ import { SeverityFilter } from './severity_filter'; import { useGetTags } from '../../containers/use_get_tags'; import { DEFAULT_FILTER_OPTIONS } from '../../containers/use_get_cases'; import { AssigneesFilterPopover } from './assignees_filter'; -import { CurrentUserProfile } from '../types'; +import type { CurrentUserProfile } from '../types'; import { useCasesFeatures } from '../../common/use_cases_features'; interface CasesTableFiltersProps { diff --git a/x-pack/plugins/cases/public/components/all_cases/use_actions.test.tsx b/x-pack/plugins/cases/public/components/all_cases/use_actions.test.tsx index bf2994a0cad58..a3e118bd6c4f1 100644 --- a/x-pack/plugins/cases/public/components/all_cases/use_actions.test.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/use_actions.test.tsx @@ -12,8 +12,8 @@ import { act, renderHook } from '@testing-library/react-hooks'; import { useActions } from './use_actions'; import { basicCase } from '../../containers/mock'; import * as api from '../../containers/api'; +import type { AppMockRenderer } from '../../common/mock'; import { - AppMockRenderer, createAppMockRenderer, noDeleteCasesPermissions, onlyDeleteCasesPermission, diff --git a/x-pack/plugins/cases/public/components/all_cases/use_actions.tsx b/x-pack/plugins/cases/public/components/all_cases/use_actions.tsx index 1fe7450835e8d..4a73f2cd98a32 100644 --- a/x-pack/plugins/cases/public/components/all_cases/use_actions.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/use_actions.tsx @@ -6,16 +6,14 @@ */ import React, { useCallback, useMemo, useState } from 'react'; -import { - EuiButtonIcon, - EuiContextMenu, +import type { EuiContextMenuPanelDescriptor, EuiContextMenuPanelItemDescriptor, - EuiPopover, EuiTableComputedColumnType, } from '@elastic/eui'; +import { EuiButtonIcon, EuiContextMenu, EuiPopover } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; -import { Case } from '../../containers/types'; +import type { Case } from '../../containers/types'; import { useDeleteAction } from '../actions/delete/use_delete_action'; import { ConfirmDeleteCaseModal } from '../confirm_delete_case'; import { useStatusAction } from '../actions/status/use_status_action'; diff --git a/x-pack/plugins/cases/public/components/all_cases/use_bulk_actions.test.tsx b/x-pack/plugins/cases/public/components/all_cases/use_bulk_actions.test.tsx index cb4c473204ab0..4ca4042e2e5b1 100644 --- a/x-pack/plugins/cases/public/components/all_cases/use_bulk_actions.test.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/use_bulk_actions.test.tsx @@ -11,9 +11,9 @@ import userEvent from '@testing-library/user-event'; import { waitFor } from '@testing-library/react'; import { act, renderHook } from '@testing-library/react-hooks'; +import type { AppMockRenderer } from '../../common/mock'; import { allCasesPermissions, - AppMockRenderer, createAppMockRenderer, noDeleteCasesPermissions, onlyDeleteCasesPermission, diff --git a/x-pack/plugins/cases/public/components/all_cases/use_bulk_actions.tsx b/x-pack/plugins/cases/public/components/all_cases/use_bulk_actions.tsx index dce7d136148de..a1648e764ae80 100644 --- a/x-pack/plugins/cases/public/components/all_cases/use_bulk_actions.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/use_bulk_actions.tsx @@ -5,10 +5,13 @@ * 2.0. */ -import { EuiContextMenuPanelDescriptor, EuiContextMenuPanelItemDescriptor } from '@elastic/eui'; +import type { + EuiContextMenuPanelDescriptor, + EuiContextMenuPanelItemDescriptor, +} from '@elastic/eui'; import React, { useMemo } from 'react'; -import { Case } from '../../containers/types'; +import type { Case } from '../../containers/types'; import { useDeleteAction } from '../actions/delete/use_delete_action'; import { useSeverityAction } from '../actions/severity/use_severity_action'; import { useStatusAction } from '../actions/status/use_status_action'; diff --git a/x-pack/plugins/cases/public/components/all_cases/use_cases_columns.test.tsx b/x-pack/plugins/cases/public/components/all_cases/use_cases_columns.test.tsx index 85caa0b0348dc..424ad669c5b34 100644 --- a/x-pack/plugins/cases/public/components/all_cases/use_cases_columns.test.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/use_cases_columns.test.tsx @@ -10,15 +10,12 @@ import { mount } from 'enzyme'; import { licensingMock } from '@kbn/licensing-plugin/public/mocks'; import '../../common/mock/match_media'; -import { ExternalServiceColumn, GetCasesColumn, useCasesColumns } from './use_cases_columns'; +import type { GetCasesColumn } from './use_cases_columns'; +import { ExternalServiceColumn, useCasesColumns } from './use_cases_columns'; import { useGetCasesMockState } from '../../containers/mock'; import { connectors } from '../configure_cases/__mock__'; -import { - AppMockRenderer, - createAppMockRenderer, - readCasesPermissions, - TestProviders, -} from '../../common/mock'; +import type { AppMockRenderer } from '../../common/mock'; +import { createAppMockRenderer, readCasesPermissions, TestProviders } from '../../common/mock'; import { renderHook } from '@testing-library/react-hooks'; import { CaseStatuses } from '../../../common'; import { userProfilesMap, userProfiles } from '../../containers/user_profiles/api.mock'; diff --git a/x-pack/plugins/cases/public/components/all_cases/use_cases_columns.tsx b/x-pack/plugins/cases/public/components/all_cases/use_cases_columns.tsx index dc90fcfe6c4a5..965277abd2dd3 100644 --- a/x-pack/plugins/cases/public/components/all_cases/use_cases_columns.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/use_cases_columns.tsx @@ -6,14 +6,16 @@ */ import React, { useCallback } from 'react'; +import type { + EuiTableActionsColumnType, + EuiTableComputedColumnType, + EuiTableFieldDataColumnType, +} from '@elastic/eui'; import { EuiBadgeGroup, EuiBadge, EuiButton, EuiLink, - EuiTableActionsColumnType, - EuiTableComputedColumnType, - EuiTableFieldDataColumnType, EuiFlexGroup, EuiFlexItem, EuiIcon, @@ -22,10 +24,12 @@ import { } from '@elastic/eui'; import { RIGHT_ALIGNMENT } from '@elastic/eui/lib/services'; import styled from 'styled-components'; +import { Status } from '@kbn/cases-components'; +import type { UserProfileWithAvatar } from '@kbn/user-profile-components'; -import { UserProfileWithAvatar } from '@kbn/user-profile-components'; -import { Case } from '../../../common/ui/types'; -import { CaseStatuses, ActionConnector, CaseSeverity } from '../../../common/api'; +import type { Case } from '../../../common/ui/types'; +import type { ActionConnector } from '../../../common/api'; +import { CaseStatuses, CaseSeverity } from '../../../common/api'; import { OWNER_INFO } from '../../../common/constants'; import { getEmptyTagValue } from '../empty_value'; import { FormattedRelativePreferenceDate } from '../formatted_date'; @@ -41,10 +45,9 @@ import { severities } from '../severity/config'; import { UserToolTip } from '../user_profiles/user_tooltip'; import { useAssignees } from '../../containers/user_profiles/use_assignees'; import { getUsernameDataTestSubj } from '../user_profiles/data_test_subject'; -import { CurrentUserProfile } from '../types'; +import type { CurrentUserProfile } from '../types'; import { SmallUserAvatar } from '../user_profiles/small_user_avatar'; import { useCasesFeatures } from '../../common/use_cases_features'; -import { Status } from '../status'; type CasesColumns = | EuiTableActionsColumnType @@ -302,7 +305,7 @@ export const useCasesColumns = ({ return getEmptyTagValue(); } - return ; + return ; }, }, { diff --git a/x-pack/plugins/cases/public/components/all_cases/use_on_refresh_cases.test.tsx b/x-pack/plugins/cases/public/components/all_cases/use_on_refresh_cases.test.tsx index cd077004b5cf9..484fabca00c3d 100644 --- a/x-pack/plugins/cases/public/components/all_cases/use_on_refresh_cases.test.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/use_on_refresh_cases.test.tsx @@ -6,7 +6,8 @@ */ import { act, renderHook } from '@testing-library/react-hooks'; -import { AppMockRenderer, createAppMockRenderer } from '../../common/mock'; +import type { AppMockRenderer } from '../../common/mock'; +import { createAppMockRenderer } from '../../common/mock'; import { casesQueriesKeys } from '../../containers/constants'; import { useRefreshCases } from './use_on_refresh_cases'; diff --git a/x-pack/plugins/cases/public/components/all_cases/utility_bar.test.tsx b/x-pack/plugins/cases/public/components/all_cases/utility_bar.test.tsx index 3a8769460656d..2fddd22a9083c 100644 --- a/x-pack/plugins/cases/public/components/all_cases/utility_bar.test.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/utility_bar.test.tsx @@ -8,10 +8,10 @@ import { act, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import React from 'react'; +import type { AppMockRenderer } from '../../common/mock'; import { noCasesPermissions, onlyDeleteCasesPermission, - AppMockRenderer, createAppMockRenderer, writeCasesPermissions, } from '../../common/mock'; diff --git a/x-pack/plugins/cases/public/components/all_cases/utility_bar.tsx b/x-pack/plugins/cases/public/components/all_cases/utility_bar.tsx index 6daf9cb665116..ef735e62d50ec 100644 --- a/x-pack/plugins/cases/public/components/all_cases/utility_bar.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/utility_bar.tsx @@ -5,7 +5,8 @@ * 2.0. */ -import React, { FunctionComponent, useCallback, useState } from 'react'; +import type { FunctionComponent } from 'react'; +import React, { useCallback, useState } from 'react'; import { EuiButtonEmpty, EuiContextMenu, @@ -16,7 +17,7 @@ import { useEuiTheme, } from '@elastic/eui'; import * as i18n from './translations'; -import { Case } from '../../../common/ui/types'; +import type { Case } from '../../../common/ui/types'; import { useRefreshCases } from './use_on_refresh_cases'; import { useBulkActions } from './use_bulk_actions'; import { useCasesContext } from '../cases_context/use_cases_context'; diff --git a/x-pack/plugins/cases/public/components/app/index.tsx b/x-pack/plugins/cases/public/components/app/index.tsx index a8046c078e641..42ef9b658fea7 100644 --- a/x-pack/plugins/cases/public/components/app/index.tsx +++ b/x-pack/plugins/cases/public/components/app/index.tsx @@ -7,13 +7,13 @@ import React from 'react'; import { APP_OWNER } from '../../../common/constants'; -import { ExternalReferenceAttachmentTypeRegistry } from '../../client/attachment_framework/external_reference_registry'; -import { PersistableStateAttachmentTypeRegistry } from '../../client/attachment_framework/persistable_state_registry'; +import type { ExternalReferenceAttachmentTypeRegistry } from '../../client/attachment_framework/external_reference_registry'; +import type { PersistableStateAttachmentTypeRegistry } from '../../client/attachment_framework/persistable_state_registry'; import { getCasesLazy } from '../../client/ui/get_cases'; import { useApplicationCapabilities } from '../../common/lib/kibana'; import { Wrapper } from '../wrappers'; -import { CasesRoutesProps } from './types'; +import type { CasesRoutesProps } from './types'; export type CasesProps = CasesRoutesProps; diff --git a/x-pack/plugins/cases/public/components/app/routes.test.tsx b/x-pack/plugins/cases/public/components/app/routes.test.tsx index 205545b682857..e905c831e398b 100644 --- a/x-pack/plugins/cases/public/components/app/routes.test.tsx +++ b/x-pack/plugins/cases/public/components/app/routes.test.tsx @@ -7,7 +7,7 @@ import React from 'react'; // eslint-disable-next-line @kbn/eslint/module_migration -import { MemoryRouterProps } from 'react-router'; +import type { MemoryRouterProps } from 'react-router'; import { render, screen, waitFor } from '@testing-library/react'; import { MemoryRouter } from 'react-router-dom'; import { @@ -17,7 +17,7 @@ import { TestProviders, } from '../../common/mock'; import { CasesRoutes } from './routes'; -import { CasesPermissions } from '../../../common'; +import type { CasesPermissions } from '../../../common'; jest.mock('../all_cases', () => ({ AllCases: () =>
{'All cases'}
, diff --git a/x-pack/plugins/cases/public/components/app/routes.tsx b/x-pack/plugins/cases/public/components/app/routes.tsx index 062007f3341e6..8755689102800 100644 --- a/x-pack/plugins/cases/public/components/app/routes.tsx +++ b/x-pack/plugins/cases/public/components/app/routes.tsx @@ -13,7 +13,7 @@ import { EuiLoadingSpinner } from '@elastic/eui'; import { AllCases } from '../all_cases'; import { CreateCase } from '../create'; import { ConfigureCases } from '../configure_cases'; -import { CasesRoutesProps } from './types'; +import type { CasesRoutesProps } from './types'; import { useCasesContext } from '../cases_context/use_cases_context'; import { getCasesConfigurePath, diff --git a/x-pack/plugins/cases/public/components/app/types.ts b/x-pack/plugins/cases/public/components/app/types.ts index 1df4d54188ec0..e11366d02d853 100644 --- a/x-pack/plugins/cases/public/components/app/types.ts +++ b/x-pack/plugins/cases/public/components/app/types.ts @@ -5,10 +5,10 @@ * 2.0. */ -import { MutableRefObject } from 'react'; -import { CaseViewRefreshPropInterface, UseFetchAlertData } from '../../../common/ui/types'; -import { CasesNavigation } from '../links'; -import { CasesTimelineIntegration } from '../timeline_context'; +import type { MutableRefObject } from 'react'; +import type { CaseViewRefreshPropInterface, UseFetchAlertData } from '../../../common/ui/types'; +import type { CasesNavigation } from '../links'; +import type { CasesTimelineIntegration } from '../timeline_context'; export interface CasesRoutesProps { onComponentInitialized?: () => void; diff --git a/x-pack/plugins/cases/public/components/app/use_available_owners.ts b/x-pack/plugins/cases/public/components/app/use_available_owners.ts index c981a6a01e063..c829b9c590d01 100644 --- a/x-pack/plugins/cases/public/components/app/use_available_owners.ts +++ b/x-pack/plugins/cases/public/components/app/use_available_owners.ts @@ -7,7 +7,7 @@ import { APP_ID, FEATURE_ID } from '../../../common/constants'; import { useKibana } from '../../common/lib/kibana'; -import { CasesPermissions } from '../../containers/types'; +import type { CasesPermissions } from '../../containers/types'; import { allCasePermissions } from '../../utils/permissions'; type Capability = Exclude; diff --git a/x-pack/plugins/cases/public/components/callouts/case_callouts.test.tsx b/x-pack/plugins/cases/public/components/callouts/case_callouts.test.tsx index 2d499bded55ee..695fe6c7a08b6 100644 --- a/x-pack/plugins/cases/public/components/callouts/case_callouts.test.tsx +++ b/x-pack/plugins/cases/public/components/callouts/case_callouts.test.tsx @@ -7,7 +7,8 @@ import React from 'react'; import { licensingMock } from '@kbn/licensing-plugin/public/mocks'; -import { AppMockRenderer, createAppMockRenderer } from '../../common/mock'; +import type { AppMockRenderer } from '../../common/mock'; +import { createAppMockRenderer } from '../../common/mock'; import { CaseCallouts } from './case_callouts'; describe('CaseCallouts ', () => { diff --git a/x-pack/plugins/cases/public/components/callouts/platinum_callout.test.tsx b/x-pack/plugins/cases/public/components/callouts/platinum_callout.test.tsx index bad098a7562d4..680c5fcf78925 100644 --- a/x-pack/plugins/cases/public/components/callouts/platinum_callout.test.tsx +++ b/x-pack/plugins/cases/public/components/callouts/platinum_callout.test.tsx @@ -6,7 +6,8 @@ */ import React from 'react'; -import { AppMockRenderer, createAppMockRenderer } from '../../common/mock'; +import type { AppMockRenderer } from '../../common/mock'; +import { createAppMockRenderer } from '../../common/mock'; import { PlatinumLicenseCallout } from './platinum_callout'; describe('PlatinumLicenseCallout ', () => { diff --git a/x-pack/plugins/cases/public/components/case_action_bar/actions.tsx b/x-pack/plugins/cases/public/components/case_action_bar/actions.tsx index 2481822f76b8d..414ac6326ef5d 100644 --- a/x-pack/plugins/cases/public/components/case_action_bar/actions.tsx +++ b/x-pack/plugins/cases/public/components/case_action_bar/actions.tsx @@ -12,8 +12,8 @@ import * as i18n from '../case_view/translations'; import { useDeleteCases } from '../../containers/use_delete_cases'; import { ConfirmDeleteCaseModal } from '../confirm_delete_case'; import { PropertyActions } from '../property_actions'; -import { Case } from '../../../common/ui/types'; -import { CaseService } from '../../containers/use_get_case_user_actions'; +import type { Case } from '../../../common/ui/types'; +import type { CaseService } from '../../containers/use_get_case_user_actions'; import { useAllCasesNavigation } from '../../common/navigation'; import { useCasesContext } from '../cases_context/use_cases_context'; diff --git a/x-pack/plugins/cases/public/components/case_action_bar/helpers.ts b/x-pack/plugins/cases/public/components/case_action_bar/helpers.ts index b26c33b0fd009..772bedd266dd8 100644 --- a/x-pack/plugins/cases/public/components/case_action_bar/helpers.ts +++ b/x-pack/plugins/cases/public/components/case_action_bar/helpers.ts @@ -6,7 +6,7 @@ */ import { CaseStatuses } from '../../../common/api'; -import { Case } from '../../containers/types'; +import type { Case } from '../../containers/types'; import { statuses } from '../status'; export const getStatusDate = (theCase: Case): string | null => { diff --git a/x-pack/plugins/cases/public/components/case_action_bar/index.test.tsx b/x-pack/plugins/cases/public/components/case_action_bar/index.test.tsx index 1802a063ca932..dc2cbccc229c2 100644 --- a/x-pack/plugins/cases/public/components/case_action_bar/index.test.tsx +++ b/x-pack/plugins/cases/public/components/case_action_bar/index.test.tsx @@ -11,7 +11,8 @@ import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { basicCase, caseUserActions, getAlertUserAction } from '../../containers/mock'; -import { CaseActionBar, CaseActionBarProps } from '.'; +import type { CaseActionBarProps } from '.'; +import { CaseActionBar } from '.'; import { allCasesPermissions, noDeleteCasesPermissions, diff --git a/x-pack/plugins/cases/public/components/case_action_bar/index.tsx b/x-pack/plugins/cases/public/components/case_action_bar/index.tsx index 09c59d0d6cc39..3d68fcaa4d56d 100644 --- a/x-pack/plugins/cases/public/components/case_action_bar/index.tsx +++ b/x-pack/plugins/cases/public/components/case_action_bar/index.tsx @@ -17,8 +17,8 @@ import { EuiIconTip, EuiLoadingSpinner, } from '@elastic/eui'; -import { Case } from '../../../common/ui/types'; -import { CaseStatuses } from '../../../common/api'; +import type { Case } from '../../../common/ui/types'; +import type { CaseStatuses } from '../../../common/api'; import * as i18n from '../case_view/translations'; import { Actions } from './actions'; import { useGetCaseUserActions } from '../../containers/use_get_case_user_actions'; @@ -107,7 +107,8 @@ const CaseActionBarComponent: React.FC = ({ diff --git a/x-pack/plugins/cases/public/components/case_action_bar/status_context_menu.test.tsx b/x-pack/plugins/cases/public/components/case_action_bar/status_context_menu.test.tsx index 4a67eada2e00d..692307229cc84 100644 --- a/x-pack/plugins/cases/public/components/case_action_bar/status_context_menu.test.tsx +++ b/x-pack/plugins/cases/public/components/case_action_bar/status_context_menu.test.tsx @@ -18,7 +18,7 @@ describe('SyncAlertsSwitch', () => { jest.clearAllMocks(); }); - it('it renders', async () => { + it('renders', async () => { const wrapper = mount( ); @@ -26,7 +26,7 @@ describe('SyncAlertsSwitch', () => { expect(wrapper.find(`[data-test-subj="case-view-status-dropdown"]`).exists()).toBeTruthy(); }); - it('it renders when disabled', async () => { + it('renders a simple status badge when disabled', async () => { const wrapper = mount( { /> ); - expect(wrapper.find(`[data-test-subj="case-view-status-dropdown"]`).exists()).toBeTruthy(); + expect(wrapper.find(`[data-test-subj="case-view-status-dropdown"]`).exists()).toBeFalsy(); + expect(wrapper.find(`[data-test-subj="case-status-badge-open"]`).exists()).toBeTruthy(); }); - it('it renders the current status correctly', async () => { + it('renders the current status correctly', async () => { const wrapper = mount( ); @@ -48,7 +49,7 @@ describe('SyncAlertsSwitch', () => { ); }); - it('it changes the status', async () => { + it('changes the status', async () => { const wrapper = mount( ); @@ -61,7 +62,7 @@ describe('SyncAlertsSwitch', () => { expect(onStatusChanged).toHaveBeenCalledWith('in-progress'); }); - it('it does not call onStatusChanged if selection is same as current status', async () => { + it('does not call onStatusChanged if selection is same as current status', async () => { const wrapper = mount( ); diff --git a/x-pack/plugins/cases/public/components/case_action_bar/status_context_menu.tsx b/x-pack/plugins/cases/public/components/case_action_bar/status_context_menu.tsx index dce26fcbd5965..ab1c728ad6f35 100644 --- a/x-pack/plugins/cases/public/components/case_action_bar/status_context_menu.tsx +++ b/x-pack/plugins/cases/public/components/case_action_bar/status_context_menu.tsx @@ -7,27 +7,42 @@ import React, { memo, useCallback, useMemo, useState } from 'react'; import { EuiPopover, EuiContextMenuPanel, EuiContextMenuItem } from '@elastic/eui'; -import { caseStatuses, CaseStatuses } from '../../../common/api'; -import { Status } from '../status'; +import { Status } from '@kbn/cases-components'; +import type { CaseStatuses } from '../../../common/api'; +import { caseStatuses } from '../../../common/api'; +import { StatusPopoverButton } from '../status'; import { CHANGE_STATUS } from '../all_cases/translations'; interface Props { currentStatus: CaseStatuses; disabled?: boolean; + isLoading?: boolean; onStatusChanged: (status: CaseStatuses) => void; } const StatusContextMenuComponent: React.FC = ({ currentStatus, disabled = false, + isLoading = false, onStatusChanged, }) => { const [isPopoverOpen, setIsPopoverOpen] = useState(false); + const togglePopover = useCallback( + () => setIsPopoverOpen((prevPopoverStatus) => !prevPopoverStatus), + [] + ); + const closePopover = useCallback(() => setIsPopoverOpen(false), []); - const openPopover = useCallback(() => setIsPopoverOpen(true), []); + const popOverButton = useMemo( - () => , - [disabled, currentStatus, openPopover] + () => ( + + ), + [disabled, currentStatus, togglePopover, isLoading] ); const onContextMenuItemClick = useCallback( @@ -49,12 +64,16 @@ const StatusContextMenuComponent: React.FC = ({ key={status} onClick={() => onContextMenuItemClick(status)} > - + )), [currentStatus, onContextMenuItemClick] ); + if (disabled) { + return ; + } + return ( = ({ ); }; + StatusContextMenuComponent.displayName = 'StatusContextMenu'; export const StatusContextMenu = memo(StatusContextMenuComponent); diff --git a/x-pack/plugins/cases/public/components/case_view/case_view_page.test.tsx b/x-pack/plugins/cases/public/components/case_view/case_view_page.test.tsx index a06ae9e772c11..7a299257b8017 100644 --- a/x-pack/plugins/cases/public/components/case_view/case_view_page.test.tsx +++ b/x-pack/plugins/cases/public/components/case_view/case_view_page.test.tsx @@ -10,12 +10,14 @@ import { act, waitFor, within } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { waitForEuiPopoverOpen } from '@elastic/eui/lib/test/rtl'; import { ConnectorTypes } from '../../../common/api'; -import { AppMockRenderer, createAppMockRenderer } from '../../common/mock'; +import type { AppMockRenderer } from '../../common/mock'; +import { createAppMockRenderer } from '../../common/mock'; import '../../common/mock/match_media'; import { useCaseViewNavigation, useUrlParams } from '../../common/navigation/hooks'; import { useGetConnectors } from '../../containers/configure/use_connectors'; import { basicCaseClosed, connectorsMock } from '../../containers/mock'; -import { useGetCase, UseGetCase } from '../../containers/use_get_case'; +import type { UseGetCase } from '../../containers/use_get_case'; +import { useGetCase } from '../../containers/use_get_case'; import { useGetCaseMetrics } from '../../containers/use_get_case_metrics'; import { useGetCaseUserActions } from '../../containers/use_get_case_user_actions'; import { useGetTags } from '../../containers/use_get_tags'; @@ -31,9 +33,10 @@ import { defaultUpdateCaseState, defaultUseGetCaseUserActions, } from './mocks'; -import { CaseViewPageProps, CASE_VIEW_PAGE_TABS } from './types'; +import type { CaseViewPageProps } from './types'; import { userProfiles } from '../../containers/user_profiles/api.mock'; import { licensingMock } from '@kbn/licensing-plugin/public/mocks'; +import { CASE_VIEW_PAGE_TABS } from '../../../common/types'; jest.mock('../../containers/use_get_action_license'); jest.mock('../../containers/use_update_case'); diff --git a/x-pack/plugins/cases/public/components/case_view/case_view_page.tsx b/x-pack/plugins/cases/public/components/case_view/case_view_page.tsx index 0075fb985f113..af796ff796d85 100644 --- a/x-pack/plugins/cases/public/components/case_view/case_view_page.tsx +++ b/x-pack/plugins/cases/public/components/case_view/case_view_page.tsx @@ -8,6 +8,7 @@ import { EuiBetaBadge, EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiTab, EuiTabs } from '@elastic/eui'; import React, { useCallback, useEffect, useMemo, useRef } from 'react'; import styled from 'styled-components'; +import { CASE_VIEW_PAGE_TABS } from '../../../common/types'; import { useCaseViewNavigation, useUrlParams } from '../../common/navigation'; import { useCasesContext } from '../cases_context/use_cases_context'; import { CaseActionBar } from '../case_action_bar'; @@ -21,7 +22,7 @@ import { CaseViewActivity } from './components/case_view_activity'; import { CaseViewAlerts } from './components/case_view_alerts'; import { CaseViewMetrics } from './metrics'; import { ACTIVITY_TAB, ALERTS_TAB } from './translations'; -import { CaseViewPageProps, CASE_VIEW_PAGE_TABS } from './types'; +import type { CaseViewPageProps } from './types'; import { useRefreshCaseViewPage } from './use_on_refresh_case_view_page'; import { useOnUpdateField } from './use_on_update_field'; diff --git a/x-pack/plugins/cases/public/components/case_view/components/assign_users.test.tsx b/x-pack/plugins/cases/public/components/case_view/components/assign_users.test.tsx index fdd4b5cb77e7d..b14e52c9e51dc 100644 --- a/x-pack/plugins/cases/public/components/case_view/components/assign_users.test.tsx +++ b/x-pack/plugins/cases/public/components/case_view/components/assign_users.test.tsx @@ -10,12 +10,10 @@ import { useGetCurrentUserProfile } from '../../../containers/user_profiles/use_ import { userProfiles, userProfilesMap } from '../../../containers/user_profiles/api.mock'; import { fireEvent, screen, waitFor } from '@testing-library/react'; import React from 'react'; -import { - AppMockRenderer, - createAppMockRenderer, - noUpdateCasesPermissions, -} from '../../../common/mock'; -import { AssignUsers, AssignUsersProps } from './assign_users'; +import type { AppMockRenderer } from '../../../common/mock'; +import { createAppMockRenderer, noUpdateCasesPermissions } from '../../../common/mock'; +import type { AssignUsersProps } from './assign_users'; +import { AssignUsers } from './assign_users'; import { waitForEuiPopoverClose, waitForEuiPopoverOpen } from '@elastic/eui/lib/test/rtl'; jest.mock('../../../containers/user_profiles/use_suggest_user_profiles'); diff --git a/x-pack/plugins/cases/public/components/case_view/components/assign_users.tsx b/x-pack/plugins/cases/public/components/case_view/components/assign_users.tsx index c1f72f84a6444..90d227901259a 100644 --- a/x-pack/plugins/cases/public/components/case_view/components/assign_users.tsx +++ b/x-pack/plugins/cases/public/components/case_view/components/assign_users.tsx @@ -15,17 +15,17 @@ import { EuiHorizontalRule, } from '@elastic/eui'; -import { UserProfileWithAvatar } from '@kbn/user-profile-components'; -import { CasesPermissions } from '../../../../common'; +import type { UserProfileWithAvatar } from '@kbn/user-profile-components'; +import type { CasesPermissions } from '../../../../common'; import { useAssignees } from '../../../containers/user_profiles/use_assignees'; -import { CaseAssignees } from '../../../../common/api/cases/assignee'; +import type { CaseAssignees } from '../../../../common/api/cases/assignee'; import * as i18n from '../translations'; import { SidebarTitle } from './sidebar_title'; import { RemovableUser } from '../../user_profiles/removable_user'; import { useCasesContext } from '../../cases_context/use_cases_context'; -import { Assignee } from '../../user_profiles/types'; +import type { Assignee } from '../../user_profiles/types'; import { SuggestUsersPopover } from './suggest_users_popover'; -import { CurrentUserProfile } from '../../types'; +import type { CurrentUserProfile } from '../../types'; interface AssigneesListProps { assignees: Assignee[]; diff --git a/x-pack/plugins/cases/public/components/case_view/components/case_view_activity.test.tsx b/x-pack/plugins/cases/public/components/case_view/components/case_view_activity.test.tsx index fe08ce1fabed4..78afb00693423 100644 --- a/x-pack/plugins/cases/public/components/case_view/components/case_view_activity.test.tsx +++ b/x-pack/plugins/cases/public/components/case_view/components/case_view_activity.test.tsx @@ -13,15 +13,12 @@ import { getAlertUserAction, } from '../../../containers/mock'; import React from 'react'; -import { - AppMockRenderer, - createAppMockRenderer, - noUpdateCasesPermissions, -} from '../../../common/mock'; +import type { AppMockRenderer } from '../../../common/mock'; +import { createAppMockRenderer, noUpdateCasesPermissions } from '../../../common/mock'; import { CaseViewActivity } from './case_view_activity'; import { ConnectorTypes } from '../../../../common/api/connectors'; -import { Case } from '../../../../common'; -import { CaseViewProps } from '../types'; +import type { Case } from '../../../../common'; +import type { CaseViewProps } from '../types'; import { useGetCaseUserActions } from '../../../containers/use_get_case_user_actions'; import { usePostPushToService } from '../../../containers/use_post_push_to_service'; import { useGetConnectors } from '../../../containers/configure/use_connectors'; diff --git a/x-pack/plugins/cases/public/components/case_view/components/case_view_activity.tsx b/x-pack/plugins/cases/public/components/case_view/components/case_view_activity.tsx index 9af7b6f1cbd17..8b2b17f544d3b 100644 --- a/x-pack/plugins/cases/public/components/case_view/components/case_view_activity.tsx +++ b/x-pack/plugins/cases/public/components/case_view/components/case_view_activity.tsx @@ -14,12 +14,12 @@ import { useCasesFeatures } from '../../../common/use_cases_features'; import { useGetCurrentUserProfile } from '../../../containers/user_profiles/use_get_current_user_profile'; import { useBulkGetUserProfiles } from '../../../containers/user_profiles/use_bulk_get_user_profiles'; import { useGetConnectors } from '../../../containers/configure/use_connectors'; -import { CaseSeverity } from '../../../../common/api'; +import type { CaseSeverity } from '../../../../common/api'; import { useCaseViewNavigation } from '../../../common/navigation'; -import { UseFetchAlertData } from '../../../../common/ui/types'; -import { Case, CaseStatuses } from '../../../../common'; +import type { UseFetchAlertData } from '../../../../common/ui/types'; +import type { Case, CaseStatuses } from '../../../../common'; import { EditConnector } from '../../edit_connector'; -import { CasesNavigation } from '../../links'; +import type { CasesNavigation } from '../../links'; import { StatusActionButton } from '../../status/button'; import { EditTags } from './edit_tags'; import { UserActions } from '../../user_actions'; @@ -32,7 +32,7 @@ import { getConnectorById } from '../../utils'; import { SeveritySidebarSelector } from '../../severity/sidebar_selector'; import { useGetCaseUserActions } from '../../../containers/use_get_case_user_actions'; import { AssignUsers } from './assign_users'; -import { Assignee } from '../../user_profiles/types'; +import type { Assignee } from '../../user_profiles/types'; export const CaseViewActivity = ({ ruleDetailsNavigation, diff --git a/x-pack/plugins/cases/public/components/case_view/components/case_view_alerts.test.tsx b/x-pack/plugins/cases/public/components/case_view/components/case_view_alerts.test.tsx index 67b57533f9b49..87bcf1557f579 100644 --- a/x-pack/plugins/cases/public/components/case_view/components/case_view_alerts.test.tsx +++ b/x-pack/plugins/cases/public/components/case_view/components/case_view_alerts.test.tsx @@ -8,8 +8,9 @@ import React from 'react'; import { waitFor } from '@testing-library/dom'; import { alertCommentWithIndices, basicCase } from '../../../containers/mock'; -import { AppMockRenderer, createAppMockRenderer } from '../../../common/mock'; -import { Case } from '../../../../common'; +import type { AppMockRenderer } from '../../../common/mock'; +import { createAppMockRenderer } from '../../../common/mock'; +import type { Case } from '../../../../common'; import { CaseViewAlerts } from './case_view_alerts'; import * as api from '../../../containers/api'; diff --git a/x-pack/plugins/cases/public/components/case_view/components/case_view_alerts.tsx b/x-pack/plugins/cases/public/components/case_view/components/case_view_alerts.tsx index 0bd582e1cef62..ccf5579dc1c7e 100644 --- a/x-pack/plugins/cases/public/components/case_view/components/case_view_alerts.tsx +++ b/x-pack/plugins/cases/public/components/case_view/components/case_view_alerts.tsx @@ -7,8 +7,9 @@ import React, { useMemo } from 'react'; -import { EuiFlexItem, EuiFlexGroup, EuiProgress, EuiFlyoutSize } from '@elastic/eui'; -import { Case } from '../../../../common'; +import type { EuiFlyoutSize } from '@elastic/eui'; +import { EuiFlexItem, EuiFlexGroup, EuiProgress } from '@elastic/eui'; +import type { Case } from '../../../../common'; import { useKibana } from '../../../common/lib/kibana'; import { getManualAlertIds, getRegistrationContextFromAlerts } from './helpers'; import { useGetFeatureIds } from '../../../containers/use_get_feature_ids'; diff --git a/x-pack/plugins/cases/public/components/case_view/components/edit_tags.test.tsx b/x-pack/plugins/cases/public/components/case_view/components/edit_tags.test.tsx index 2302da1efb89c..d63aae3eb74b0 100644 --- a/x-pack/plugins/cases/public/components/case_view/components/edit_tags.test.tsx +++ b/x-pack/plugins/cases/public/components/case_view/components/edit_tags.test.tsx @@ -8,7 +8,8 @@ import React from 'react'; import { mount } from 'enzyme'; -import { EditTags, EditTagsProps } from './edit_tags'; +import type { EditTagsProps } from './edit_tags'; +import { EditTags } from './edit_tags'; import { getFormMock } from '../../__mock__/form'; import { readCasesPermissions, TestProviders } from '../../../common/mock'; import { waitFor } from '@testing-library/react'; 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 0dd651f6c9251..3a3a01cc49e94 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 @@ -19,13 +19,13 @@ import { 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 { Form, FormDataProvider, useForm, getUseField, Field, - FormSchema, } from '../../../common/shared_imports'; import { useGetTags } from '../../../containers/use_get_tags'; import { Tags } from '../../tags/tags'; diff --git a/x-pack/plugins/cases/public/components/case_view/components/suggest_users_popover.test.tsx b/x-pack/plugins/cases/public/components/case_view/components/suggest_users_popover.test.tsx index f38857fbbfe5d..479b8e39d232d 100644 --- a/x-pack/plugins/cases/public/components/case_view/components/suggest_users_popover.test.tsx +++ b/x-pack/plugins/cases/public/components/case_view/components/suggest_users_popover.test.tsx @@ -6,13 +6,15 @@ */ import React from 'react'; -import { AppMockRenderer, createAppMockRenderer } from '../../../common/mock'; +import type { AppMockRenderer } from '../../../common/mock'; +import { createAppMockRenderer } from '../../../common/mock'; import { screen, fireEvent, waitFor } from '@testing-library/react'; -import { SuggestUsersPopoverProps, SuggestUsersPopover } from './suggest_users_popover'; +import type { SuggestUsersPopoverProps } from './suggest_users_popover'; +import { SuggestUsersPopover } from './suggest_users_popover'; import { userProfiles } from '../../../containers/user_profiles/api.mock'; import { waitForEuiPopoverOpen } from '@elastic/eui/lib/test/rtl'; -import { UserProfileWithAvatar } from '@kbn/user-profile-components'; -import { AssigneeWithProfile } from '../../user_profiles/types'; +import type { UserProfileWithAvatar } from '@kbn/user-profile-components'; +import type { AssigneeWithProfile } from '../../user_profiles/types'; jest.mock('../../../containers/user_profiles/api'); diff --git a/x-pack/plugins/cases/public/components/case_view/components/suggest_users_popover.tsx b/x-pack/plugins/cases/public/components/case_view/components/suggest_users_popover.tsx index cb824adf0a217..fd73d3a2ae7ce 100644 --- a/x-pack/plugins/cases/public/components/case_view/components/suggest_users_popover.tsx +++ b/x-pack/plugins/cases/public/components/case_view/components/suggest_users_popover.tsx @@ -6,19 +6,20 @@ */ import React, { useCallback, useMemo, useState } from 'react'; -import { UserProfilesPopover, UserProfileWithAvatar } from '@kbn/user-profile-components'; +import type { UserProfileWithAvatar } from '@kbn/user-profile-components'; +import { UserProfilesPopover } from '@kbn/user-profile-components'; import { EuiButtonIcon, EuiToolTip } from '@elastic/eui'; import { isEmpty } from 'lodash'; import { useSuggestUserProfiles } from '../../../containers/user_profiles/use_suggest_user_profiles'; import { useCasesContext } from '../../cases_context/use_cases_context'; -import { AssigneeWithProfile } from '../../user_profiles/types'; +import type { AssigneeWithProfile } from '../../user_profiles/types'; import * as i18n from '../translations'; import { bringCurrentUserToFrontAndSort } from '../../user_profiles/sort'; import { SelectedStatusMessage } from '../../user_profiles/selected_status_message'; import { EmptyMessage } from '../../user_profiles/empty_message'; import { NoMatches } from '../../user_profiles/no_matches'; -import { CurrentUserProfile } from '../../types'; +import type { CurrentUserProfile } from '../../types'; const PopoverButton: React.FC<{ togglePopover: () => void; isDisabled: boolean }> = ({ togglePopover, diff --git a/x-pack/plugins/cases/public/components/case_view/components/user_list.tsx b/x-pack/plugins/cases/public/components/case_view/components/user_list.tsx index ae90712e9cfdb..3ae7f0541ea91 100644 --- a/x-pack/plugins/cases/public/components/case_view/components/user_list.tsx +++ b/x-pack/plugins/cases/public/components/case_view/components/user_list.tsx @@ -19,10 +19,10 @@ import { import styled, { css } from 'styled-components'; -import { UserProfileWithAvatar } from '@kbn/user-profile-components'; -import { ElasticUser } from '../../../containers/types'; +import type { UserProfileWithAvatar } from '@kbn/user-profile-components'; +import type { ElasticUser } from '../../../containers/types'; import * as i18n from '../translations'; -import { UserInfoWithAvatar } from '../../user_profiles/types'; +import type { UserInfoWithAvatar } from '../../user_profiles/types'; import { HoverableUserWithAvatar } from '../../user_profiles/hoverable_user_with_avatar'; import { convertToUserInfo } from '../../user_profiles/user_converter'; diff --git a/x-pack/plugins/cases/public/components/case_view/index.test.tsx b/x-pack/plugins/cases/public/components/case_view/index.test.tsx index 6a5fd8fad8113..c745cd9d01c74 100644 --- a/x-pack/plugins/cases/public/components/case_view/index.test.tsx +++ b/x-pack/plugins/cases/public/components/case_view/index.test.tsx @@ -15,18 +15,20 @@ import React from 'react'; import '../../common/mock/match_media'; -import { CaseViewProps } from './types'; +import type { CaseViewProps } from './types'; import { connectorsMock } from '../../containers/mock'; -import { SpacesApi } from '@kbn/spaces-plugin/public'; +import type { SpacesApi } from '@kbn/spaces-plugin/public'; import { useUpdateCase } from '../../containers/use_update_case'; -import { UseGetCase, useGetCase } from '../../containers/use_get_case'; +import type { UseGetCase } from '../../containers/use_get_case'; +import { useGetCase } from '../../containers/use_get_case'; import { useGetCaseMetrics } from '../../containers/use_get_case_metrics'; import { usePostPushToService } from '../../containers/use_post_push_to_service'; import { useKibana } from '../../common/lib/kibana'; import { useGetCaseUserActions } from '../../containers/use_get_case_user_actions'; import { useGetConnectors } from '../../containers/configure/use_connectors'; -import { AppMockRenderer, createAppMockRenderer } from '../../common/mock'; +import type { AppMockRenderer } from '../../common/mock'; +import { createAppMockRenderer } from '../../common/mock'; import CaseView from '.'; import { waitFor } from '@testing-library/dom'; import { useGetTags } from '../../containers/use_get_tags'; diff --git a/x-pack/plugins/cases/public/components/case_view/metrics/index.test.tsx b/x-pack/plugins/cases/public/components/case_view/metrics/index.test.tsx index ebe2d35f55db4..166ec92d5798c 100644 --- a/x-pack/plugins/cases/public/components/case_view/metrics/index.test.tsx +++ b/x-pack/plugins/cases/public/components/case_view/metrics/index.test.tsx @@ -13,7 +13,7 @@ import { basicCaseStatusFeatures, } from '../../../containers/mock'; import { CaseViewMetrics } from '.'; -import { SingleCaseMetrics, SingleCaseMetricsFeature } from '../../../../common/ui'; +import type { SingleCaseMetrics, SingleCaseMetricsFeature } from '../../../../common/ui'; import { TestProviders } from '../../../common/mock'; import { useGetCaseMetrics } from '../../../containers/use_get_case_metrics'; import { useCasesFeatures } from '../../../common/use_cases_features'; diff --git a/x-pack/plugins/cases/public/components/case_view/metrics/status.tsx b/x-pack/plugins/cases/public/components/case_view/metrics/status.tsx index e67f554d2394d..e7364f029fc2d 100644 --- a/x-pack/plugins/cases/public/components/case_view/metrics/status.tsx +++ b/x-pack/plugins/cases/public/components/case_view/metrics/status.tsx @@ -9,7 +9,7 @@ import React, { useMemo } from 'react'; import prettyMilliseconds from 'pretty-ms'; import { EuiFlexGrid, EuiFlexGroup, EuiFlexItem, EuiIconTip, EuiSpacer } from '@elastic/eui'; import { euiStyled } from '@kbn/kibana-react-plugin/common'; -import { SingleCaseMetrics, SingleCaseMetricsFeature } from '../../../../common/ui'; +import type { SingleCaseMetrics, SingleCaseMetricsFeature } from '../../../../common/ui'; import { CASE_CREATED, CASE_IN_PROGRESS_DURATION, diff --git a/x-pack/plugins/cases/public/components/case_view/metrics/totals.tsx b/x-pack/plugins/cases/public/components/case_view/metrics/totals.tsx index 922f3f83e2254..dd81a2328a97a 100644 --- a/x-pack/plugins/cases/public/components/case_view/metrics/totals.tsx +++ b/x-pack/plugins/cases/public/components/case_view/metrics/totals.tsx @@ -8,7 +8,7 @@ import React, { useMemo } from 'react'; import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { euiStyled } from '@kbn/kibana-react-plugin/common'; -import { SingleCaseMetrics, SingleCaseMetricsFeature } from '../../../../common/ui'; +import type { SingleCaseMetrics, SingleCaseMetricsFeature } from '../../../../common/ui'; import { ASSOCIATED_HOSTS_METRIC, ASSOCIATED_USERS_METRIC, diff --git a/x-pack/plugins/cases/public/components/case_view/mocks.ts b/x-pack/plugins/cases/public/components/case_view/mocks.ts index 41bc35eeb7b4a..1df9907d7f2e2 100644 --- a/x-pack/plugins/cases/public/components/case_view/mocks.ts +++ b/x-pack/plugins/cases/public/components/case_view/mocks.ts @@ -13,8 +13,8 @@ import { caseUserActions, getAlertUserAction, } from '../../containers/mock'; -import { Case } from '../../containers/types'; -import { CaseViewProps } from './types'; +import type { Case } from '../../containers/types'; +import type { CaseViewProps } from './types'; export const alertsHit = [ { diff --git a/x-pack/plugins/cases/public/components/case_view/types.ts b/x-pack/plugins/cases/public/components/case_view/types.ts index 3f6e058013993..0e6bf82c5fef9 100644 --- a/x-pack/plugins/cases/public/components/case_view/types.ts +++ b/x-pack/plugins/cases/public/components/case_view/types.ts @@ -4,11 +4,11 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { MutableRefObject } from 'react'; -import { CasesTimelineIntegration } from '../timeline_context'; -import { CasesNavigation } from '../links'; -import { CaseViewRefreshPropInterface, Case } from '../../../common'; -import { UseFetchAlertData } from '../../../common/ui'; +import type { MutableRefObject } from 'react'; +import type { CasesTimelineIntegration } from '../timeline_context'; +import type { CasesNavigation } from '../links'; +import type { CaseViewRefreshPropInterface, Case } from '../../../common'; +import type { UseFetchAlertData } from '../../../common/ui'; export interface CaseViewBaseProps { onComponentInitialized?: () => void; @@ -39,8 +39,3 @@ export interface OnUpdateFields { onSuccess?: () => void; onError?: () => void; } - -export enum CASE_VIEW_PAGE_TABS { - ALERTS = 'alerts', - ACTIVITY = 'activity', -} diff --git a/x-pack/plugins/cases/public/components/case_view/use_on_update_field.ts b/x-pack/plugins/cases/public/components/case_view/use_on_update_field.ts index 9180244b9cf45..449eb7b2ca8a9 100644 --- a/x-pack/plugins/cases/public/components/case_view/use_on_update_field.ts +++ b/x-pack/plugins/cases/public/components/case_view/use_on_update_field.ts @@ -8,13 +8,13 @@ import { useCallback } from 'react'; import deepEqual from 'fast-deep-equal'; -import { CaseConnector } from '../../../common/api'; -import { CaseAttributes } from '../../../common/api/cases/case'; -import { CaseStatuses } from '../../../common/api/cases/status'; -import { Case, UpdateByKey, UpdateKey } from '../../containers/types'; +import type { CaseConnector } from '../../../common/api'; +import type { CaseAttributes } from '../../../common/api/cases/case'; +import type { CaseStatuses } from '../../../common/api/cases/status'; +import type { Case, UpdateByKey, UpdateKey } from '../../containers/types'; import { useUpdateCase } from '../../containers/use_update_case'; import { getTypedPayload } from '../../containers/utils'; -import { OnUpdateFields } from './types'; +import type { OnUpdateFields } from './types'; export const useOnUpdateField = ({ caseData, caseId }: { caseData: Case; caseId: string }) => { const { isLoading, updateKey: loadingKey, updateCaseProperty } = useUpdateCase(); diff --git a/x-pack/plugins/cases/public/components/cases_context/cases_context_reducer.ts b/x-pack/plugins/cases/public/components/cases_context/cases_context_reducer.ts index 53af5d75f2dbe..1ab468e246bdd 100644 --- a/x-pack/plugins/cases/public/components/cases_context/cases_context_reducer.ts +++ b/x-pack/plugins/cases/public/components/cases_context/cases_context_reducer.ts @@ -6,8 +6,8 @@ */ import { assertNever } from '@kbn/std'; -import { AllCasesSelectorModalProps } from '../all_cases/selector_modal'; -import { CreateCaseFlyoutProps } from '../create/flyout'; +import type { AllCasesSelectorModalProps } from '../all_cases/selector_modal'; +import type { CreateCaseFlyoutProps } from '../create/flyout'; export const getInitialCasesContextState = (): CasesContextState => { return { diff --git a/x-pack/plugins/cases/public/components/cases_context/cases_global_components.test.tsx b/x-pack/plugins/cases/public/components/cases_context/cases_global_components.test.tsx index 0f7efd67dc63c..40793010c789f 100644 --- a/x-pack/plugins/cases/public/components/cases_context/cases_global_components.test.tsx +++ b/x-pack/plugins/cases/public/components/cases_context/cases_global_components.test.tsx @@ -8,7 +8,8 @@ import React from 'react'; import { getAllCasesSelectorModalNoProviderLazy } from '../../client/ui/get_all_cases_selector_modal'; import { getCreateCaseFlyoutLazyNoProvider } from '../../client/ui/get_create_case_flyout'; -import { AppMockRenderer, createAppMockRenderer } from '../../common/mock'; +import type { AppMockRenderer } from '../../common/mock'; +import { createAppMockRenderer } from '../../common/mock'; import { getInitialCasesContextState } from './cases_context_reducer'; import { CasesGlobalComponents } from './cases_global_components'; diff --git a/x-pack/plugins/cases/public/components/cases_context/cases_global_components.tsx b/x-pack/plugins/cases/public/components/cases_context/cases_global_components.tsx index 09b0c0d5658eb..2add2322b1f0b 100644 --- a/x-pack/plugins/cases/public/components/cases_context/cases_global_components.tsx +++ b/x-pack/plugins/cases/public/components/cases_context/cases_global_components.tsx @@ -8,7 +8,7 @@ import React from 'react'; import { getAllCasesSelectorModalNoProviderLazy } from '../../client/ui/get_all_cases_selector_modal'; import { getCreateCaseFlyoutLazyNoProvider } from '../../client/ui/get_create_case_flyout'; -import { CasesContextState } from './cases_context_reducer'; +import type { CasesContextState } from './cases_context_reducer'; export const CasesGlobalComponents = React.memo(({ state }: { state: CasesContextState }) => { return ( diff --git a/x-pack/plugins/cases/public/components/cases_context/index.tsx b/x-pack/plugins/cases/public/components/cases_context/index.tsx index 627dec248b371..4e31fffdd7701 100644 --- a/x-pack/plugins/cases/public/components/cases_context/index.tsx +++ b/x-pack/plugins/cases/public/components/cases_context/index.tsx @@ -5,22 +5,24 @@ * 2.0. */ -import React, { useState, useEffect, useReducer, Dispatch } from 'react'; +import type { Dispatch } from 'react'; +import React, { useState, useEffect, useReducer } from 'react'; import { merge } from 'lodash'; import useDeepCompareEffect from 'react-use/lib/useDeepCompareEffect'; import { DEFAULT_FEATURES } from '../../../common/constants'; import { DEFAULT_BASE_PATH } from '../../common/navigation'; import { useApplication } from './use_application'; -import { - CasesContextStoreAction, - casesContextReducer, - getInitialCasesContextState, -} from './cases_context_reducer'; -import { CasesFeaturesAllRequired, CasesFeatures, CasesPermissions } from '../../containers/types'; +import type { CasesContextStoreAction } from './cases_context_reducer'; +import { casesContextReducer, getInitialCasesContextState } from './cases_context_reducer'; +import type { + CasesFeaturesAllRequired, + CasesFeatures, + CasesPermissions, +} from '../../containers/types'; import { CasesGlobalComponents } from './cases_global_components'; -import { ReleasePhase } from '../types'; -import { ExternalReferenceAttachmentTypeRegistry } from '../../client/attachment_framework/external_reference_registry'; -import { PersistableStateAttachmentTypeRegistry } from '../../client/attachment_framework/persistable_state_registry'; +import type { ReleasePhase } from '../types'; +import type { ExternalReferenceAttachmentTypeRegistry } from '../../client/attachment_framework/external_reference_registry'; +import type { PersistableStateAttachmentTypeRegistry } from '../../client/attachment_framework/persistable_state_registry'; export type CasesContextValueDispatch = Dispatch; diff --git a/x-pack/plugins/cases/public/components/configure_cases/__mock__/index.tsx b/x-pack/plugins/cases/public/components/configure_cases/__mock__/index.tsx index cc76bdfcd2f7d..5ffdf69e47a41 100644 --- a/x-pack/plugins/cases/public/components/configure_cases/__mock__/index.tsx +++ b/x-pack/plugins/cases/public/components/configure_cases/__mock__/index.tsx @@ -5,9 +5,10 @@ * 2.0. */ -import { ActionTypeConnector, ConnectorTypes } from '../../../../common/api'; -import { ActionConnector } from '../../../containers/configure/types'; -import { ReturnUseCaseConfigure } from '../../../containers/configure/use_configure'; +import type { ActionTypeConnector } from '../../../../common/api'; +import { ConnectorTypes } from '../../../../common/api'; +import type { ActionConnector } from '../../../containers/configure/types'; +import type { ReturnUseCaseConfigure } from '../../../containers/configure/use_configure'; import { connectorsMock, actionTypesMock } from '../../../common/mock/connectors'; export { mappings } from '../../../containers/configure/mock'; diff --git a/x-pack/plugins/cases/public/components/configure_cases/closure_options.test.tsx b/x-pack/plugins/cases/public/components/configure_cases/closure_options.test.tsx index 56123a934d51f..0202651b6f2bf 100644 --- a/x-pack/plugins/cases/public/components/configure_cases/closure_options.test.tsx +++ b/x-pack/plugins/cases/public/components/configure_cases/closure_options.test.tsx @@ -6,9 +6,11 @@ */ import React from 'react'; -import { mount, ReactWrapper } from 'enzyme'; +import type { ReactWrapper } from 'enzyme'; +import { mount } from 'enzyme'; -import { ClosureOptions, ClosureOptionsProps } from './closure_options'; +import type { ClosureOptionsProps } from './closure_options'; +import { ClosureOptions } from './closure_options'; import { TestProviders } from '../../common/mock'; import { ClosureOptionsRadio } from './closure_options_radio'; diff --git a/x-pack/plugins/cases/public/components/configure_cases/closure_options.tsx b/x-pack/plugins/cases/public/components/configure_cases/closure_options.tsx index 1681f2cf94497..9073988783889 100644 --- a/x-pack/plugins/cases/public/components/configure_cases/closure_options.tsx +++ b/x-pack/plugins/cases/public/components/configure_cases/closure_options.tsx @@ -8,7 +8,7 @@ import React from 'react'; import { EuiDescribedFormGroup, EuiFormRow } from '@elastic/eui'; -import { ClosureType } from '../../containers/configure/types'; +import type { ClosureType } from '../../containers/configure/types'; import { ClosureOptionsRadio } from './closure_options_radio'; import * as i18n from './translations'; diff --git a/x-pack/plugins/cases/public/components/configure_cases/closure_options_radio.test.tsx b/x-pack/plugins/cases/public/components/configure_cases/closure_options_radio.test.tsx index b9885b4e07d48..7fb66f2e1eb14 100644 --- a/x-pack/plugins/cases/public/components/configure_cases/closure_options_radio.test.tsx +++ b/x-pack/plugins/cases/public/components/configure_cases/closure_options_radio.test.tsx @@ -6,9 +6,11 @@ */ import React from 'react'; -import { ReactWrapper, mount } from 'enzyme'; +import type { ReactWrapper } from 'enzyme'; +import { mount } from 'enzyme'; -import { ClosureOptionsRadio, ClosureOptionsRadioComponentProps } from './closure_options_radio'; +import type { ClosureOptionsRadioComponentProps } from './closure_options_radio'; +import { ClosureOptionsRadio } from './closure_options_radio'; import { TestProviders } from '../../common/mock'; describe('ClosureOptionsRadio', () => { diff --git a/x-pack/plugins/cases/public/components/configure_cases/closure_options_radio.tsx b/x-pack/plugins/cases/public/components/configure_cases/closure_options_radio.tsx index 88ee18db805ff..50009ec69fc13 100644 --- a/x-pack/plugins/cases/public/components/configure_cases/closure_options_radio.tsx +++ b/x-pack/plugins/cases/public/components/configure_cases/closure_options_radio.tsx @@ -5,10 +5,11 @@ * 2.0. */ -import React, { ReactNode, useCallback } from 'react'; +import type { ReactNode } from 'react'; +import React, { useCallback } from 'react'; import { EuiRadioGroup } from '@elastic/eui'; -import { ClosureType } from '../../containers/configure/types'; +import type { ClosureType } from '../../containers/configure/types'; import * as i18n from './translations'; interface ClosureRadios { diff --git a/x-pack/plugins/cases/public/components/configure_cases/connectors.test.tsx b/x-pack/plugins/cases/public/components/configure_cases/connectors.test.tsx index 955e114561ce8..2057d0153be68 100644 --- a/x-pack/plugins/cases/public/components/configure_cases/connectors.test.tsx +++ b/x-pack/plugins/cases/public/components/configure_cases/connectors.test.tsx @@ -6,11 +6,14 @@ */ import React from 'react'; -import { mount, ReactWrapper } from 'enzyme'; +import type { ReactWrapper } from 'enzyme'; +import { mount } from 'enzyme'; import { render, screen } from '@testing-library/react'; -import { Connectors, Props } from './connectors'; -import { AppMockRenderer, createAppMockRenderer, TestProviders } from '../../common/mock'; +import type { Props } from './connectors'; +import { Connectors } from './connectors'; +import type { AppMockRenderer } from '../../common/mock'; +import { createAppMockRenderer, TestProviders } from '../../common/mock'; import { ConnectorsDropdown } from './connectors_dropdown'; import { connectors, actionTypes } from './__mock__'; import { ConnectorTypes } from '../../../common/api'; diff --git a/x-pack/plugins/cases/public/components/configure_cases/connectors.tsx b/x-pack/plugins/cases/public/components/configure_cases/connectors.tsx index f0772195fc522..935b65c066055 100644 --- a/x-pack/plugins/cases/public/components/configure_cases/connectors.tsx +++ b/x-pack/plugins/cases/public/components/configure_cases/connectors.tsx @@ -20,9 +20,10 @@ import styled from 'styled-components'; import { ConnectorsDropdown } from './connectors_dropdown'; import * as i18n from './translations'; -import { ActionConnector, CaseConnectorMapping } from '../../containers/configure/types'; +import type { ActionConnector, CaseConnectorMapping } from '../../containers/configure/types'; import { Mapping } from './mapping'; -import { ActionTypeConnector, ConnectorTypes } from '../../../common/api'; +import type { ActionTypeConnector } from '../../../common/api'; +import { ConnectorTypes } from '../../../common/api'; import { DeprecatedCallout } from '../connectors/deprecated_callout'; import { isDeprecatedConnector } from '../utils'; import { useApplicationCapabilities } from '../../common/lib/kibana'; diff --git a/x-pack/plugins/cases/public/components/configure_cases/connectors_dropdown.test.tsx b/x-pack/plugins/cases/public/components/configure_cases/connectors_dropdown.test.tsx index e8093325c1e09..3f3bdedff3e3c 100644 --- a/x-pack/plugins/cases/public/components/configure_cases/connectors_dropdown.test.tsx +++ b/x-pack/plugins/cases/public/components/configure_cases/connectors_dropdown.test.tsx @@ -6,11 +6,13 @@ */ import React from 'react'; -import { mount, ReactWrapper } from 'enzyme'; +import type { ReactWrapper } from 'enzyme'; +import { mount } from 'enzyme'; import { EuiSuperSelect } from '@elastic/eui'; import { render, screen } from '@testing-library/react'; -import { ConnectorsDropdown, Props } from './connectors_dropdown'; +import type { Props } from './connectors_dropdown'; +import { ConnectorsDropdown } from './connectors_dropdown'; import { TestProviders } from '../../common/mock'; import { connectors } from './__mock__'; diff --git a/x-pack/plugins/cases/public/components/configure_cases/connectors_dropdown.tsx b/x-pack/plugins/cases/public/components/configure_cases/connectors_dropdown.tsx index a5fe9f655ef44..2eaad4c722493 100644 --- a/x-pack/plugins/cases/public/components/configure_cases/connectors_dropdown.tsx +++ b/x-pack/plugins/cases/public/components/configure_cases/connectors_dropdown.tsx @@ -10,7 +10,7 @@ import { EuiFlexGroup, EuiFlexItem, EuiIcon, EuiIconTip, EuiSuperSelect } from ' import styled from 'styled-components'; import { euiStyled } from '@kbn/kibana-react-plugin/common'; -import { ActionConnector } from '../../containers/configure/types'; +import type { ActionConnector } from '../../containers/configure/types'; import * as i18n from './translations'; import { useKibana } from '../../common/lib/kibana'; import { getConnectorIcon, isDeprecatedConnector } from '../utils'; diff --git a/x-pack/plugins/cases/public/components/configure_cases/field_mapping.test.tsx b/x-pack/plugins/cases/public/components/configure_cases/field_mapping.test.tsx index 8d235f31277fe..d96c83387c76e 100644 --- a/x-pack/plugins/cases/public/components/configure_cases/field_mapping.test.tsx +++ b/x-pack/plugins/cases/public/components/configure_cases/field_mapping.test.tsx @@ -6,9 +6,11 @@ */ import React from 'react'; -import { mount, ReactWrapper } from 'enzyme'; +import type { ReactWrapper } from 'enzyme'; +import { mount } from 'enzyme'; -import { FieldMapping, FieldMappingProps } from './field_mapping'; +import type { FieldMappingProps } from './field_mapping'; +import { FieldMapping } from './field_mapping'; import { mappings } from './__mock__'; import { TestProviders } from '../../common/mock'; import { FieldMappingRowStatic } from './field_mapping_row_static'; diff --git a/x-pack/plugins/cases/public/components/configure_cases/field_mapping.tsx b/x-pack/plugins/cases/public/components/configure_cases/field_mapping.tsx index 7c52184968013..9356ceae9b742 100644 --- a/x-pack/plugins/cases/public/components/configure_cases/field_mapping.tsx +++ b/x-pack/plugins/cases/public/components/configure_cases/field_mapping.tsx @@ -12,7 +12,7 @@ import styled from 'styled-components'; import { FieldMappingRowStatic } from './field_mapping_row_static'; import * as i18n from './translations'; -import { CaseConnectorMapping } from '../../containers/configure/types'; +import type { CaseConnectorMapping } from '../../containers/configure/types'; const FieldRowWrapper = styled.div` margin: 10px 0; diff --git a/x-pack/plugins/cases/public/components/configure_cases/field_mapping_row_static.tsx b/x-pack/plugins/cases/public/components/configure_cases/field_mapping_row_static.tsx index d7949362e4a1b..84fea6aebc498 100644 --- a/x-pack/plugins/cases/public/components/configure_cases/field_mapping_row_static.tsx +++ b/x-pack/plugins/cases/public/components/configure_cases/field_mapping_row_static.tsx @@ -9,7 +9,7 @@ import React, { useMemo } from 'react'; import { EuiCode, EuiFlexItem, EuiFlexGroup, EuiIcon, EuiLoadingSpinner } from '@elastic/eui'; import { capitalize } from 'lodash/fp'; -import { CaseField, ActionType, ThirdPartyField } from '../../containers/configure/types'; +import type { CaseField, ActionType, ThirdPartyField } from '../../containers/configure/types'; export interface RowProps { isLoading: boolean; diff --git a/x-pack/plugins/cases/public/components/configure_cases/index.test.tsx b/x-pack/plugins/cases/public/components/configure_cases/index.test.tsx index f25b3b8f64b66..2699557bb51f1 100644 --- a/x-pack/plugins/cases/public/components/configure_cases/index.test.tsx +++ b/x-pack/plugins/cases/public/components/configure_cases/index.test.tsx @@ -6,7 +6,8 @@ */ import React from 'react'; -import { ReactWrapper, mount } from 'enzyme'; +import type { ReactWrapper } from 'enzyme'; +import { mount } from 'enzyme'; import { waitFor } from '@testing-library/react'; import { ConfigureCases } from '.'; diff --git a/x-pack/plugins/cases/public/components/configure_cases/index.tsx b/x-pack/plugins/cases/public/components/configure_cases/index.tsx index edffb7e192214..ec9b8a8c7a2fb 100644 --- a/x-pack/plugins/cases/public/components/configure_cases/index.tsx +++ b/x-pack/plugins/cases/public/components/configure_cases/index.tsx @@ -11,13 +11,13 @@ import styled, { css } from 'styled-components'; import { FormattedMessage } from '@kbn/i18n-react'; import { EuiCallOut, EuiLink } from '@elastic/eui'; -import { ActionConnectorTableItem } from '@kbn/triggers-actions-ui-plugin/public/types'; +import type { ActionConnectorTableItem } from '@kbn/triggers-actions-ui-plugin/public/types'; import { CasesConnectorFeatureId } from '@kbn/actions-plugin/common'; import { useKibana } from '../../common/lib/kibana'; import { useGetActionTypes } from '../../containers/configure/use_action_types'; import { useCaseConfigure } from '../../containers/configure/use_configure'; -import { ClosureType } from '../../containers/configure/types'; +import type { ClosureType } from '../../containers/configure/types'; import { SectionWrapper, ContentWrapper, WhitePageWrapper } from '../wrappers'; import { Connectors } from './connectors'; diff --git a/x-pack/plugins/cases/public/components/configure_cases/mapping.test.tsx b/x-pack/plugins/cases/public/components/configure_cases/mapping.test.tsx index 22ebc5412dcc5..b97602beda906 100644 --- a/x-pack/plugins/cases/public/components/configure_cases/mapping.test.tsx +++ b/x-pack/plugins/cases/public/components/configure_cases/mapping.test.tsx @@ -9,7 +9,8 @@ import React from 'react'; import { mount } from 'enzyme'; import { TestProviders } from '../../common/mock'; -import { Mapping, MappingProps } from './mapping'; +import type { MappingProps } from './mapping'; +import { Mapping } from './mapping'; import { mappings } from './__mock__'; import { ConnectorTypes } from '../../../common/api'; diff --git a/x-pack/plugins/cases/public/components/configure_cases/mapping.tsx b/x-pack/plugins/cases/public/components/configure_cases/mapping.tsx index 1f7736041d561..0338e33a5f3c9 100644 --- a/x-pack/plugins/cases/public/components/configure_cases/mapping.tsx +++ b/x-pack/plugins/cases/public/components/configure_cases/mapping.tsx @@ -9,12 +9,12 @@ import React, { useMemo } from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiText, EuiTextColor } from '@elastic/eui'; -import { TextColor } from '@elastic/eui/src/components/text/text_color'; +import type { TextColor } from '@elastic/eui/src/components/text/text_color'; import { ConnectorTypes } from '../../../common/api'; import * as i18n from './translations'; import { FieldMapping } from './field_mapping'; -import { CaseConnectorMapping } from '../../containers/configure/types'; +import type { CaseConnectorMapping } from '../../containers/configure/types'; export interface MappingProps { actionTypeName: string; diff --git a/x-pack/plugins/cases/public/components/configure_cases/utils.test.tsx b/x-pack/plugins/cases/public/components/configure_cases/utils.test.tsx index 45bb7f1f5136d..21cc238e2131f 100644 --- a/x-pack/plugins/cases/public/components/configure_cases/utils.test.tsx +++ b/x-pack/plugins/cases/public/components/configure_cases/utils.test.tsx @@ -7,7 +7,7 @@ import { mappings } from './__mock__'; import { setActionTypeToMapping, setThirdPartyToMapping } from './utils'; -import { CaseConnectorMapping } from '../../containers/configure/types'; +import type { CaseConnectorMapping } from '../../containers/configure/types'; describe('FieldMappingRow', () => { test('it should change the action type', () => { diff --git a/x-pack/plugins/cases/public/components/configure_cases/utils.ts b/x-pack/plugins/cases/public/components/configure_cases/utils.ts index d7de06e9c5aee..a4dfc0442c6d9 100644 --- a/x-pack/plugins/cases/public/components/configure_cases/utils.ts +++ b/x-pack/plugins/cases/public/components/configure_cases/utils.ts @@ -5,15 +5,16 @@ * 2.0. */ -import { ConnectorTypeFields, ConnectorTypes } from '../../../common/api'; -import { +import type { ConnectorTypeFields } from '../../../common/api'; +import { ConnectorTypes } from '../../../common/api'; +import type { CaseField, ActionType, ThirdPartyField, CaseConnector, CaseConnectorMapping, } from '../../containers/configure/types'; -import { CaseActionConnector } from '../types'; +import type { CaseActionConnector } from '../types'; export const setActionTypeToMapping = ( caseField: CaseField, 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 44e5179f1e02e..139d8c48692a0 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,7 +7,8 @@ import React from 'react'; import { mount } from 'enzyme'; -import { UseField, Form, useForm, FormHook } from '../../common/shared_imports'; +import type { FormHook } from '../../common/shared_imports'; +import { UseField, Form, useForm } from '../../common/shared_imports'; 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 c863d4862f31a..6f9f416e69037 100644 --- a/x-pack/plugins/cases/public/components/connector_selector/form.tsx +++ b/x-pack/plugins/cases/public/components/connector_selector/form.tsx @@ -10,9 +10,10 @@ import { isEmpty } from 'lodash/fp'; import { EuiFormRow } from '@elastic/eui'; import styled from 'styled-components'; -import { FieldHook, getFieldValidityAndErrorMessage } from '../../common/shared_imports'; +import type { FieldHook } from '../../common/shared_imports'; +import { getFieldValidityAndErrorMessage } from '../../common/shared_imports'; import { ConnectorsDropdown } from '../configure_cases/connectors_dropdown'; -import { ActionConnector } from '../../../common/api'; +import type { ActionConnector } from '../../../common/api'; interface ConnectorSelectorProps { connectors: ActionConnector[]; diff --git a/x-pack/plugins/cases/public/components/connectors/card.tsx b/x-pack/plugins/cases/public/components/connectors/card.tsx index d6ef92572e506..c4cd24787b01c 100644 --- a/x-pack/plugins/cases/public/components/connectors/card.tsx +++ b/x-pack/plugins/cases/public/components/connectors/card.tsx @@ -9,7 +9,7 @@ import React, { memo, useMemo } from 'react'; import { EuiCard, EuiFlexGroup, EuiFlexItem, EuiIcon, EuiLoadingSpinner } from '@elastic/eui'; import styled from 'styled-components'; -import { ConnectorTypes } from '../../../common/api'; +import type { ConnectorTypes } from '../../../common/api'; import { useKibana } from '../../common/lib/kibana'; import { getConnectorIcon } from '../utils'; diff --git a/x-pack/plugins/cases/public/components/connectors/cases_webhook/case_fields.tsx b/x-pack/plugins/cases/public/components/connectors/cases_webhook/case_fields.tsx index f0410839517f2..e3c912652ba74 100644 --- a/x-pack/plugins/cases/public/components/connectors/cases_webhook/case_fields.tsx +++ b/x-pack/plugins/cases/public/components/connectors/cases_webhook/case_fields.tsx @@ -9,7 +9,7 @@ import React from 'react'; import { EuiCallOut, EuiSpacer } from '@elastic/eui'; import { ConnectorTypes } from '../../../../common/api'; -import { ConnectorFieldsProps } from '../types'; +import type { ConnectorFieldsProps } from '../types'; import { ConnectorCard } from '../card'; import * as i18n from './translations'; diff --git a/x-pack/plugins/cases/public/components/connectors/cases_webhook/index.ts b/x-pack/plugins/cases/public/components/connectors/cases_webhook/index.ts index e884ef3684171..a94076c0949ce 100644 --- a/x-pack/plugins/cases/public/components/connectors/cases_webhook/index.ts +++ b/x-pack/plugins/cases/public/components/connectors/cases_webhook/index.ts @@ -7,7 +7,7 @@ import { lazy } from 'react'; -import { CaseConnector } from '../types'; +import type { CaseConnector } from '../types'; import { ConnectorTypes } from '../../../../common/api'; export const getCaseConnector = (): CaseConnector => { diff --git a/x-pack/plugins/cases/public/components/connectors/connectors_registry.ts b/x-pack/plugins/cases/public/components/connectors/connectors_registry.ts index 8174733301348..92f1d76e4096c 100644 --- a/x-pack/plugins/cases/public/components/connectors/connectors_registry.ts +++ b/x-pack/plugins/cases/public/components/connectors/connectors_registry.ts @@ -6,7 +6,7 @@ */ import { i18n } from '@kbn/i18n'; -import { CaseConnector, CaseConnectorsRegistry } from './types'; +import type { CaseConnector, CaseConnectorsRegistry } from './types'; export const createCaseConnectorsRegistry = (): CaseConnectorsRegistry => { // eslint-disable-next-line @typescript-eslint/no-explicit-any diff --git a/x-pack/plugins/cases/public/components/connectors/deprecated_callout.tsx b/x-pack/plugins/cases/public/components/connectors/deprecated_callout.tsx index 60ae867fab8b4..504a00ec5e5b9 100644 --- a/x-pack/plugins/cases/public/components/connectors/deprecated_callout.tsx +++ b/x-pack/plugins/cases/public/components/connectors/deprecated_callout.tsx @@ -6,7 +6,8 @@ */ import React from 'react'; -import { EuiCallOut, EuiCallOutProps } from '@elastic/eui'; +import type { EuiCallOutProps } from '@elastic/eui'; +import { EuiCallOut } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; const DEPRECATED_CONNECTOR_WARNING_TITLE = i18n.translate( diff --git a/x-pack/plugins/cases/public/components/connectors/fields_form.tsx b/x-pack/plugins/cases/public/components/connectors/fields_form.tsx index 60eb20fe861da..228ddbc952d6b 100644 --- a/x-pack/plugins/cases/public/components/connectors/fields_form.tsx +++ b/x-pack/plugins/cases/public/components/connectors/fields_form.tsx @@ -8,10 +8,10 @@ import React, { memo, Suspense } from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiLoadingSpinner } from '@elastic/eui'; -import { CaseActionConnector } from '../types'; -import { ConnectorFieldsProps } from './types'; +import type { CaseActionConnector } from '../types'; +import type { ConnectorFieldsProps } from './types'; import { getCaseConnectors } from '.'; -import { ConnectorTypeFields } from '../../../common/api'; +import type { ConnectorTypeFields } from '../../../common/api'; interface Props extends Omit, 'connector'> { connector: CaseActionConnector | null; diff --git a/x-pack/plugins/cases/public/components/connectors/index.ts b/x-pack/plugins/cases/public/components/connectors/index.ts index f70773c4864d2..9e23f6d16f677 100644 --- a/x-pack/plugins/cases/public/components/connectors/index.ts +++ b/x-pack/plugins/cases/public/components/connectors/index.ts @@ -5,14 +5,14 @@ * 2.0. */ -import { CaseConnectorsRegistry } from './types'; +import type { CaseConnectorsRegistry } from './types'; import { createCaseConnectorsRegistry } from './connectors_registry'; import { getCaseConnector as getJiraCaseConnector } from './jira'; import { getCaseConnector as getSwimlaneCaseConnector } from './swimlane'; import { getCaseConnector as getResilientCaseConnector } from './resilient'; import { getCaseConnector as getCasesWebhookCaseConnector } from './cases_webhook'; import { getServiceNowITSMCaseConnector, getServiceNowSIRCaseConnector } from './servicenow'; -import { +import type { JiraFieldsType, ServiceNowITSMFieldsType, ServiceNowSIRFieldsType, diff --git a/x-pack/plugins/cases/public/components/connectors/jira/__mocks__/api.ts b/x-pack/plugins/cases/public/components/connectors/jira/__mocks__/api.ts index 3a7b51545dfca..402299482611d 100644 --- a/x-pack/plugins/cases/public/components/connectors/jira/__mocks__/api.ts +++ b/x-pack/plugins/cases/public/components/connectors/jira/__mocks__/api.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { GetIssueTypesProps, GetFieldsByIssueTypeProps, GetIssueTypeProps } from '../api'; -import { IssueTypes, Fields, Issues, Issue } from '../types'; +import type { GetIssueTypesProps, GetFieldsByIssueTypeProps, GetIssueTypeProps } from '../api'; +import type { IssueTypes, Fields, Issues, Issue } from '../types'; import { issues } from '../../mock'; const issueTypes = [ diff --git a/x-pack/plugins/cases/public/components/connectors/jira/api.ts b/x-pack/plugins/cases/public/components/connectors/jira/api.ts index 286d44c5916d4..d1b37dee612f9 100644 --- a/x-pack/plugins/cases/public/components/connectors/jira/api.ts +++ b/x-pack/plugins/cases/public/components/connectors/jira/api.ts @@ -5,14 +5,12 @@ * 2.0. */ -import { HttpSetup } from '@kbn/core/public'; -import { ActionTypeExecutorResult } from '@kbn/actions-plugin/common'; +import type { HttpSetup } from '@kbn/core/public'; +import type { ActionTypeExecutorResult } from '@kbn/actions-plugin/common'; import { getExecuteConnectorUrl } from '../../../../common/utils'; -import { - ConnectorExecutorResult, - rewriteResponseToCamelCase, -} from '../rewrite_response_to_camel_case'; -import { IssueTypes, Fields, Issues, Issue } from './types'; +import type { ConnectorExecutorResult } from '../rewrite_response_to_camel_case'; +import { rewriteResponseToCamelCase } from '../rewrite_response_to_camel_case'; +import type { IssueTypes, Fields, Issues, Issue } from './types'; export interface GetIssueTypesProps { http: HttpSetup; diff --git a/x-pack/plugins/cases/public/components/connectors/jira/case_fields.test.tsx b/x-pack/plugins/cases/public/components/connectors/jira/case_fields.test.tsx index 591dbf15d35a8..ed600e58245b8 100644 --- a/x-pack/plugins/cases/public/components/connectors/jira/case_fields.test.tsx +++ b/x-pack/plugins/cases/public/components/connectors/jira/case_fields.test.tsx @@ -17,7 +17,8 @@ import Fields from './case_fields'; import { waitFor } from '@testing-library/dom'; import { useGetSingleIssue } from './use_get_single_issue'; import { useGetIssues } from './use_get_issues'; -import { EuiComboBox, EuiComboBoxOptionOption } from '@elastic/eui'; +import type { EuiComboBoxOptionOption } from '@elastic/eui'; +import { EuiComboBox } from '@elastic/eui'; jest.mock('./use_get_issue_types'); jest.mock('./use_get_fields_by_issue_type'); diff --git a/x-pack/plugins/cases/public/components/connectors/jira/case_fields.tsx b/x-pack/plugins/cases/public/components/connectors/jira/case_fields.tsx index 1fe02a8483ed3..d3ba99370ee47 100644 --- a/x-pack/plugins/cases/public/components/connectors/jira/case_fields.tsx +++ b/x-pack/plugins/cases/public/components/connectors/jira/case_fields.tsx @@ -10,9 +10,10 @@ import { map } from 'lodash/fp'; import { EuiFormRow, EuiSelect, EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui'; import * as i18n from './translations'; -import { ConnectorTypes, JiraFieldsType } from '../../../../common/api'; +import type { JiraFieldsType } from '../../../../common/api'; +import { ConnectorTypes } from '../../../../common/api'; import { useKibana } from '../../../common/lib/kibana'; -import { ConnectorFieldsProps } from '../types'; +import type { ConnectorFieldsProps } from '../types'; import { useGetIssueTypes } from './use_get_issue_types'; import { useGetFieldsByIssueType } from './use_get_fields_by_issue_type'; import { SearchIssues } from './search_issues'; diff --git a/x-pack/plugins/cases/public/components/connectors/jira/index.ts b/x-pack/plugins/cases/public/components/connectors/jira/index.ts index afb53ffcb87cf..aeafd760d966c 100644 --- a/x-pack/plugins/cases/public/components/connectors/jira/index.ts +++ b/x-pack/plugins/cases/public/components/connectors/jira/index.ts @@ -7,8 +7,9 @@ import { lazy } from 'react'; -import { CaseConnector } from '../types'; -import { ConnectorTypes, JiraFieldsType } from '../../../../common/api'; +import type { CaseConnector } from '../types'; +import type { JiraFieldsType } from '../../../../common/api'; +import { ConnectorTypes } from '../../../../common/api'; import * as i18n from './translations'; export * from './types'; diff --git a/x-pack/plugins/cases/public/components/connectors/jira/search_issues.tsx b/x-pack/plugins/cases/public/components/connectors/jira/search_issues.tsx index 53c25db0a72b6..952c39fdc9876 100644 --- a/x-pack/plugins/cases/public/components/connectors/jira/search_issues.tsx +++ b/x-pack/plugins/cases/public/components/connectors/jira/search_issues.tsx @@ -6,10 +6,11 @@ */ import React, { useMemo, useEffect, useCallback, useState, memo } from 'react'; -import { EuiComboBox, EuiComboBoxOptionOption } from '@elastic/eui'; +import type { EuiComboBoxOptionOption } from '@elastic/eui'; +import { EuiComboBox } from '@elastic/eui'; import { useKibana } from '../../../common/lib/kibana'; -import { ActionConnector } from '../../../../common/api'; +import type { ActionConnector } from '../../../../common/api'; import { useGetIssues } from './use_get_issues'; import { useGetSingleIssue } from './use_get_single_issue'; import * as i18n from './translations'; diff --git a/x-pack/plugins/cases/public/components/connectors/jira/use_get_fields_by_issue_type.test.tsx b/x-pack/plugins/cases/public/components/connectors/jira/use_get_fields_by_issue_type.test.tsx index b4c2c848d79ed..8dd64701fc0d4 100644 --- a/x-pack/plugins/cases/public/components/connectors/jira/use_get_fields_by_issue_type.test.tsx +++ b/x-pack/plugins/cases/public/components/connectors/jira/use_get_fields_by_issue_type.test.tsx @@ -9,7 +9,8 @@ import { renderHook, act } from '@testing-library/react-hooks'; import { useKibana } from '../../../common/lib/kibana'; import { connector } from '../mock'; -import { useGetFieldsByIssueType, UseGetFieldsByIssueType } from './use_get_fields_by_issue_type'; +import type { UseGetFieldsByIssueType } from './use_get_fields_by_issue_type'; +import { useGetFieldsByIssueType } from './use_get_fields_by_issue_type'; import * as api from './api'; jest.mock('../../../common/lib/kibana'); diff --git a/x-pack/plugins/cases/public/components/connectors/jira/use_get_fields_by_issue_type.tsx b/x-pack/plugins/cases/public/components/connectors/jira/use_get_fields_by_issue_type.tsx index 955a03c614888..c80c305982794 100644 --- a/x-pack/plugins/cases/public/components/connectors/jira/use_get_fields_by_issue_type.tsx +++ b/x-pack/plugins/cases/public/components/connectors/jira/use_get_fields_by_issue_type.tsx @@ -6,10 +6,10 @@ */ import { useState, useEffect, useRef } from 'react'; -import { HttpSetup, IToasts } from '@kbn/core/public'; -import { ActionConnector } from '../../../../common/api'; +import type { HttpSetup, IToasts } from '@kbn/core/public'; +import type { ActionConnector } from '../../../../common/api'; import { getFieldsByIssueType } from './api'; -import { Fields } from './types'; +import type { Fields } from './types'; import * as i18n from './translations'; interface Props { diff --git a/x-pack/plugins/cases/public/components/connectors/jira/use_get_issue_types.test.tsx b/x-pack/plugins/cases/public/components/connectors/jira/use_get_issue_types.test.tsx index 6c1a9b5fcab08..7500085f004a7 100644 --- a/x-pack/plugins/cases/public/components/connectors/jira/use_get_issue_types.test.tsx +++ b/x-pack/plugins/cases/public/components/connectors/jira/use_get_issue_types.test.tsx @@ -9,7 +9,8 @@ import { renderHook, act } from '@testing-library/react-hooks'; import { useKibana } from '../../../common/lib/kibana'; import { connector } from '../mock'; -import { useGetIssueTypes, UseGetIssueTypes } from './use_get_issue_types'; +import type { UseGetIssueTypes } from './use_get_issue_types'; +import { useGetIssueTypes } from './use_get_issue_types'; import * as api from './api'; jest.mock('../../../common/lib/kibana'); diff --git a/x-pack/plugins/cases/public/components/connectors/jira/use_get_issue_types.tsx b/x-pack/plugins/cases/public/components/connectors/jira/use_get_issue_types.tsx index 3be1093eeaccb..0f8b5de8a2ff4 100644 --- a/x-pack/plugins/cases/public/components/connectors/jira/use_get_issue_types.tsx +++ b/x-pack/plugins/cases/public/components/connectors/jira/use_get_issue_types.tsx @@ -6,10 +6,10 @@ */ import { useState, useEffect, useRef } from 'react'; -import { HttpSetup, IToasts } from '@kbn/core/public'; -import { ActionConnector } from '../../../../common/api'; +import type { HttpSetup, IToasts } from '@kbn/core/public'; +import type { ActionConnector } from '../../../../common/api'; import { getIssueTypes } from './api'; -import { IssueTypes } from './types'; +import type { IssueTypes } from './types'; import * as i18n from './translations'; interface Props { diff --git a/x-pack/plugins/cases/public/components/connectors/jira/use_get_issues.test.tsx b/x-pack/plugins/cases/public/components/connectors/jira/use_get_issues.test.tsx index 2308fe604e710..1c7cf140c9fe2 100644 --- a/x-pack/plugins/cases/public/components/connectors/jira/use_get_issues.test.tsx +++ b/x-pack/plugins/cases/public/components/connectors/jira/use_get_issues.test.tsx @@ -9,7 +9,8 @@ import { renderHook, act } from '@testing-library/react-hooks'; import { useKibana } from '../../../common/lib/kibana'; import { connector as actionConnector, issues } from '../mock'; -import { useGetIssues, UseGetIssues } from './use_get_issues'; +import type { UseGetIssues } from './use_get_issues'; +import { useGetIssues } from './use_get_issues'; import * as api from './api'; jest.mock('../../../common/lib/kibana'); diff --git a/x-pack/plugins/cases/public/components/connectors/jira/use_get_issues.tsx b/x-pack/plugins/cases/public/components/connectors/jira/use_get_issues.tsx index 230bf5636d62d..983542b30e54c 100644 --- a/x-pack/plugins/cases/public/components/connectors/jira/use_get_issues.tsx +++ b/x-pack/plugins/cases/public/components/connectors/jira/use_get_issues.tsx @@ -7,10 +7,10 @@ import { isEmpty, debounce } from 'lodash/fp'; import { useState, useEffect, useRef } from 'react'; -import { HttpSetup, ToastsApi } from '@kbn/core/public'; -import { ActionConnector } from '../../../../common/api'; +import type { HttpSetup, ToastsApi } from '@kbn/core/public'; +import type { ActionConnector } from '../../../../common/api'; import { getIssues } from './api'; -import { Issues } from './types'; +import type { Issues } from './types'; import * as i18n from './translations'; interface Props { diff --git a/x-pack/plugins/cases/public/components/connectors/jira/use_get_single_issue.test.tsx b/x-pack/plugins/cases/public/components/connectors/jira/use_get_single_issue.test.tsx index 28949b456ecdd..38c61f05ed083 100644 --- a/x-pack/plugins/cases/public/components/connectors/jira/use_get_single_issue.test.tsx +++ b/x-pack/plugins/cases/public/components/connectors/jira/use_get_single_issue.test.tsx @@ -9,7 +9,8 @@ import { renderHook, act } from '@testing-library/react-hooks'; import { useKibana } from '../../../common/lib/kibana'; import { connector as actionConnector, issues } from '../mock'; -import { useGetSingleIssue, UseGetSingleIssue } from './use_get_single_issue'; +import type { UseGetSingleIssue } from './use_get_single_issue'; +import { useGetSingleIssue } from './use_get_single_issue'; import * as api from './api'; jest.mock('../../../common/lib/kibana'); diff --git a/x-pack/plugins/cases/public/components/connectors/jira/use_get_single_issue.tsx b/x-pack/plugins/cases/public/components/connectors/jira/use_get_single_issue.tsx index aa7bd2ea0d4f6..d330d37d9faed 100644 --- a/x-pack/plugins/cases/public/components/connectors/jira/use_get_single_issue.tsx +++ b/x-pack/plugins/cases/public/components/connectors/jira/use_get_single_issue.tsx @@ -6,10 +6,10 @@ */ import { useState, useEffect, useRef } from 'react'; -import { HttpSetup, ToastsApi } from '@kbn/core/public'; -import { ActionConnector } from '../../../../common/api'; +import type { HttpSetup, ToastsApi } from '@kbn/core/public'; +import type { ActionConnector } from '../../../../common/api'; import { getIssue } from './api'; -import { Issue } from './types'; +import type { Issue } from './types'; import * as i18n from './translations'; interface Props { diff --git a/x-pack/plugins/cases/public/components/connectors/resilient/__mocks__/api.ts b/x-pack/plugins/cases/public/components/connectors/resilient/__mocks__/api.ts index 350cf7ec47974..c3a91714852e6 100644 --- a/x-pack/plugins/cases/public/components/connectors/resilient/__mocks__/api.ts +++ b/x-pack/plugins/cases/public/components/connectors/resilient/__mocks__/api.ts @@ -6,8 +6,8 @@ */ import { incidentTypes, severity } from '../../mock'; -import { Props } from '../api'; -import { ResilientIncidentTypes, ResilientSeverity } from '../types'; +import type { Props } from '../api'; +import type { ResilientIncidentTypes, ResilientSeverity } from '../types'; export const getIncidentTypes = async (props: Props): Promise<{ data: ResilientIncidentTypes }> => Promise.resolve({ data: incidentTypes, actionId: '1' }); diff --git a/x-pack/plugins/cases/public/components/connectors/resilient/api.ts b/x-pack/plugins/cases/public/components/connectors/resilient/api.ts index 2afb2d5d35f22..987a23c771f96 100644 --- a/x-pack/plugins/cases/public/components/connectors/resilient/api.ts +++ b/x-pack/plugins/cases/public/components/connectors/resilient/api.ts @@ -5,13 +5,11 @@ * 2.0. */ -import { HttpSetup } from '@kbn/core/public'; +import type { HttpSetup } from '@kbn/core/public'; import { getExecuteConnectorUrl } from '../../../../common/utils/connectors_api'; -import { - ConnectorExecutorResult, - rewriteResponseToCamelCase, -} from '../rewrite_response_to_camel_case'; -import { ResilientIncidentTypes, ResilientSeverity } from './types'; +import type { ConnectorExecutorResult } from '../rewrite_response_to_camel_case'; +import { rewriteResponseToCamelCase } from '../rewrite_response_to_camel_case'; +import type { ResilientIncidentTypes, ResilientSeverity } from './types'; export const BASE_ACTION_API_PATH = '/api/actions'; diff --git a/x-pack/plugins/cases/public/components/connectors/resilient/case_fields.test.tsx b/x-pack/plugins/cases/public/components/connectors/resilient/case_fields.test.tsx index 814c73537b1f4..6717e7cc9189a 100644 --- a/x-pack/plugins/cases/public/components/connectors/resilient/case_fields.test.tsx +++ b/x-pack/plugins/cases/public/components/connectors/resilient/case_fields.test.tsx @@ -7,7 +7,8 @@ import React from 'react'; import { mount } from 'enzyme'; -import { EuiComboBox, EuiComboBoxOptionOption } from '@elastic/eui'; +import type { EuiComboBoxOptionOption } from '@elastic/eui'; +import { EuiComboBox } from '@elastic/eui'; import { waitFor } from '@testing-library/react'; import { connector } from '../mock'; diff --git a/x-pack/plugins/cases/public/components/connectors/resilient/case_fields.tsx b/x-pack/plugins/cases/public/components/connectors/resilient/case_fields.tsx index c6e7615f944b0..d9e15e193490a 100644 --- a/x-pack/plugins/cases/public/components/connectors/resilient/case_fields.tsx +++ b/x-pack/plugins/cases/public/components/connectors/resilient/case_fields.tsx @@ -6,22 +6,17 @@ */ import React, { useMemo, useCallback, useEffect, useRef } from 'react'; -import { - EuiComboBox, - EuiComboBoxOptionOption, - EuiFormRow, - EuiSelect, - EuiSelectOption, - EuiSpacer, -} from '@elastic/eui'; +import type { EuiComboBoxOptionOption, EuiSelectOption } from '@elastic/eui'; +import { EuiComboBox, EuiFormRow, EuiSelect, EuiSpacer } from '@elastic/eui'; import { useKibana } from '../../../common/lib/kibana'; -import { ConnectorFieldsProps } from '../types'; +import type { ConnectorFieldsProps } from '../types'; import { useGetIncidentTypes } from './use_get_incident_types'; import { useGetSeverity } from './use_get_severity'; import * as i18n from './translations'; -import { ConnectorTypes, ResilientFieldsType } from '../../../../common/api'; +import type { ResilientFieldsType } from '../../../../common/api'; +import { ConnectorTypes } from '../../../../common/api'; import { ConnectorCard } from '../card'; const ResilientFieldsComponent: React.FunctionComponent> = diff --git a/x-pack/plugins/cases/public/components/connectors/resilient/index.ts b/x-pack/plugins/cases/public/components/connectors/resilient/index.ts index 0da7448e62a65..06f4c932b1586 100644 --- a/x-pack/plugins/cases/public/components/connectors/resilient/index.ts +++ b/x-pack/plugins/cases/public/components/connectors/resilient/index.ts @@ -7,8 +7,9 @@ import { lazy } from 'react'; -import { CaseConnector } from '../types'; -import { ConnectorTypes, ResilientFieldsType } from '../../../../common/api'; +import type { CaseConnector } from '../types'; +import type { ResilientFieldsType } from '../../../../common/api'; +import { ConnectorTypes } from '../../../../common/api'; import * as i18n from './translations'; export * from './types'; diff --git a/x-pack/plugins/cases/public/components/connectors/resilient/use_get_incident_types.test.tsx b/x-pack/plugins/cases/public/components/connectors/resilient/use_get_incident_types.test.tsx index 59c1f8e9b40d0..6d90feee5198d 100644 --- a/x-pack/plugins/cases/public/components/connectors/resilient/use_get_incident_types.test.tsx +++ b/x-pack/plugins/cases/public/components/connectors/resilient/use_get_incident_types.test.tsx @@ -9,7 +9,8 @@ import { renderHook, act } from '@testing-library/react-hooks'; import { useKibana } from '../../../common/lib/kibana'; import { connector } from '../mock'; -import { useGetIncidentTypes, UseGetIncidentTypes } from './use_get_incident_types'; +import type { UseGetIncidentTypes } from './use_get_incident_types'; +import { useGetIncidentTypes } from './use_get_incident_types'; import * as api from './api'; jest.mock('../../../common/lib/kibana'); diff --git a/x-pack/plugins/cases/public/components/connectors/resilient/use_get_incident_types.tsx b/x-pack/plugins/cases/public/components/connectors/resilient/use_get_incident_types.tsx index 0f58b8e37cc7c..95eb91327c2fb 100644 --- a/x-pack/plugins/cases/public/components/connectors/resilient/use_get_incident_types.tsx +++ b/x-pack/plugins/cases/public/components/connectors/resilient/use_get_incident_types.tsx @@ -6,8 +6,8 @@ */ import { useState, useEffect, useRef } from 'react'; -import { HttpSetup, ToastsApi } from '@kbn/core/public'; -import { ActionConnector } from '../../../../common/api'; +import type { HttpSetup, ToastsApi } from '@kbn/core/public'; +import type { ActionConnector } from '../../../../common/api'; import { getIncidentTypes } from './api'; import * as i18n from './translations'; diff --git a/x-pack/plugins/cases/public/components/connectors/resilient/use_get_severity.test.tsx b/x-pack/plugins/cases/public/components/connectors/resilient/use_get_severity.test.tsx index f646dd7e8f7c2..1bbbae56531f2 100644 --- a/x-pack/plugins/cases/public/components/connectors/resilient/use_get_severity.test.tsx +++ b/x-pack/plugins/cases/public/components/connectors/resilient/use_get_severity.test.tsx @@ -9,7 +9,8 @@ import { renderHook, act } from '@testing-library/react-hooks'; import { useKibana } from '../../../common/lib/kibana'; import { connector } from '../mock'; -import { useGetSeverity, UseGetSeverity } from './use_get_severity'; +import type { UseGetSeverity } from './use_get_severity'; +import { useGetSeverity } from './use_get_severity'; import * as api from './api'; jest.mock('../../../common/lib/kibana'); diff --git a/x-pack/plugins/cases/public/components/connectors/resilient/use_get_severity.tsx b/x-pack/plugins/cases/public/components/connectors/resilient/use_get_severity.tsx index fa3b63ea4c7d0..0c1fafc0aeca2 100644 --- a/x-pack/plugins/cases/public/components/connectors/resilient/use_get_severity.tsx +++ b/x-pack/plugins/cases/public/components/connectors/resilient/use_get_severity.tsx @@ -6,8 +6,8 @@ */ import { useState, useEffect, useRef } from 'react'; -import { HttpSetup, ToastsApi } from '@kbn/core/public'; -import { ActionConnector } from '../../../../common/api'; +import type { HttpSetup, ToastsApi } from '@kbn/core/public'; +import type { ActionConnector } from '../../../../common/api'; import { getSeverity } from './api'; import * as i18n from './translations'; diff --git a/x-pack/plugins/cases/public/components/connectors/rewrite_response_to_camel_case.test.ts b/x-pack/plugins/cases/public/components/connectors/rewrite_response_to_camel_case.test.ts index 28f901076759b..7807651afe6ab 100644 --- a/x-pack/plugins/cases/public/components/connectors/rewrite_response_to_camel_case.test.ts +++ b/x-pack/plugins/cases/public/components/connectors/rewrite_response_to_camel_case.test.ts @@ -5,10 +5,8 @@ * 2.0. */ -import { - ConnectorExecutorResult, - rewriteResponseToCamelCase, -} from './rewrite_response_to_camel_case'; +import type { ConnectorExecutorResult } from './rewrite_response_to_camel_case'; +import { rewriteResponseToCamelCase } from './rewrite_response_to_camel_case'; const responseWithSnakeCasedFields: ConnectorExecutorResult<{}> = { service_message: 'oh noooooo', diff --git a/x-pack/plugins/cases/public/components/connectors/rewrite_response_to_camel_case.ts b/x-pack/plugins/cases/public/components/connectors/rewrite_response_to_camel_case.ts index 739250bee0d19..1224b1b476cc8 100644 --- a/x-pack/plugins/cases/public/components/connectors/rewrite_response_to_camel_case.ts +++ b/x-pack/plugins/cases/public/components/connectors/rewrite_response_to_camel_case.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { ActionTypeExecutorResult, RewriteResponseCase } from '@kbn/actions-plugin/common'; +import type { ActionTypeExecutorResult, RewriteResponseCase } from '@kbn/actions-plugin/common'; export type ConnectorExecutorResult = ReturnType< RewriteResponseCase> diff --git a/x-pack/plugins/cases/public/components/connectors/servicenow/__mocks__/api.ts b/x-pack/plugins/cases/public/components/connectors/servicenow/__mocks__/api.ts index 215e3d6f92e6d..49c728b68f40c 100644 --- a/x-pack/plugins/cases/public/components/connectors/servicenow/__mocks__/api.ts +++ b/x-pack/plugins/cases/public/components/connectors/servicenow/__mocks__/api.ts @@ -6,8 +6,8 @@ */ import { choices } from '../../mock'; -import { GetChoicesProps } from '../api'; -import { Choice } from '../types'; +import type { GetChoicesProps } from '../api'; +import type { Choice } from '../types'; export const choicesResponse = { status: 'ok', diff --git a/x-pack/plugins/cases/public/components/connectors/servicenow/api.ts b/x-pack/plugins/cases/public/components/connectors/servicenow/api.ts index 3224c65cc9319..ae91920d848ec 100644 --- a/x-pack/plugins/cases/public/components/connectors/servicenow/api.ts +++ b/x-pack/plugins/cases/public/components/connectors/servicenow/api.ts @@ -5,13 +5,11 @@ * 2.0. */ -import { HttpSetup } from '@kbn/core/public'; +import type { HttpSetup } from '@kbn/core/public'; import { getExecuteConnectorUrl } from '../../../../common/utils/connectors_api'; -import { - ConnectorExecutorResult, - rewriteResponseToCamelCase, -} from '../rewrite_response_to_camel_case'; -import { Choice } from './types'; +import type { ConnectorExecutorResult } from '../rewrite_response_to_camel_case'; +import { rewriteResponseToCamelCase } from '../rewrite_response_to_camel_case'; +import type { Choice } from './types'; export const BASE_ACTION_API_PATH = '/api/actions'; diff --git a/x-pack/plugins/cases/public/components/connectors/servicenow/helpers.ts b/x-pack/plugins/cases/public/components/connectors/servicenow/helpers.ts index 314d224491128..f0cef67e67f64 100644 --- a/x-pack/plugins/cases/public/components/connectors/servicenow/helpers.ts +++ b/x-pack/plugins/cases/public/components/connectors/servicenow/helpers.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { EuiSelectOption } from '@elastic/eui'; -import { Choice } from './types'; +import type { EuiSelectOption } from '@elastic/eui'; +import type { Choice } from './types'; export const choicesToEuiOptions = (choices: Choice[]): EuiSelectOption[] => choices.map((choice) => ({ value: choice.value, text: choice.label })); diff --git a/x-pack/plugins/cases/public/components/connectors/servicenow/index.ts b/x-pack/plugins/cases/public/components/connectors/servicenow/index.ts index 1c466d08e9bcb..92817307219ce 100644 --- a/x-pack/plugins/cases/public/components/connectors/servicenow/index.ts +++ b/x-pack/plugins/cases/public/components/connectors/servicenow/index.ts @@ -7,12 +7,9 @@ import { lazy } from 'react'; -import { CaseConnector } from '../types'; -import { - ConnectorTypes, - ServiceNowITSMFieldsType, - ServiceNowSIRFieldsType, -} from '../../../../common/api'; +import type { CaseConnector } from '../types'; +import type { ServiceNowITSMFieldsType, ServiceNowSIRFieldsType } from '../../../../common/api'; +import { ConnectorTypes } from '../../../../common/api'; import * as i18n from './translations'; export const getServiceNowITSMCaseConnector = (): CaseConnector => ({ diff --git a/x-pack/plugins/cases/public/components/connectors/servicenow/servicenow_itsm_case_fields.test.tsx b/x-pack/plugins/cases/public/components/connectors/servicenow/servicenow_itsm_case_fields.test.tsx index e2f4a683772c7..2589dd2587dd0 100644 --- a/x-pack/plugins/cases/public/components/connectors/servicenow/servicenow_itsm_case_fields.test.tsx +++ b/x-pack/plugins/cases/public/components/connectors/servicenow/servicenow_itsm_case_fields.test.tsx @@ -12,7 +12,7 @@ import { mount } from 'enzyme'; import { useKibana } from '../../../common/lib/kibana'; import { connector, choices as mockChoices } from '../mock'; -import { Choice } from './types'; +import type { Choice } from './types'; import Fields from './servicenow_itsm_case_fields'; let onChoicesSuccess = (c: Choice[]) => {}; diff --git a/x-pack/plugins/cases/public/components/connectors/servicenow/servicenow_itsm_case_fields.tsx b/x-pack/plugins/cases/public/components/connectors/servicenow/servicenow_itsm_case_fields.tsx index 2dae544ec274c..502d3c304bcc6 100644 --- a/x-pack/plugins/cases/public/components/connectors/servicenow/servicenow_itsm_case_fields.tsx +++ b/x-pack/plugins/cases/public/components/connectors/servicenow/servicenow_itsm_case_fields.tsx @@ -9,12 +9,13 @@ import React, { useCallback, useEffect, useMemo, useState, useRef } from 'react' import { EuiFormRow, EuiSelect, EuiSpacer, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import * as i18n from './translations'; -import { ConnectorFieldsProps } from '../types'; -import { ConnectorTypes, ServiceNowITSMFieldsType } from '../../../../common/api'; +import type { ConnectorFieldsProps } from '../types'; +import type { ServiceNowITSMFieldsType } from '../../../../common/api'; +import { ConnectorTypes } from '../../../../common/api'; import { useKibana } from '../../../common/lib/kibana'; import { ConnectorCard } from '../card'; import { useGetChoices } from './use_get_choices'; -import { Fields, Choice } from './types'; +import type { Fields, Choice } from './types'; import { choicesToEuiOptions } from './helpers'; import { DeprecatedCallout } from '../deprecated_callout'; diff --git a/x-pack/plugins/cases/public/components/connectors/servicenow/servicenow_sir_case_fields.test.tsx b/x-pack/plugins/cases/public/components/connectors/servicenow/servicenow_sir_case_fields.test.tsx index 1b06e0cfdce81..8b81745adeaa8 100644 --- a/x-pack/plugins/cases/public/components/connectors/servicenow/servicenow_sir_case_fields.test.tsx +++ b/x-pack/plugins/cases/public/components/connectors/servicenow/servicenow_sir_case_fields.test.tsx @@ -6,13 +6,14 @@ */ import React from 'react'; -import { mount, ReactWrapper } from 'enzyme'; +import type { ReactWrapper } from 'enzyme'; +import { mount } from 'enzyme'; import { waitFor, act, render, screen } from '@testing-library/react'; import { EuiSelect } from '@elastic/eui'; import { useKibana } from '../../../common/lib/kibana'; import { connector, choices as mockChoices } from '../mock'; -import { Choice } from './types'; +import type { Choice } from './types'; import Fields from './servicenow_sir_case_fields'; let onChoicesSuccess = (_c: Choice[]) => {}; diff --git a/x-pack/plugins/cases/public/components/connectors/servicenow/servicenow_sir_case_fields.tsx b/x-pack/plugins/cases/public/components/connectors/servicenow/servicenow_sir_case_fields.tsx index 78f17a1d4215a..b1b3678149baf 100644 --- a/x-pack/plugins/cases/public/components/connectors/servicenow/servicenow_sir_case_fields.tsx +++ b/x-pack/plugins/cases/public/components/connectors/servicenow/servicenow_sir_case_fields.tsx @@ -8,12 +8,13 @@ import React, { useCallback, useEffect, useMemo, useState, useRef } from 'react'; import { EuiFormRow, EuiSelect, EuiFlexGroup, EuiFlexItem, EuiCheckbox } from '@elastic/eui'; -import { ConnectorTypes, ServiceNowSIRFieldsType } from '../../../../common/api'; +import type { ServiceNowSIRFieldsType } from '../../../../common/api'; +import { ConnectorTypes } from '../../../../common/api'; import { useKibana } from '../../../common/lib/kibana'; -import { ConnectorFieldsProps } from '../types'; +import type { ConnectorFieldsProps } from '../types'; import { ConnectorCard } from '../card'; import { useGetChoices } from './use_get_choices'; -import { Choice, Fields } from './types'; +import type { Choice, Fields } from './types'; import { choicesToEuiOptions } from './helpers'; import * as i18n from './translations'; diff --git a/x-pack/plugins/cases/public/components/connectors/servicenow/use_get_choices.test.tsx b/x-pack/plugins/cases/public/components/connectors/servicenow/use_get_choices.test.tsx index 9a4e19d126bba..e44e1d8013dfa 100644 --- a/x-pack/plugins/cases/public/components/connectors/servicenow/use_get_choices.test.tsx +++ b/x-pack/plugins/cases/public/components/connectors/servicenow/use_get_choices.test.tsx @@ -8,9 +8,10 @@ import { renderHook } from '@testing-library/react-hooks'; import { useKibana } from '../../../common/lib/kibana'; -import { ActionConnector } from '../../../../common/api'; +import type { ActionConnector } from '../../../../common/api'; import { choices } from '../mock'; -import { useGetChoices, UseGetChoices, UseGetChoicesProps } from './use_get_choices'; +import type { UseGetChoices, UseGetChoicesProps } from './use_get_choices'; +import { useGetChoices } from './use_get_choices'; import * as api from './api'; jest.mock('./api'); diff --git a/x-pack/plugins/cases/public/components/connectors/servicenow/use_get_choices.tsx b/x-pack/plugins/cases/public/components/connectors/servicenow/use_get_choices.tsx index 19452cb3ac3ae..63bcbc4cdab1a 100644 --- a/x-pack/plugins/cases/public/components/connectors/servicenow/use_get_choices.tsx +++ b/x-pack/plugins/cases/public/components/connectors/servicenow/use_get_choices.tsx @@ -6,10 +6,10 @@ */ import { useState, useEffect, useRef } from 'react'; -import { HttpSetup, IToasts } from '@kbn/core/public'; -import { ActionConnector } from '../../../../common/api'; +import type { HttpSetup, IToasts } from '@kbn/core/public'; +import type { ActionConnector } from '../../../../common/api'; import { getChoices } from './api'; -import { Choice } from './types'; +import type { Choice } from './types'; import * as i18n from './translations'; export interface UseGetChoicesProps { diff --git a/x-pack/plugins/cases/public/components/connectors/swimlane/case_fields.tsx b/x-pack/plugins/cases/public/components/connectors/swimlane/case_fields.tsx index 3ca1d6b3ec674..0993dfcad5d48 100644 --- a/x-pack/plugins/cases/public/components/connectors/swimlane/case_fields.tsx +++ b/x-pack/plugins/cases/public/components/connectors/swimlane/case_fields.tsx @@ -9,8 +9,9 @@ import React, { useMemo } from 'react'; import { EuiCallOut } from '@elastic/eui'; import * as i18n from './translations'; -import { ConnectorTypes, SwimlaneFieldsType } from '../../../../common/api'; -import { ConnectorFieldsProps } from '../types'; +import type { SwimlaneFieldsType } from '../../../../common/api'; +import { ConnectorTypes } from '../../../../common/api'; +import type { ConnectorFieldsProps } from '../types'; import { ConnectorCard } from '../card'; import { connectorValidator } from './validator'; diff --git a/x-pack/plugins/cases/public/components/connectors/swimlane/index.ts b/x-pack/plugins/cases/public/components/connectors/swimlane/index.ts index 394b93b961004..ee69e739f0fb7 100644 --- a/x-pack/plugins/cases/public/components/connectors/swimlane/index.ts +++ b/x-pack/plugins/cases/public/components/connectors/swimlane/index.ts @@ -7,8 +7,9 @@ import { lazy } from 'react'; -import { CaseConnector } from '../types'; -import { ConnectorTypes, SwimlaneFieldsType } from '../../../../common/api'; +import type { CaseConnector } from '../types'; +import type { SwimlaneFieldsType } from '../../../../common/api'; +import { ConnectorTypes } from '../../../../common/api'; import * as i18n from './translations'; export const getCaseConnector = (): CaseConnector => { 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 d3c94d0150bbe..8480350841b0e 100644 --- a/x-pack/plugins/cases/public/components/connectors/swimlane/validator.ts +++ b/x-pack/plugins/cases/public/components/connectors/swimlane/validator.ts @@ -6,8 +6,8 @@ */ import { SwimlaneConnectorType } from '../../../../common/api'; -import { ValidationConfig } from '../../../common/shared_imports'; -import { CaseActionConnector } from '../../types'; +import type { ValidationConfig } from '../../../common/shared_imports'; +import type { CaseActionConnector } from '../../types'; const casesRequiredFields = [ 'caseIdConfig', diff --git a/x-pack/plugins/cases/public/components/connectors/types.ts b/x-pack/plugins/cases/public/components/connectors/types.ts index 66e5d519ac752..93e2ee92d83a6 100644 --- a/x-pack/plugins/cases/public/components/connectors/types.ts +++ b/x-pack/plugins/cases/public/components/connectors/types.ts @@ -5,15 +5,15 @@ * 2.0. */ -import { IconType } from '@elastic/eui'; -import React from 'react'; +import type { IconType } from '@elastic/eui'; +import type React from 'react'; -import { +import type { ActionType as ThirdPartySupportedActions, CaseField, ConnectorTypeFields, } from '../../../common/api'; -import { CaseActionConnector } from '../types'; +import type { CaseActionConnector } from '../types'; export type { ThirdPartyField as AllThirdPartyFields } from '../../../common/api'; 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 1970ef9739fde..97ee74ad76831 100644 --- a/x-pack/plugins/cases/public/components/create/assignees.test.tsx +++ b/x-pack/plugins/cases/public/components/create/assignees.test.tsx @@ -7,15 +7,17 @@ import React from 'react'; import userEvent from '@testing-library/user-event'; -import { AppMockRenderer, createAppMockRenderer } from '../../common/mock'; +import type { AppMockRenderer } from '../../common/mock'; +import { createAppMockRenderer } from '../../common/mock'; -import { useForm, Form, FormHook } from '../../common/shared_imports'; +import type { FormHook } from '../../common/shared_imports'; +import { useForm, Form } from '../../common/shared_imports'; import { userProfiles } from '../../containers/user_profiles/api.mock'; import { Assignees } from './assignees'; -import { FormProps } from './schema'; +import type { FormProps } from './schema'; import { act, waitFor, screen } from '@testing-library/react'; import * as api from '../../containers/user_profiles/api'; -import { UserProfile } from '@kbn/user-profile-components'; +import type { UserProfile } from '@kbn/user-profile-components'; jest.mock('../../containers/user_profiles/api'); diff --git a/x-pack/plugins/cases/public/components/create/assignees.tsx b/x-pack/plugins/cases/public/components/create/assignees.tsx index c434b578cf9dd..1b5577bd87469 100644 --- a/x-pack/plugins/cases/public/components/create/assignees.tsx +++ b/x-pack/plugins/cases/public/components/create/assignees.tsx @@ -7,28 +7,20 @@ import { isEmpty } from 'lodash'; import React, { memo, useCallback, useState } from 'react'; +import type { EuiComboBoxOptionOption } from '@elastic/eui'; import { EuiComboBox, - EuiComboBoxOptionOption, EuiFormRow, EuiLink, EuiSelectableListItem, EuiTextColor, } from '@elastic/eui'; -import { - UserProfileWithAvatar, - UserAvatar, - getUserDisplayName, - UserProfile, -} from '@kbn/user-profile-components'; +import type { UserProfileWithAvatar, UserProfile } from '@kbn/user-profile-components'; +import { UserAvatar, getUserDisplayName } from '@kbn/user-profile-components'; import { MAX_ASSIGNEES_PER_CASE } from '../../../common/constants'; -import { CaseAssignees } from '../../../common/api'; -import { - UseField, - FieldConfig, - FieldHook, - getFieldValidityAndErrorMessage, -} from '../../common/shared_imports'; +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 7a2a4b366c7a1..1fc99cf30ab75 100644 --- a/x-pack/plugins/cases/public/components/create/connector.test.tsx +++ b/x-pack/plugins/cases/public/components/create/connector.test.tsx @@ -8,17 +8,21 @@ import React from 'react'; import { mount } from 'enzyme'; import { act, waitFor } from '@testing-library/react'; -import { EuiComboBox, EuiComboBoxOptionOption } from '@elastic/eui'; +import type { EuiComboBoxOptionOption } from '@elastic/eui'; +import { EuiComboBox } from '@elastic/eui'; -import { useForm, Form, FormHook } from '../../common/shared_imports'; +import type { FormHook } from '../../common/shared_imports'; +import { useForm, Form } from '../../common/shared_imports'; import { connectorsMock } from '../../containers/mock'; import { Connector } from './connector'; import { useGetIncidentTypes } from '../connectors/resilient/use_get_incident_types'; import { useGetSeverity } from '../connectors/resilient/use_get_severity'; import { useGetChoices } from '../connectors/servicenow/use_get_choices'; import { incidentTypes, severity, choices } from '../connectors/mock'; -import { schema, FormProps } from './schema'; -import { AppMockRenderer, createAppMockRenderer, TestProviders } from '../../common/mock'; +import type { FormProps } from './schema'; +import { schema } from './schema'; +import type { AppMockRenderer } from '../../common/mock'; +import { createAppMockRenderer, TestProviders } from '../../common/mock'; import { useCaseConfigure } from '../../containers/configure/use_configure'; import { useCaseConfigureResponse } from '../configure_cases/__mock__'; diff --git a/x-pack/plugins/cases/public/components/create/connector.tsx b/x-pack/plugins/cases/public/components/create/connector.tsx index ca196f06908b1..102b8ec73d1b0 100644 --- a/x-pack/plugins/cases/public/components/create/connector.tsx +++ b/x-pack/plugins/cases/public/components/create/connector.tsx @@ -8,17 +8,13 @@ import React, { memo, useCallback, useMemo, useEffect } from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui'; -import { ActionConnector } from '../../../common/api'; -import { - UseField, - useFormData, - FieldHook, - useFormContext, - FieldConfig, -} from '../../common/shared_imports'; +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 { FormProps, schema } from './schema'; +import type { FormProps } from './schema'; +import { schema } from './schema'; import { useCaseConfigure } from '../../containers/configure/use_configure'; import { getConnectorById, getConnectorsFormValidators } from '../utils'; import { useApplicationCapabilities } from '../../common/lib/kibana'; 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 1fe13b17e7337..d95fade009f3d 100644 --- a/x-pack/plugins/cases/public/components/create/description.test.tsx +++ b/x-pack/plugins/cases/public/components/create/description.test.tsx @@ -9,10 +9,13 @@ import React from 'react'; import { waitFor } from '@testing-library/react'; import userEvent, { specialChars } from '@testing-library/user-event'; -import { useForm, Form, FormHook } from '../../common/shared_imports'; +import type { FormHook } from '../../common/shared_imports'; +import { useForm, Form } from '../../common/shared_imports'; import { Description } from './description'; -import { schema, FormProps } from './schema'; -import { createAppMockRenderer, AppMockRenderer } from '../../common/mock'; +import type { FormProps } from './schema'; +import { schema } from './schema'; +import type { AppMockRenderer } from '../../common/mock'; +import { createAppMockRenderer } from '../../common/mock'; jest.mock('../markdown_editor/plugins/lens/use_lens_draft_comment'); diff --git a/x-pack/plugins/cases/public/components/create/flyout/create_case_flyout.test.tsx b/x-pack/plugins/cases/public/components/create/flyout/create_case_flyout.test.tsx index 325fffb460ee0..df2ba80901738 100644 --- a/x-pack/plugins/cases/public/components/create/flyout/create_case_flyout.test.tsx +++ b/x-pack/plugins/cases/public/components/create/flyout/create_case_flyout.test.tsx @@ -10,7 +10,8 @@ import { act } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { CreateCaseFlyout } from './create_case_flyout'; -import { AppMockRenderer, createAppMockRenderer } from '../../../common/mock'; +import type { AppMockRenderer } from '../../../common/mock'; +import { createAppMockRenderer } from '../../../common/mock'; jest.mock('../../../common/lib/kibana'); diff --git a/x-pack/plugins/cases/public/components/create/flyout/create_case_flyout.tsx b/x-pack/plugins/cases/public/components/create/flyout/create_case_flyout.tsx index c7bcb9b0828c6..75a18f2e70209 100644 --- a/x-pack/plugins/cases/public/components/create/flyout/create_case_flyout.tsx +++ b/x-pack/plugins/cases/public/components/create/flyout/create_case_flyout.tsx @@ -11,10 +11,10 @@ import { EuiFlyout, EuiFlyoutHeader, EuiTitle, EuiFlyoutBody } from '@elastic/eu import { QueryClientProvider } from '@tanstack/react-query'; import * as i18n from '../translations'; -import { Case } from '../../../../common/ui/types'; +import type { Case } from '../../../../common/ui/types'; import { CreateCaseForm } from '../form'; -import { UseCreateAttachments } from '../../../containers/use_create_attachments'; -import { CaseAttachmentsWithoutOwner } from '../../../types'; +import type { UseCreateAttachments } from '../../../containers/use_create_attachments'; +import type { CaseAttachmentsWithoutOwner } from '../../../types'; import { casesQueryClient } from '../../cases_context/query_client'; export interface CreateCaseFlyoutProps { diff --git a/x-pack/plugins/cases/public/components/create/flyout/index.tsx b/x-pack/plugins/cases/public/components/create/flyout/index.tsx index 5b8aef47d1544..9a1097b18863e 100644 --- a/x-pack/plugins/cases/public/components/create/flyout/index.tsx +++ b/x-pack/plugins/cases/public/components/create/flyout/index.tsx @@ -4,7 +4,8 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { CreateCaseFlyout, CreateCaseFlyoutProps } from './create_case_flyout'; +import type { CreateCaseFlyoutProps } from './create_case_flyout'; +import { CreateCaseFlyout } from './create_case_flyout'; export type { CreateCaseFlyoutProps }; export { CreateCaseFlyout }; diff --git a/x-pack/plugins/cases/public/components/create/flyout/use_cases_add_to_new_case_flyout.tsx b/x-pack/plugins/cases/public/components/create/flyout/use_cases_add_to_new_case_flyout.tsx index 8b2d2b02cce79..86b03f46bf745 100644 --- a/x-pack/plugins/cases/public/components/create/flyout/use_cases_add_to_new_case_flyout.tsx +++ b/x-pack/plugins/cases/public/components/create/flyout/use_cases_add_to_new_case_flyout.tsx @@ -6,12 +6,12 @@ */ import { useCallback } from 'react'; -import { CaseAttachmentsWithoutOwner } from '../../../types'; +import type { CaseAttachmentsWithoutOwner } from '../../../types'; import { useCasesToast } from '../../../common/use_cases_toast'; -import { Case } from '../../../containers/types'; +import type { Case } from '../../../containers/types'; import { CasesContextStoreActionsList } from '../../cases_context/cases_context_reducer'; import { useCasesContext } from '../../cases_context/use_cases_context'; -import { CreateCaseFlyoutProps } from './create_case_flyout'; +import type { CreateCaseFlyoutProps } from './create_case_flyout'; type AddToNewCaseFlyoutProps = Omit & { toastTitle?: string; 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 7459e7b45fed2..3316134f7762e 100644 --- a/x-pack/plugins/cases/public/components/create/form.test.tsx +++ b/x-pack/plugins/cases/public/components/create/form.test.tsx @@ -11,10 +11,13 @@ import { act, render } from '@testing-library/react'; import { licensingMock } from '@kbn/licensing-plugin/public/mocks'; import { NONE_CONNECTOR_ID } from '../../../common/api'; -import { useForm, Form, FormHook } from '../../common/shared_imports'; +import type { FormHook } from '../../common/shared_imports'; +import { useForm, Form } from '../../common/shared_imports'; import { connectorsMock } from '../../containers/mock'; -import { schema, FormProps } from './schema'; -import { CreateCaseForm, CreateCaseFormProps } from './form'; +import type { FormProps } from './schema'; +import { schema } from './schema'; +import type { CreateCaseFormProps } from './form'; +import { CreateCaseForm } from './form'; import { useCaseConfigure } from '../../containers/configure/use_configure'; import { useCaseConfigureResponse } from '../configure_cases/__mock__'; import { TestProviders } from '../../common/mock'; diff --git a/x-pack/plugins/cases/public/components/create/form.tsx b/x-pack/plugins/cases/public/components/create/form.tsx index 854261b005e5e..32fff2048685d 100644 --- a/x-pack/plugins/cases/public/components/create/form.tsx +++ b/x-pack/plugins/cases/public/components/create/form.tsx @@ -23,18 +23,19 @@ import { Tags } from './tags'; import { Connector } from './connector'; import * as i18n from './translations'; import { SyncAlertsToggle } from './sync_alerts_toggle'; -import { ActionConnector } from '../../../common/api'; -import { Case } from '../../containers/types'; -import { CasesTimelineIntegration, CasesTimelineIntegrationProvider } from '../timeline_context'; +import type { ActionConnector } from '../../../common/api'; +import type { Case } from '../../containers/types'; +import type { CasesTimelineIntegration } from '../timeline_context'; +import { CasesTimelineIntegrationProvider } from '../timeline_context'; import { InsertTimeline } from '../insert_timeline'; -import { UseCreateAttachments } from '../../containers/use_create_attachments'; +import type { UseCreateAttachments } from '../../containers/use_create_attachments'; import { SubmitCaseButton } from './submit_button'; import { FormContext } from './form_context'; import { useCasesFeatures } from '../../common/use_cases_features'; import { CreateCaseOwnerSelector } from './owner_selector'; import { useCasesContext } from '../cases_context/use_cases_context'; import { useAvailableCasesOwners } from '../app/use_available_owners'; -import { CaseAttachmentsWithoutOwner } from '../../types'; +import type { CaseAttachmentsWithoutOwner } from '../../types'; import { Severity } from './severity'; import { Assignees } from './assignees'; diff --git a/x-pack/plugins/cases/public/components/create/form_context.test.tsx b/x-pack/plugins/cases/public/components/create/form_context.test.tsx index 26b14510b481b..6ac37abddb514 100644 --- a/x-pack/plugins/cases/public/components/create/form_context.test.tsx +++ b/x-pack/plugins/cases/public/components/create/form_context.test.tsx @@ -6,12 +6,14 @@ */ import React from 'react'; -import { act, RenderResult, waitFor, within } from '@testing-library/react'; +import type { RenderResult } from '@testing-library/react'; +import { act, waitFor, within } from '@testing-library/react'; import { waitForEuiPopoverOpen } from '@elastic/eui/lib/test/rtl'; import { CaseSeverity, CommentType, ConnectorTypes } from '../../../common/api'; import { useKibana } from '../../common/lib/kibana'; -import { AppMockRenderer, createAppMockRenderer } from '../../common/mock'; +import type { AppMockRenderer } from '../../common/mock'; +import { createAppMockRenderer } from '../../common/mock'; import { usePostCase } from '../../containers/use_post_case'; import { useCreateAttachments } from '../../containers/use_create_attachments'; import { useCaseConfigure } from '../../containers/configure/use_configure'; @@ -32,13 +34,14 @@ import { useGetChoicesResponse, } from './mock'; import { FormContext } from './form_context'; -import { CreateCaseFormFields, CreateCaseFormFieldsProps } from './form'; +import type { CreateCaseFormFieldsProps } from './form'; +import { CreateCaseFormFields } from './form'; import { SubmitCaseButton } from './submit_button'; import { usePostPushToService } from '../../containers/use_post_push_to_service'; -import { Choice } from '../connectors/servicenow/types'; +import type { Choice } from '../connectors/servicenow/types'; import userEvent from '@testing-library/user-event'; import { connectorsMock } from '../../common/mock/connectors'; -import { CaseAttachments } from '../../types'; +import type { CaseAttachments } from '../../types'; import { useGetConnectors } from '../../containers/configure/use_connectors'; import { useGetTags } from '../../containers/use_get_tags'; import { waitForComponentToUpdate } from '../../common/test_utils'; @@ -118,7 +121,8 @@ const fillFormReactTestingLib = async (renderResult: RenderResult) => { } }; -describe('Create case', () => { +// FLAKY: https://github.com/elastic/kibana/issues/142283 +describe.skip('Create case', () => { const refetch = jest.fn(); const onFormSubmitSuccess = jest.fn(); const afterCaseCreated = jest.fn(); 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 01dbb7fbf40d0..1e6cfaafe4eeb 100644 --- a/x-pack/plugins/cases/public/components/create/form_context.tsx +++ b/x-pack/plugins/cases/public/components/create/form_context.tsx @@ -6,22 +6,21 @@ */ import React, { useCallback, useMemo } from 'react'; -import { schema, FormProps } from './schema'; +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'; -import { Case } from '../../containers/types'; +import type { Case } from '../../containers/types'; import { CaseSeverity, NONE_CONNECTOR_ID } from '../../../common/api'; -import { - UseCreateAttachments, - useCreateAttachments, -} from '../../containers/use_create_attachments'; +import type { UseCreateAttachments } from '../../containers/use_create_attachments'; +import { useCreateAttachments } from '../../containers/use_create_attachments'; import { useCasesContext } from '../cases_context/use_cases_context'; import { useCasesFeatures } from '../../common/use_cases_features'; import { getConnectorById } from '../utils'; -import { CaseAttachmentsWithoutOwner } from '../../types'; +import type { CaseAttachmentsWithoutOwner } from '../../types'; import { useGetConnectors } from '../../containers/configure/use_connectors'; import { useCreateCaseWithAttachmentsTransaction } from '../../common/apm/use_cases_transactions'; diff --git a/x-pack/plugins/cases/public/components/create/index.test.tsx b/x-pack/plugins/cases/public/components/create/index.test.tsx index 4a2449397bbcc..b5840da22cf45 100644 --- a/x-pack/plugins/cases/public/components/create/index.test.tsx +++ b/x-pack/plugins/cases/public/components/create/index.test.tsx @@ -6,9 +6,11 @@ */ import React from 'react'; -import { mount, ReactWrapper } from 'enzyme'; +import type { ReactWrapper } from 'enzyme'; +import { mount } from 'enzyme'; import { act } from '@testing-library/react'; -import { EuiComboBox, EuiComboBoxOptionOption } from '@elastic/eui'; +import type { EuiComboBoxOptionOption } from '@elastic/eui'; +import { EuiComboBox } from '@elastic/eui'; import { TestProviders } from '../../common/mock'; import { useCaseConfigure } from '../../containers/configure/use_configure'; diff --git a/x-pack/plugins/cases/public/components/create/index.tsx b/x-pack/plugins/cases/public/components/create/index.tsx index eb35f78b87f5f..a1ffd7b3ebd6b 100644 --- a/x-pack/plugins/cases/public/components/create/index.tsx +++ b/x-pack/plugins/cases/public/components/create/index.tsx @@ -9,7 +9,8 @@ import React from 'react'; import { Field, getUseField } from '../../common/shared_imports'; import * as i18n from './translations'; -import { CreateCaseForm, CreateCaseFormProps } from './form'; +import type { CreateCaseFormProps } from './form'; +import { CreateCaseForm } from './form'; import { HeaderPage } from '../header_page'; import { useCasesBreadcrumbs } from '../use_breadcrumbs'; import { CasesDeepLinkId } from '../../common/navigation'; diff --git a/x-pack/plugins/cases/public/components/create/mock.ts b/x-pack/plugins/cases/public/components/create/mock.ts index c54e3206b2b01..ee57410bfb783 100644 --- a/x-pack/plugins/cases/public/components/create/mock.ts +++ b/x-pack/plugins/cases/public/components/create/mock.ts @@ -5,7 +5,8 @@ * 2.0. */ -import { CasePostRequest, CaseSeverity, ConnectorTypes } from '../../../common/api'; +import type { CasePostRequest } from '../../../common/api'; +import { CaseSeverity, ConnectorTypes } from '../../../common/api'; import { SECURITY_SOLUTION_OWNER } from '../../../common/constants'; import { choices } from '../connectors/mock'; 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 11d7f09f785b1..25f0f9ba0faaa 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,9 +11,11 @@ import { act, waitFor } from '@testing-library/react'; import { SECURITY_SOLUTION_OWNER } from '../../../common'; import { OBSERVABILITY_OWNER } from '../../../common/constants'; -import { useForm, Form, FormHook } from '../../common/shared_imports'; +import type { FormHook } from '../../common/shared_imports'; +import { useForm, Form } from '../../common/shared_imports'; import { CreateCaseOwnerSelector } from './owner_selector'; -import { schema, FormProps } from './schema'; +import type { FormProps } from './schema'; +import { schema } from './schema'; import { waitForComponentToPaint } from '../../common/test_utils'; describe('Case Owner Selection', () => { 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 bcc8709ee5c5d..e572e7c9f9ca5 100644 --- a/x-pack/plugins/cases/public/components/create/owner_selector.tsx +++ b/x-pack/plugins/cases/public/components/create/owner_selector.tsx @@ -21,7 +21,8 @@ import { euiStyled } from '@kbn/kibana-react-plugin/common'; import { SECURITY_SOLUTION_OWNER } from '../../../common'; import { OWNER_INFO } from '../../../common/constants'; -import { FieldHook, getFieldValidityAndErrorMessage, UseField } from '../../common/shared_imports'; +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 59cf8f919606b..30dc762143ae3 100644 --- a/x-pack/plugins/cases/public/components/create/schema.tsx +++ b/x-pack/plugins/cases/public/components/create/schema.tsx @@ -5,15 +5,11 @@ * 2.0. */ -import { CasePostRequest, ConnectorTypeFields } from '../../../common/api'; +import type { CasePostRequest, ConnectorTypeFields } from '../../../common/api'; import { isInvalidTag } from '../../../common/utils/validators'; import { MAX_TITLE_LENGTH } from '../../../common/constants'; -import { - FIELD_TYPES, - fieldValidators, - FormSchema, - VALIDATION_TYPES, -} from '../../common/shared_imports'; +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 09a24eb5801e6..5d80028817a83 100644 --- a/x-pack/plugins/cases/public/components/create/severity.test.tsx +++ b/x-pack/plugins/cases/public/components/create/severity.test.tsx @@ -7,10 +7,13 @@ import { CaseSeverity } from '../../../common/api'; import React from 'react'; -import { AppMockRenderer, createAppMockRenderer } from '../../common/mock'; -import { Form, FormHook, useForm } from '../../common/shared_imports'; +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 { Severity } from './severity'; -import { FormProps, schema } from './schema'; +import type { FormProps } from './schema'; +import { schema } from './schema'; import userEvent from '@testing-library/user-event'; import { waitFor } from '@testing-library/dom'; import { waitForEuiPopoverOpen } from '@elastic/eui/lib/test/rtl'; 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 62279500616ee..b703eb703d720 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 @@ -11,7 +11,8 @@ import { waitFor } from '@testing-library/react'; import { useForm, Form } from '../../common/shared_imports'; import { SubmitCaseButton } from './submit_button'; -import { schema, FormProps } from './schema'; +import type { FormProps } from './schema'; +import { schema } from './schema'; describe('SubmitCaseButton', () => { const onSubmit = jest.fn(); 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 b4a37f0abb518..28abe40607c72 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,9 +9,11 @@ import React from 'react'; import { mount } from 'enzyme'; import { waitFor } from '@testing-library/react'; -import { useForm, Form, FormHook } from '../../common/shared_imports'; +import type { FormHook } from '../../common/shared_imports'; +import { useForm, Form } from '../../common/shared_imports'; import { SyncAlertsToggle } from './sync_alerts_toggle'; -import { schema, FormProps } from './schema'; +import type { FormProps } from './schema'; +import { schema } from './schema'; describe('SyncAlertsToggle', () => { let globalForm: FormHook; 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 dde659c2da8ba..9e84955c3a07e 100644 --- a/x-pack/plugins/cases/public/components/create/tags.test.tsx +++ b/x-pack/plugins/cases/public/components/create/tags.test.tsx @@ -7,12 +7,15 @@ import React from 'react'; import { mount } from 'enzyme'; -import { EuiComboBox, EuiComboBoxOptionOption } from '@elastic/eui'; +import type { EuiComboBoxOptionOption } from '@elastic/eui'; +import { EuiComboBox } from '@elastic/eui'; import { waitFor } from '@testing-library/react'; -import { useForm, Form, FormHook } from '../../common/shared_imports'; +import type { FormHook } from '../../common/shared_imports'; +import { useForm, Form } from '../../common/shared_imports'; import { Tags } from './tags'; -import { schema, FormProps } from './schema'; +import type { FormProps } from './schema'; +import { schema } from './schema'; import { TestProviders } from '../../common/mock'; import { useGetTags } from '../../containers/use_get_tags'; 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 a41d5afbb4038..37952ba530842 100644 --- a/x-pack/plugins/cases/public/components/create/title.test.tsx +++ b/x-pack/plugins/cases/public/components/create/title.test.tsx @@ -9,9 +9,11 @@ import React from 'react'; import { mount } from 'enzyme'; import { act } from '@testing-library/react'; -import { useForm, Form, FormHook } from '../../common/shared_imports'; +import type { FormHook } from '../../common/shared_imports'; +import { useForm, Form } from '../../common/shared_imports'; import { Title } from './title'; -import { schema, FormProps } from './schema'; +import type { FormProps } from './schema'; +import { schema } from './schema'; describe('Title', () => { let globalForm: FormHook; diff --git a/x-pack/plugins/cases/public/components/edit_connector/helpers.test.ts b/x-pack/plugins/cases/public/components/edit_connector/helpers.test.ts index 4efd4b995eb83..12503b6d223fc 100644 --- a/x-pack/plugins/cases/public/components/edit_connector/helpers.test.ts +++ b/x-pack/plugins/cases/public/components/edit_connector/helpers.test.ts @@ -5,8 +5,9 @@ * 2.0. */ -import { Actions, ConnectorTypes, ConnectorUserAction } from '../../../common/api'; -import { CaseUserActions } from '../../containers/types'; +import type { ConnectorUserAction } from '../../../common/api'; +import { Actions, ConnectorTypes } from '../../../common/api'; +import type { CaseUserActions } from '../../containers/types'; import { getConnectorFieldsFromUserActions } from './helpers'; const defaultJiraFields = { diff --git a/x-pack/plugins/cases/public/components/edit_connector/helpers.ts b/x-pack/plugins/cases/public/components/edit_connector/helpers.ts index 9f7ecaa95793b..84d6984f35bbc 100644 --- a/x-pack/plugins/cases/public/components/edit_connector/helpers.ts +++ b/x-pack/plugins/cases/public/components/edit_connector/helpers.ts @@ -6,8 +6,8 @@ */ import { isConnectorUserAction, isCreateCaseUserAction } from '../../../common/utils/user_actions'; -import { ConnectorTypeFields } from '../../../common/api'; -import { CaseUserActions } from '../../containers/types'; +import type { ConnectorTypeFields } from '../../../common/api'; +import type { CaseUserActions } from '../../containers/types'; export const getConnectorFieldsFromUserActions = ( id: string, diff --git a/x-pack/plugins/cases/public/components/edit_connector/index.test.tsx b/x-pack/plugins/cases/public/components/edit_connector/index.test.tsx index 5db400203468a..401f43ae9afff 100644 --- a/x-pack/plugins/cases/public/components/edit_connector/index.test.tsx +++ b/x-pack/plugins/cases/public/components/edit_connector/index.test.tsx @@ -11,16 +11,17 @@ import { render, waitFor, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { waitForEuiPopoverOpen } from '@elastic/eui/lib/test/rtl'; -import { EditConnector, EditConnectorProps } from '.'; +import type { EditConnectorProps } from '.'; +import { EditConnector } from '.'; +import type { AppMockRenderer } from '../../common/mock'; import { - AppMockRenderer, createAppMockRenderer, readCasesPermissions, noPushCasesPermissions, TestProviders, } from '../../common/mock'; import { basicCase, basicPush, caseUserActions, connectorsMock } from '../../containers/mock'; -import { CaseConnector } from '../../containers/configure/types'; +import type { CaseConnector } from '../../containers/configure/types'; const onSubmit = jest.fn(); const caseServices = { 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 fe3e980016e4c..7be868fa5d625 100644 --- a/x-pack/plugins/cases/public/components/edit_connector/index.tsx +++ b/x-pack/plugins/cases/public/components/edit_connector/index.tsx @@ -19,18 +19,20 @@ import { import styled from 'styled-components'; import { isEmpty, noop } from 'lodash/fp'; -import { FieldConfig, Form, UseField, useForm } from '../../common/shared_imports'; -import { Case } from '../../../common/ui/types'; -import { ActionConnector, ConnectorTypeFields, NONE_CONNECTOR_ID } from '../../../common/api'; +import type { FieldConfig } from '../../common/shared_imports'; +import { Form, UseField, useForm } from '../../common/shared_imports'; +import type { Case } from '../../../common/ui/types'; +import type { ActionConnector, ConnectorTypeFields } from '../../../common/api'; +import { NONE_CONNECTOR_ID } from '../../../common/api'; import { ConnectorSelector } from '../connector_selector/form'; import { ConnectorFieldsForm } from '../connectors/fields_form'; -import { CaseUserActions } from '../../containers/types'; +import type { CaseUserActions } from '../../containers/types'; import { schema } from './schema'; import { getConnectorFieldsFromUserActions } from './helpers'; import * as i18n from './translations'; import { getConnectorById, getConnectorsFormValidators } from '../utils'; import { usePushToService } from '../use_push_to_service'; -import { CaseServices } from '../../containers/use_get_case_user_actions'; +import type { CaseServices } from '../../containers/use_get_case_user_actions'; import { useApplicationCapabilities } from '../../common/lib/kibana'; import { useCasesContext } from '../cases_context/use_cases_context'; 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 a12511f704be2..0ff191fff5bda 100644 --- a/x-pack/plugins/cases/public/components/edit_connector/schema.tsx +++ b/x-pack/plugins/cases/public/components/edit_connector/schema.tsx @@ -5,7 +5,8 @@ * 2.0. */ -import { FormSchema, FIELD_TYPES } from '../../common/shared_imports'; +import type { FormSchema } from '../../common/shared_imports'; +import { FIELD_TYPES } from '../../common/shared_imports'; export interface FormProps { connectorId: string; diff --git a/x-pack/plugins/cases/public/components/header_page/editable_title.test.tsx b/x-pack/plugins/cases/public/components/header_page/editable_title.test.tsx index e2893cbbc5aa8..51d42c3d1d3b0 100644 --- a/x-pack/plugins/cases/public/components/header_page/editable_title.test.tsx +++ b/x-pack/plugins/cases/public/components/header_page/editable_title.test.tsx @@ -8,13 +8,10 @@ import React from 'react'; import '../../common/mock/match_media'; -import { - AppMockRenderer, - createAppMockRenderer, - readCasesPermissions, - TestProviders, -} from '../../common/mock'; -import { EditableTitle, EditableTitleProps } from './editable_title'; +import type { AppMockRenderer } from '../../common/mock'; +import { createAppMockRenderer, readCasesPermissions, TestProviders } from '../../common/mock'; +import type { EditableTitleProps } from './editable_title'; +import { EditableTitle } from './editable_title'; import { useMountAppended } from '../../utils/use_mount_appended'; describe('EditableTitle', () => { diff --git a/x-pack/plugins/cases/public/components/header_page/editable_title.tsx b/x-pack/plugins/cases/public/components/header_page/editable_title.tsx index 7e0dd2f5fd1fc..287cbb23134d8 100644 --- a/x-pack/plugins/cases/public/components/header_page/editable_title.tsx +++ b/x-pack/plugins/cases/public/components/header_page/editable_title.tsx @@ -5,7 +5,8 @@ * 2.0. */ -import React, { useState, useCallback, ChangeEvent } from 'react'; +import type { ChangeEvent } from 'react'; +import React, { useState, useCallback } from 'react'; import styled, { css } from 'styled-components'; import { diff --git a/x-pack/plugins/cases/public/components/header_page/index.test.tsx b/x-pack/plugins/cases/public/components/header_page/index.test.tsx index c5c7ddcaab875..19301bb5eebc4 100644 --- a/x-pack/plugins/cases/public/components/header_page/index.test.tsx +++ b/x-pack/plugins/cases/public/components/header_page/index.test.tsx @@ -9,7 +9,8 @@ import { euiDarkVars } from '@kbn/ui-theme'; import React from 'react'; import '../../common/mock/match_media'; -import { AppMockRenderer, createAppMockRenderer, TestProviders } from '../../common/mock'; +import type { AppMockRenderer } from '../../common/mock'; +import { createAppMockRenderer, TestProviders } from '../../common/mock'; import { HeaderPage } from '.'; import { useMountAppended } from '../../utils/use_mount_appended'; diff --git a/x-pack/plugins/cases/public/components/header_page/index.tsx b/x-pack/plugins/cases/public/components/header_page/index.tsx index 6bec4035ca823..5d47bc2d62847 100644 --- a/x-pack/plugins/cases/public/components/header_page/index.tsx +++ b/x-pack/plugins/cases/public/components/header_page/index.tsx @@ -11,7 +11,8 @@ import styled, { css } from 'styled-components'; import { useAllCasesNavigation } from '../../common/navigation'; import { LinkIcon } from '../link_icon'; -import { Subtitle, SubtitleProps } from '../subtitle'; +import type { SubtitleProps } from '../subtitle'; +import { Subtitle } from '../subtitle'; import { Title } from './title'; import * as i18n from './translations'; import { useCasesContext } from '../cases_context/use_cases_context'; diff --git a/x-pack/plugins/cases/public/components/header_page/title.tsx b/x-pack/plugins/cases/public/components/header_page/title.tsx index c6d2bf97e1cf1..15cddbdadc7fb 100644 --- a/x-pack/plugins/cases/public/components/header_page/title.tsx +++ b/x-pack/plugins/cases/public/components/header_page/title.tsx @@ -10,7 +10,7 @@ import { isString } from 'lodash'; import { EuiBetaBadge, EuiTitle, EuiFlexItem, EuiFlexGroup } from '@elastic/eui'; import { TruncatedText } from '../truncated_text'; -import { ReleasePhase } from '../types'; +import type { ReleasePhase } from '../types'; import * as i18n from './translations'; interface Props { 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 1a745221bbc48..931cf3255c5a5 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,7 +10,8 @@ import { mount } from 'enzyme'; import { waitFor } from '@testing-library/react'; import { TestProviders } from '../../common/mock'; -import { Form, useForm, FormHook } from '../../common/shared_imports'; +import type { FormHook } from '../../common/shared_imports'; +import { Form, useForm } from '../../common/shared_imports'; import { CasesTimelineIntegrationProvider } from '../timeline_context'; import { timelineIntegrationMock } from '../__mock__/timeline'; import { getFormMock } from '../__mock__/form'; diff --git a/x-pack/plugins/cases/public/components/link_icon/index.tsx b/x-pack/plugins/cases/public/components/link_icon/index.tsx index 6285eceed0dd4..5f65ab39e39e2 100644 --- a/x-pack/plugins/cases/public/components/link_icon/index.tsx +++ b/x-pack/plugins/cases/public/components/link_icon/index.tsx @@ -5,9 +5,11 @@ * 2.0. */ -import { EuiIcon, EuiLink, IconSize, IconType } from '@elastic/eui'; -import { LinkAnchorProps } from '@elastic/eui/src/components/link/link'; -import React, { ReactNode, useCallback, useMemo } from 'react'; +import type { IconSize, IconType } from '@elastic/eui'; +import { EuiIcon, EuiLink } from '@elastic/eui'; +import type { LinkAnchorProps } from '@elastic/eui/src/components/link/link'; +import type { ReactNode } from 'react'; +import React, { useCallback, useMemo } from 'react'; import styled, { css } from 'styled-components'; interface LinkProps { diff --git a/x-pack/plugins/cases/public/components/links/index.test.tsx b/x-pack/plugins/cases/public/components/links/index.test.tsx index 69c418790c9d7..e2da1a28261e7 100644 --- a/x-pack/plugins/cases/public/components/links/index.test.tsx +++ b/x-pack/plugins/cases/public/components/links/index.test.tsx @@ -6,18 +6,15 @@ */ import React from 'react'; -import { ReactWrapper, mount } from 'enzyme'; +import type { ReactWrapper } from 'enzyme'; +import { mount } from 'enzyme'; import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { EuiText } from '@elastic/eui'; import '../../common/mock/match_media'; -import { - ConfigureCaseButton, - ConfigureCaseButtonProps, - CaseDetailsLink, - CaseDetailsLinkProps, -} from '.'; +import type { ConfigureCaseButtonProps, CaseDetailsLinkProps } from '.'; +import { ConfigureCaseButton, CaseDetailsLink } from '.'; import { TestProviders } from '../../common/mock'; import { useCaseViewNavigation } from '../../common/navigation/hooks'; diff --git a/x-pack/plugins/cases/public/components/links/index.tsx b/x-pack/plugins/cases/public/components/links/index.tsx index db8a4df2a88ca..2916aebd2d32f 100644 --- a/x-pack/plugins/cases/public/components/links/index.tsx +++ b/x-pack/plugins/cases/public/components/links/index.tsx @@ -5,15 +5,8 @@ * 2.0. */ -import { - EuiButton, - EuiButtonProps, - EuiLink, - EuiLinkProps, - EuiToolTip, - PropsForAnchor, - PropsForButton, -} from '@elastic/eui'; +import type { EuiButtonProps, EuiLinkProps, PropsForAnchor, PropsForButton } from '@elastic/eui'; +import { EuiButton, EuiLink, EuiToolTip } from '@elastic/eui'; import React, { useCallback, useMemo } from 'react'; import { useCaseViewNavigation, useConfigureCasesNavigation } from '../../common/navigation'; import * as i18n from './translations'; diff --git a/x-pack/plugins/cases/public/components/markdown_editor/editor.tsx b/x-pack/plugins/cases/public/components/markdown_editor/editor.tsx index a3de9072f0ea5..613fe6153b25d 100644 --- a/x-pack/plugins/cases/public/components/markdown_editor/editor.tsx +++ b/x-pack/plugins/cases/public/components/markdown_editor/editor.tsx @@ -5,18 +5,12 @@ * 2.0. */ -import React, { - memo, - forwardRef, - useCallback, - useRef, - useState, - useImperativeHandle, - ElementRef, -} from 'react'; -import { PluggableList } from 'unified'; -import { EuiMarkdownEditor, EuiMarkdownEditorProps, EuiMarkdownAstNode } from '@elastic/eui'; -import { ContextShape } from '@elastic/eui/src/components/markdown_editor/markdown_context'; +import type { ElementRef } from 'react'; +import React, { memo, forwardRef, useCallback, useRef, useState, useImperativeHandle } from 'react'; +import type { PluggableList } from 'unified'; +import type { EuiMarkdownEditorProps, EuiMarkdownAstNode } from '@elastic/eui'; +import { EuiMarkdownEditor } from '@elastic/eui'; +import type { ContextShape } from '@elastic/eui/src/components/markdown_editor/markdown_context'; import { usePlugins } from './use_plugins'; import { useLensButtonToggle } from './plugins/lens/use_lens_button_toggle'; 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 f0e951c89326f..2884816a091a3 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 @@ -7,9 +7,12 @@ import React, { forwardRef, useMemo } from 'react'; import styled from 'styled-components'; -import { EuiMarkdownEditorProps, EuiFormRow, EuiFlexItem, EuiFlexGroup } from '@elastic/eui'; -import { FieldHook, getFieldValidityAndErrorMessage } from '../../common/shared_imports'; -import { MarkdownEditor, MarkdownEditorRef } from './editor'; +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 { MarkdownEditorRef } from './editor'; +import { MarkdownEditor } from './editor'; import { CommentEditorContext } from './context'; type MarkdownEditorFormProps = EuiMarkdownEditorProps & { diff --git a/x-pack/plugins/cases/public/components/markdown_editor/markdown_link.tsx b/x-pack/plugins/cases/public/components/markdown_editor/markdown_link.tsx index c42ef90648bc9..e2a7415346fc4 100644 --- a/x-pack/plugins/cases/public/components/markdown_editor/markdown_link.tsx +++ b/x-pack/plugins/cases/public/components/markdown_editor/markdown_link.tsx @@ -6,7 +6,8 @@ */ import React, { memo } from 'react'; -import { EuiLink, EuiLinkAnchorProps, EuiToolTip } from '@elastic/eui'; +import type { EuiLinkAnchorProps } from '@elastic/eui'; +import { EuiLink, EuiToolTip } from '@elastic/eui'; type MarkdownLinkProps = { disableLinks?: boolean } & EuiLinkAnchorProps; diff --git a/x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/parser.ts b/x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/parser.ts index 38243ebfac5a9..dd908b87064a9 100644 --- a/x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/parser.ts +++ b/x-pack/plugins/cases/public/components/markdown_editor/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 { ID, PREFIX } from './constants'; export const LensParser: Plugin = function () { diff --git a/x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/plugin.tsx b/x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/plugin.tsx index 65a2653bb298b..eca83f9e45801 100644 --- a/x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/plugin.tsx +++ b/x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/plugin.tsx @@ -6,19 +6,18 @@ */ import { first } from 'rxjs/operators'; +import type { EuiMarkdownEditorUiPlugin, EuiMarkdownAstNodePosition } from '@elastic/eui'; import { EuiCodeBlock, EuiModalBody, EuiModalHeader, EuiModalHeaderTitle, - EuiMarkdownEditorUiPlugin, EuiMarkdownContext, EuiModalFooter, EuiButtonEmpty, EuiButton, EuiFlexItem, EuiFlexGroup, - EuiMarkdownAstNodePosition, EuiBetaBadge, } from '@elastic/eui'; import React, { useCallback, useContext, useMemo, useEffect, useState } from 'react'; diff --git a/x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/processor.tsx b/x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/processor.tsx index 73ee01231587e..0f84529dcc92a 100644 --- a/x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/processor.tsx +++ b/x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/processor.tsx @@ -9,7 +9,7 @@ import React from 'react'; import styled from 'styled-components'; import { createGlobalStyle } from '@kbn/kibana-react-plugin/common'; -import { TypedLensByValueInput } from '@kbn/lens-plugin/public'; +import type { TypedLensByValueInput } from '@kbn/lens-plugin/public'; import { useKibana } from '../../../../common/lib/kibana'; import { LENS_VISUALIZATION_HEIGHT } from './constants'; diff --git a/x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/saved_objects_finder.tsx b/x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/saved_objects_finder.tsx index a24cc5d644e3d..5b96ea377fc74 100644 --- a/x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/saved_objects_finder.tsx +++ b/x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/saved_objects_finder.tsx @@ -11,12 +11,12 @@ import { debounce } from 'lodash'; import PropTypes from 'prop-types'; import React from 'react'; +import type { EuiFieldSearchProps, IconType, EuiFormRowProps } from '@elastic/eui'; import { EuiContextMenuItem, EuiContextMenuPanel, EuiEmptyPrompt, EuiFieldSearch, - EuiFieldSearchProps, EuiFilterButton, EuiFilterGroup, EuiFlexGroup, @@ -28,14 +28,12 @@ import { EuiPopover, EuiSpacer, EuiTablePagination, - IconType, EuiFormRow, - EuiFormRowProps, } from '@elastic/eui'; -import { Direction } from '@elastic/eui/src/services/sort/sort_direction'; +import type { Direction } from '@elastic/eui/src/services/sort/sort_direction'; import { i18n } from '@kbn/i18n'; -import { SimpleSavedObject, CoreStart } from '@kbn/core/public'; +import type { SimpleSavedObject, CoreStart } from '@kbn/core/public'; import { LISTING_LIMIT_SETTING } from '@kbn/saved-objects-plugin/public'; diff --git a/x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/use_lens_button_toggle.ts b/x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/use_lens_button_toggle.ts index a8ede7ab58068..4431261bdfaaa 100644 --- a/x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/use_lens_button_toggle.ts +++ b/x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/use_lens_button_toggle.ts @@ -9,9 +9,9 @@ import { some } from 'lodash'; import useDebounce from 'react-use/lib/useDebounce'; -import { ContextShape } from '@elastic/eui/src/components/markdown_editor/markdown_context'; +import type { ContextShape } from '@elastic/eui/src/components/markdown_editor/markdown_context'; import { useCallback, useEffect, useRef, useState } from 'react'; -import { EuiMarkdownAstNode, EuiMarkdownEditorUiPlugin } from '@elastic/eui'; +import type { EuiMarkdownAstNode, EuiMarkdownEditorUiPlugin } from '@elastic/eui'; import { VISUALIZATION } from './translations'; import { PREFIX } from './constants'; diff --git a/x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/use_lens_draft_comment.ts b/x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/use_lens_draft_comment.ts index a2dccc0e44d74..f8f4582190284 100644 --- a/x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/use_lens_draft_comment.ts +++ b/x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/use_lens_draft_comment.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { EuiMarkdownAstNodePosition } from '@elastic/eui'; +import type { EuiMarkdownAstNodePosition } from '@elastic/eui'; import { useCallback, useEffect, useState } from 'react'; import { first } from 'rxjs/operators'; import { useKibana } from '../../../../common/lib/kibana'; diff --git a/x-pack/plugins/cases/public/components/markdown_editor/renderer.test.tsx b/x-pack/plugins/cases/public/components/markdown_editor/renderer.test.tsx index 8cb8b7f23b439..57cc3024a0215 100644 --- a/x-pack/plugins/cases/public/components/markdown_editor/renderer.test.tsx +++ b/x-pack/plugins/cases/public/components/markdown_editor/renderer.test.tsx @@ -9,7 +9,8 @@ import React from 'react'; import { removeExternalLinkText } from '../../common/test_utils'; import { MarkdownRenderer } from './renderer'; -import { AppMockRenderer, createAppMockRenderer } from '../../common/mock'; +import type { AppMockRenderer } from '../../common/mock'; +import { createAppMockRenderer } from '../../common/mock'; describe('Markdown', () => { let appMockRender: AppMockRenderer; diff --git a/x-pack/plugins/cases/public/components/markdown_editor/renderer.tsx b/x-pack/plugins/cases/public/components/markdown_editor/renderer.tsx index e0265a2884b97..0f75449883850 100644 --- a/x-pack/plugins/cases/public/components/markdown_editor/renderer.tsx +++ b/x-pack/plugins/cases/public/components/markdown_editor/renderer.tsx @@ -7,7 +7,8 @@ import React, { memo, useMemo } from 'react'; import { cloneDeep } from 'lodash/fp'; -import { EuiMarkdownFormat, EuiLinkAnchorProps } from '@elastic/eui'; +import type { EuiLinkAnchorProps } from '@elastic/eui'; +import { EuiMarkdownFormat } from '@elastic/eui'; import { MarkdownLink } from './markdown_link'; import { usePlugins } from './use_plugins'; diff --git a/x-pack/plugins/cases/public/components/markdown_editor/types.ts b/x-pack/plugins/cases/public/components/markdown_editor/types.ts index 33249c0025f8e..82ff738a178bf 100644 --- a/x-pack/plugins/cases/public/components/markdown_editor/types.ts +++ b/x-pack/plugins/cases/public/components/markdown_editor/types.ts @@ -5,13 +5,12 @@ * 2.0. */ -import { FunctionComponent } from 'react'; -import { Plugin, PluggableList } from 'unified'; +import type { FunctionComponent } from 'react'; +import type { Plugin, PluggableList } from 'unified'; // Remove after this issue is resolved: https://github.com/elastic/eui/issues/4688 -import { Options as Remark2RehypeOptions } from 'mdast-util-to-hast'; -// eslint-disable-next-line import/no-extraneous-dependencies -import rehype2react from 'rehype-react'; -import { EuiLinkAnchorProps } from '@elastic/eui'; +import type { Options as Remark2RehypeOptions } from 'mdast-util-to-hast'; +import type rehype2react from 'rehype-react'; +import type { EuiLinkAnchorProps } from '@elastic/eui'; export interface CursorPosition { start: number; end: number; diff --git a/x-pack/plugins/cases/public/components/markdown_editor/use_plugins.ts b/x-pack/plugins/cases/public/components/markdown_editor/use_plugins.ts index 15d92d1c7f1a1..2ed36feebcb4e 100644 --- a/x-pack/plugins/cases/public/components/markdown_editor/use_plugins.ts +++ b/x-pack/plugins/cases/public/components/markdown_editor/use_plugins.ts @@ -12,7 +12,7 @@ import { } from '@elastic/eui'; import { useMemo } from 'react'; import { useTimelineContext } from '../timeline_context/use_timeline_context'; -import { TemporaryProcessingPluginsType } from './types'; +import type { TemporaryProcessingPluginsType } from './types'; import { KibanaServices, useApplicationCapabilities } from '../../common/lib/kibana'; import * as lensMarkdownPlugin from './plugins/lens'; import { ID as LensPluginId } from './plugins/lens/constants'; diff --git a/x-pack/plugins/cases/public/components/recent_cases/filters/index.tsx b/x-pack/plugins/cases/public/components/recent_cases/filters/index.tsx index b42ed968e78c5..c93cf8a1995a8 100644 --- a/x-pack/plugins/cases/public/components/recent_cases/filters/index.tsx +++ b/x-pack/plugins/cases/public/components/recent_cases/filters/index.tsx @@ -5,10 +5,11 @@ * 2.0. */ -import { EuiButtonGroup, EuiButtonGroupOptionProps } from '@elastic/eui'; +import type { EuiButtonGroupOptionProps } from '@elastic/eui'; +import { EuiButtonGroup } from '@elastic/eui'; import React, { useCallback, useMemo } from 'react'; -import { FilterMode } from '../types'; +import type { FilterMode } from '../types'; import * as i18n from '../translations'; diff --git a/x-pack/plugins/cases/public/components/recent_cases/index.test.tsx b/x-pack/plugins/cases/public/components/recent_cases/index.test.tsx index 46138fb354604..d61dcc2a23429 100644 --- a/x-pack/plugins/cases/public/components/recent_cases/index.test.tsx +++ b/x-pack/plugins/cases/public/components/recent_cases/index.test.tsx @@ -8,13 +8,10 @@ import React from 'react'; import { configure, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; -import RecentCases, { RecentCasesProps } from '.'; -import { - AppMockRenderer, - createAppMockRenderer, - noCasesCapabilities, - TestProviders, -} from '../../common/mock'; +import type { RecentCasesProps } from '.'; +import RecentCases from '.'; +import type { AppMockRenderer } from '../../common/mock'; +import { createAppMockRenderer, noCasesCapabilities, TestProviders } from '../../common/mock'; import { useGetCasesMockState } from '../../containers/mock'; import { useCurrentUser } from '../../common/lib/kibana/hooks'; import { useGetCases } from '../../containers/use_get_cases'; diff --git a/x-pack/plugins/cases/public/components/recent_cases/index.tsx b/x-pack/plugins/cases/public/components/recent_cases/index.tsx index c63c98b14a6e9..0637e077b16e5 100644 --- a/x-pack/plugins/cases/public/components/recent_cases/index.tsx +++ b/x-pack/plugins/cases/public/components/recent_cases/index.tsx @@ -9,17 +9,18 @@ import { EuiFlexGroup, EuiFlexItem, EuiHorizontalRule, EuiText, EuiTitle } from import React, { useCallback, useMemo, useState } from 'react'; import { QueryClientProvider } from '@tanstack/react-query'; -import { UserProfile } from '@kbn/user-profile-components'; +import type { UserProfile } from '@kbn/user-profile-components'; import * as i18n from './translations'; import { LinkAnchor } from '../links'; import { RecentCasesFilters } from './filters'; import { RecentCasesComp } from './recent_cases'; -import { FilterMode as RecentCasesFilterMode } from './types'; -import { AuthenticatedElasticUser, useCurrentUser } from '../../common/lib/kibana'; +import type { FilterMode as RecentCasesFilterMode } from './types'; +import type { AuthenticatedElasticUser } from '../../common/lib/kibana'; +import { useCurrentUser } from '../../common/lib/kibana'; import { useAllCasesNavigation } from '../../common/navigation'; import { casesQueryClient } from '../cases_context/query_client'; import { useGetCurrentUserProfile } from '../../containers/user_profiles/use_get_current_user_profile'; -import { User } from '../../../common/api'; +import type { User } from '../../../common/api'; export interface RecentCasesProps { maxCasesToShow: number; diff --git a/x-pack/plugins/cases/public/components/recent_cases/recent_cases.tsx b/x-pack/plugins/cases/public/components/recent_cases/recent_cases.tsx index 190972eeb9327..9aa954ecb9be1 100644 --- a/x-pack/plugins/cases/public/components/recent_cases/recent_cases.tsx +++ b/x-pack/plugins/cases/public/components/recent_cases/recent_cases.tsx @@ -15,7 +15,7 @@ import { CaseDetailsLink } from '../links'; import { LoadingPlaceholders } from './loading_placeholders'; import { NoCases } from './no_cases'; import { MarkdownRenderer } from '../markdown_editor'; -import { FilterOptions } from '../../containers/types'; +import type { FilterOptions } from '../../containers/types'; import { TruncatedText } from '../truncated_text'; import { initialData as initialGetCasesData, useGetCases } from '../../containers/use_get_cases'; import { useAvailableCasesOwners } from '../app/use_available_owners'; diff --git a/x-pack/plugins/cases/public/components/severity/selector.tsx b/x-pack/plugins/cases/public/components/severity/selector.tsx index 0d1ff4b319f2b..63cd57e1925cd 100644 --- a/x-pack/plugins/cases/public/components/severity/selector.tsx +++ b/x-pack/plugins/cases/public/components/severity/selector.tsx @@ -5,15 +5,10 @@ * 2.0. */ -import { - EuiFlexGroup, - EuiFlexItem, - EuiHealth, - EuiSuperSelect, - EuiSuperSelectOption, -} from '@elastic/eui'; +import type { EuiSuperSelectOption } from '@elastic/eui'; +import { EuiFlexGroup, EuiFlexItem, EuiHealth, EuiSuperSelect } from '@elastic/eui'; import React from 'react'; -import { CaseSeverity } from '../../../common/api'; +import type { CaseSeverity } from '../../../common/api'; import { severities } from './config'; interface Props { diff --git a/x-pack/plugins/cases/public/components/severity/sidebar_selector.tsx b/x-pack/plugins/cases/public/components/severity/sidebar_selector.tsx index ff591e342793f..1210fc78da52f 100644 --- a/x-pack/plugins/cases/public/components/severity/sidebar_selector.tsx +++ b/x-pack/plugins/cases/public/components/severity/sidebar_selector.tsx @@ -7,7 +7,7 @@ import { EuiFlexItem, EuiHorizontalRule, EuiSpacer, EuiText } from '@elastic/eui'; import React from 'react'; -import { CaseSeverity } from '../../../common/api'; +import type { CaseSeverity } from '../../../common/api'; import { SeveritySelector } from './selector'; import { SEVERITY_TITLE } from './translations'; diff --git a/x-pack/plugins/cases/public/components/status/button.tsx b/x-pack/plugins/cases/public/components/status/button.tsx index 34eb5d62c7790..bed36942ed6e8 100644 --- a/x-pack/plugins/cases/public/components/status/button.tsx +++ b/x-pack/plugins/cases/public/components/status/button.tsx @@ -8,7 +8,8 @@ import React, { memo, useCallback, useMemo } from 'react'; import { EuiButton } from '@elastic/eui'; -import { CaseStatuses, caseStatuses } from '../../../common/api'; +import type { CaseStatuses } from '../../../common/api'; +import { caseStatuses } from '../../../common/api'; import { statuses } from './config'; interface Props { diff --git a/x-pack/plugins/cases/public/components/status/config.ts b/x-pack/plugins/cases/public/components/status/config.ts index 520759991605b..113f91d5194df 100644 --- a/x-pack/plugins/cases/public/components/status/config.ts +++ b/x-pack/plugins/cases/public/components/status/config.ts @@ -4,10 +4,13 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ +import { getStatusConfiguration } from '@kbn/cases-components'; import { StatusAll } from '../../../common/ui/types'; import { CaseStatuses } from '../../../common/api'; import * as i18n from './translations'; -import { AllCaseStatus, Statuses } from './types'; +import type { AllCaseStatus, Statuses } from './types'; + +const statusConfiguration = getStatusConfiguration(); export const allCaseStatus: AllCaseStatus = { [StatusAll]: { color: 'hollow', label: i18n.ALL }, @@ -15,9 +18,7 @@ export const allCaseStatus: AllCaseStatus = { export const statuses: Statuses = { [CaseStatuses.open]: { - color: 'primary', - label: i18n.OPEN, - icon: 'folderOpen' as const, + ...statusConfiguration[CaseStatuses.open], actions: { single: { title: i18n.OPEN_CASE, @@ -34,9 +35,7 @@ export const statuses: Statuses = { }, }, [CaseStatuses['in-progress']]: { - color: 'warning', - label: i18n.IN_PROGRESS, - icon: 'folderExclamation' as const, + ...statusConfiguration[CaseStatuses['in-progress']], actions: { single: { title: i18n.MARK_CASE_IN_PROGRESS, @@ -53,9 +52,7 @@ export const statuses: Statuses = { }, }, [CaseStatuses.closed]: { - color: 'default', - label: i18n.CLOSED, - icon: 'folderCheck' as const, + ...statusConfiguration[CaseStatuses.closed], actions: { single: { title: i18n.CLOSE_CASE, diff --git a/x-pack/plugins/cases/public/components/status/index.ts b/x-pack/plugins/cases/public/components/status/index.ts index a261b903ae9ce..defeb3b8b0f15 100644 --- a/x-pack/plugins/cases/public/components/status/index.ts +++ b/x-pack/plugins/cases/public/components/status/index.ts @@ -5,7 +5,7 @@ * 2.0. */ -export * from './status'; +export * from './status_popover_button'; export * from './config'; export * from './status_stats'; export * from './types'; diff --git a/x-pack/plugins/cases/public/components/status/status.test.tsx b/x-pack/plugins/cases/public/components/status/status.test.tsx deleted file mode 100644 index 9ea71dfd52393..0000000000000 --- a/x-pack/plugins/cases/public/components/status/status.test.tsx +++ /dev/null @@ -1,93 +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 from 'react'; -import { mount } from 'enzyme'; - -import { CaseStatuses } from '../../../common/api'; -import { Status } from './status'; - -describe('Stats', () => { - const onClick = jest.fn(); - - it('it renders', async () => { - const wrapper = mount(); - - expect(wrapper.find(`[data-test-subj="status-badge-open"]`).exists()).toBeTruthy(); - expect( - wrapper.find(`[data-test-subj="status-badge-open"] .euiBadge__iconButton`).exists() - ).toBeFalsy(); - }); - - it('it renders with arrow', async () => { - const wrapper = mount(); - - expect( - wrapper.find(`[data-test-subj="status-badge-open"] .euiBadge__iconButton`).exists() - ).toBeTruthy(); - }); - - it('it renders with the pop over enabled by default', async () => { - const wrapper = mount(); - - expect( - wrapper - .find(`[data-test-subj="status-badge-open"] .euiBadge__iconButton`) - .first() - .prop('disabled') - ).toBe(false); - }); - - it('renders without the arrow and is not clickable when initialized disabled', async () => { - const wrapper = mount( - - ); - - expect( - wrapper.find(`[data-test-subj="status-badge-open"] .euiBadge__iconButton`).exists() - ).toBeFalsy(); - }); - - it('it calls onClick when pressing the badge', async () => { - const wrapper = mount(); - - wrapper.find(`[data-test-subj="status-badge-open"] .euiBadge__iconButton`).simulate('click'); - expect(onClick).toHaveBeenCalled(); - }); - - describe('Colors', () => { - it('shows the correct color when status is open', async () => { - const wrapper = mount( - - ); - - expect(wrapper.find(`[data-test-subj="status-badge-open"]`).first().prop('color')).toBe( - 'primary' - ); - }); - - it('shows the correct color when status is in-progress', async () => { - const wrapper = mount( - - ); - - expect( - wrapper.find(`[data-test-subj="status-badge-in-progress"]`).first().prop('color') - ).toBe('warning'); - }); - - it('shows the correct color when status is closed', async () => { - const wrapper = mount( - - ); - - expect(wrapper.find(`[data-test-subj="status-badge-closed"]`).first().prop('color')).toBe( - 'default' - ); - }); - }); -}); diff --git a/x-pack/plugins/cases/public/components/status/status.tsx b/x-pack/plugins/cases/public/components/status/status.tsx deleted file mode 100644 index ad9add5d3fffd..0000000000000 --- a/x-pack/plugins/cases/public/components/status/status.tsx +++ /dev/null @@ -1,51 +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, { memo, useMemo } from 'react'; -import { noop } from 'lodash/fp'; -import { EuiBadge } from '@elastic/eui'; - -import { allCaseStatus, statuses } from './config'; -import * as i18n from './translations'; -import { CaseStatusWithAllStatus, StatusAll } from '../../../common/ui/types'; - -interface Props { - disabled?: boolean; - type: CaseStatusWithAllStatus; - withArrow?: boolean; - onClick?: () => void; -} - -const StatusComponent: React.FC = ({ - type, - disabled = false, - withArrow = false, - onClick = noop, -}) => { - const props = useMemo( - () => ({ - color: type === StatusAll ? allCaseStatus[StatusAll].color : statuses[type].color, - // if we are disabled, don't show the arrow and don't allow the user to click - ...(withArrow && !disabled ? { iconType: 'arrowDown', iconSide: 'right' as const } : {}), - ...(!disabled ? { iconOnClick: onClick } : { iconOnClick: noop }), - }), - [disabled, onClick, withArrow, type] - ); - - return ( - - {type === StatusAll ? allCaseStatus[StatusAll].label : statuses[type].label} - - ); -}; -StatusComponent.displayName = 'Status'; - -export const Status = memo(StatusComponent); diff --git a/x-pack/plugins/cases/public/components/status/status_popover_button.test.tsx b/x-pack/plugins/cases/public/components/status/status_popover_button.test.tsx new file mode 100644 index 0000000000000..6706aaec9c71f --- /dev/null +++ b/x-pack/plugins/cases/public/components/status/status_popover_button.test.tsx @@ -0,0 +1,99 @@ +/* + * 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 { mount } from 'enzyme'; + +import { CaseStatuses } from '../../../common/api'; +import { StatusPopoverButton } from './status_popover_button'; + +describe('StatusPopoverButton', () => { + const onClick = jest.fn(); + + it('renders', async () => { + const wrapper = mount(); + + expect( + wrapper.find(`[data-test-subj="case-status-badge-popover-button-open"]`).exists() + ).toBeTruthy(); + expect( + wrapper + .find(`[data-test-subj="case-status-badge-popover-button-open"] .euiBadge__iconButton`) + .exists() + ).toBeTruthy(); + }); + + it('renders with the pop over enabled by default', async () => { + const wrapper = mount(); + + expect( + wrapper + .find(`[data-test-subj="case-status-badge-popover-button-open"] .euiBadge__iconButton`) + .first() + .prop('disabled') + ).toBe(false); + }); + + it('disables the button correctly', async () => { + const wrapper = mount( + + ); + + expect( + wrapper + .find(`[data-test-subj="case-status-badge-popover-button-open"] .euiBadge__iconButton`) + .first() + .prop('disabled') + ).toBe(true); + }); + + it('calls onClick when pressing the badge', async () => { + const wrapper = mount(); + + wrapper + .find(`[data-test-subj="case-status-badge-popover-button-open"] .euiBadge__iconButton`) + .simulate('click'); + expect(onClick).toHaveBeenCalled(); + }); + + describe('Colors', () => { + it('shows the correct color when status is open', async () => { + const wrapper = mount(); + + expect( + wrapper + .find(`[data-test-subj="case-status-badge-popover-button-open"]`) + .first() + .prop('color') + ).toBe('primary'); + }); + + it('shows the correct color when status is in-progress', async () => { + const wrapper = mount( + + ); + + expect( + wrapper + .find(`[data-test-subj="case-status-badge-popover-button-in-progress"]`) + .first() + .prop('color') + ).toBe('warning'); + }); + + it('shows the correct color when status is closed', async () => { + const wrapper = mount(); + + expect( + wrapper + .find(`[data-test-subj="case-status-badge-popover-button-closed"]`) + .first() + .prop('color') + ).toBe('default'); + }); + }); +}); diff --git a/x-pack/plugins/cases/public/components/status/status_popover_button.tsx b/x-pack/plugins/cases/public/components/status/status_popover_button.tsx new file mode 100644 index 0000000000000..04a426347c83f --- /dev/null +++ b/x-pack/plugins/cases/public/components/status/status_popover_button.tsx @@ -0,0 +1,39 @@ +/* + * 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, { memo } from 'react'; +import { EuiBadge } from '@elastic/eui'; + +import type { CaseStatuses } from '@kbn/cases-components'; +import { statuses } from './config'; +import * as i18n from './translations'; + +interface Props { + disabled?: boolean; + status: CaseStatuses; + onClick: () => void; +} + +const StatusPopoverButtonComponent: React.FC = ({ status, disabled = false, onClick }) => { + return ( + + {statuses[status].label} + + ); +}; + +StatusPopoverButtonComponent.displayName = 'StatusPopoverButton'; + +export const StatusPopoverButton = memo(StatusPopoverButtonComponent); diff --git a/x-pack/plugins/cases/public/components/status/status_stats.tsx b/x-pack/plugins/cases/public/components/status/status_stats.tsx index 56f4259f87ea6..515c095b24c28 100644 --- a/x-pack/plugins/cases/public/components/status/status_stats.tsx +++ b/x-pack/plugins/cases/public/components/status/status_stats.tsx @@ -7,7 +7,7 @@ import React, { memo, useMemo } from 'react'; import { EuiDescriptionList, EuiLoadingSpinner } from '@elastic/eui'; -import { CaseStatuses } from '../../../common/api'; +import type { CaseStatuses } from '../../../common/api'; import { statuses } from './config'; export interface Props { diff --git a/x-pack/plugins/cases/public/components/status/translations.ts b/x-pack/plugins/cases/public/components/status/translations.ts index 9401209c51c08..3806074f3be11 100644 --- a/x-pack/plugins/cases/public/components/status/translations.ts +++ b/x-pack/plugins/cases/public/components/status/translations.ts @@ -12,18 +12,6 @@ export const ALL = i18n.translate('xpack.cases.status.all', { defaultMessage: 'All status', }); -export const OPEN = i18n.translate('xpack.cases.status.open', { - defaultMessage: 'Open', -}); - -export const IN_PROGRESS = i18n.translate('xpack.cases.status.inProgress', { - defaultMessage: 'In progress', -}); - -export const CLOSED = i18n.translate('xpack.cases.status.closed', { - defaultMessage: 'Closed', -}); - export const STATUS_ICON_ARIA = i18n.translate('xpack.cases.status.iconAria', { defaultMessage: 'Change status', }); @@ -39,10 +27,3 @@ export const CASE_IN_PROGRESS = i18n.translate('xpack.cases.caseView.caseInProgr export const CASE_CLOSED = i18n.translate('xpack.cases.caseView.caseClosed', { defaultMessage: 'Case closed', }); - -export const BULK_ACTION_DELETE_SELECTED = i18n.translate( - 'xpack.cases.caseTable.bulkActions.deleteSelectedTitle', - { - defaultMessage: 'Delete selected', - } -); diff --git a/x-pack/plugins/cases/public/components/status/types.ts b/x-pack/plugins/cases/public/components/status/types.ts index 1df8eb781ecc0..1bd8b553593b6 100644 --- a/x-pack/plugins/cases/public/components/status/types.ts +++ b/x-pack/plugins/cases/public/components/status/types.ts @@ -5,9 +5,9 @@ * 2.0. */ -import { EuiIconType } from '@elastic/eui/src/components/icon/icon'; -import { StatusAllType } from '../../../common/ui/types'; -import { CaseStatuses } from '../../../common/api'; +import type { EuiIconType } from '@elastic/eui/src/components/icon/icon'; +import type { StatusAllType } from '../../../common/ui/types'; +import type { CaseStatuses } from '../../../common/api'; export type AllCaseStatus = Record; diff --git a/x-pack/plugins/cases/public/components/tags/tags.tsx b/x-pack/plugins/cases/public/components/tags/tags.tsx index dd27a4a91ca12..af9623f666564 100644 --- a/x-pack/plugins/cases/public/components/tags/tags.tsx +++ b/x-pack/plugins/cases/public/components/tags/tags.tsx @@ -6,7 +6,8 @@ */ import React, { memo } from 'react'; -import { EuiBadgeGroup, EuiBadge, EuiBadgeGroupProps } from '@elastic/eui'; +import type { EuiBadgeGroupProps } from '@elastic/eui'; +import { EuiBadgeGroup, EuiBadge } from '@elastic/eui'; import styled from 'styled-components'; interface TagsProps { diff --git a/x-pack/plugins/cases/public/components/timeline_context/index.tsx b/x-pack/plugins/cases/public/components/timeline_context/index.tsx index 7dd8ae8e9851b..9187a4131053e 100644 --- a/x-pack/plugins/cases/public/components/timeline_context/index.tsx +++ b/x-pack/plugins/cases/public/components/timeline_context/index.tsx @@ -6,8 +6,8 @@ */ import React, { useState } from 'react'; -import { EuiMarkdownEditorUiPlugin, EuiMarkdownAstNodePosition } from '@elastic/eui'; -import { Plugin } from 'unified'; +import type { EuiMarkdownEditorUiPlugin, EuiMarkdownAstNodePosition } from '@elastic/eui'; +import type { Plugin } from 'unified'; /** * @description - manage the plugins, hooks, and ui components needed to enable timeline functionality within the cases plugin * @TODO - To better encapsulate the timeline logic needed by cases, we are managing it in this top level context. diff --git a/x-pack/plugins/cases/public/components/types.ts b/x-pack/plugins/cases/public/components/types.ts index d9ba8890aab31..7135672a8a53c 100644 --- a/x-pack/plugins/cases/public/components/types.ts +++ b/x-pack/plugins/cases/public/components/types.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { UserProfileWithAvatar } from '@kbn/user-profile-components'; +import type { UserProfileWithAvatar } from '@kbn/user-profile-components'; export type { CaseActionConnector } from '../../common/ui/types'; diff --git a/x-pack/plugins/cases/public/components/use_breadcrumbs/index.test.tsx b/x-pack/plugins/cases/public/components/use_breadcrumbs/index.test.tsx index 04e848e92d63a..7a52686e64378 100644 --- a/x-pack/plugins/cases/public/components/use_breadcrumbs/index.test.tsx +++ b/x-pack/plugins/cases/public/components/use_breadcrumbs/index.test.tsx @@ -5,7 +5,8 @@ * 2.0. */ -import React, { ReactNode } from 'react'; +import type { ReactNode } from 'react'; +import React from 'react'; import { renderHook } from '@testing-library/react-hooks'; import { TestProviders } from '../../common/mock'; import { useCasesBreadcrumbs, useCasesTitleBreadcrumbs } from '.'; diff --git a/x-pack/plugins/cases/public/components/use_breadcrumbs/index.ts b/x-pack/plugins/cases/public/components/use_breadcrumbs/index.ts index ce42b36a471e3..68a37f8252f05 100644 --- a/x-pack/plugins/cases/public/components/use_breadcrumbs/index.ts +++ b/x-pack/plugins/cases/public/components/use_breadcrumbs/index.ts @@ -6,10 +6,11 @@ */ import { i18n } from '@kbn/i18n'; -import { ChromeBreadcrumb } from '@kbn/core/public'; +import type { ChromeBreadcrumb } from '@kbn/core/public'; import { useCallback, useEffect } from 'react'; import { useKibana, useNavigation } from '../../common/lib/kibana'; -import { CasesDeepLinkId, ICasesDeepLinkId } from '../../common/navigation'; +import type { ICasesDeepLinkId } from '../../common/navigation'; +import { CasesDeepLinkId } from '../../common/navigation'; import { useCasesContext } from '../cases_context/use_cases_context'; const casesBreadcrumbTitle: Record = { diff --git a/x-pack/plugins/cases/public/components/use_create_case_modal/create_case_modal.tsx b/x-pack/plugins/cases/public/components/use_create_case_modal/create_case_modal.tsx index f7450b2dd31ef..0418746eff912 100644 --- a/x-pack/plugins/cases/public/components/use_create_case_modal/create_case_modal.tsx +++ b/x-pack/plugins/cases/public/components/use_create_case_modal/create_case_modal.tsx @@ -8,7 +8,7 @@ import React, { memo } from 'react'; import { EuiModal, EuiModalBody, EuiModalHeader, EuiModalHeaderTitle } from '@elastic/eui'; -import { Case } from '../../containers/types'; +import type { Case } from '../../containers/types'; import * as i18n from '../../common/translations'; import { CreateCase } from '../create'; diff --git a/x-pack/plugins/cases/public/components/use_create_case_modal/index.test.tsx b/x-pack/plugins/cases/public/components/use_create_case_modal/index.test.tsx index 8225b62d7f4a7..b0985bbc097ce 100644 --- a/x-pack/plugins/cases/public/components/use_create_case_modal/index.test.tsx +++ b/x-pack/plugins/cases/public/components/use_create_case_modal/index.test.tsx @@ -10,7 +10,8 @@ import { renderHook, act } from '@testing-library/react-hooks'; import { render, act as reactAct } from '@testing-library/react'; import { useKibana } from '../../common/lib/kibana'; -import { useCreateCaseModal, UseCreateCaseModalProps, UseCreateCaseModalReturnedValues } from '.'; +import type { UseCreateCaseModalProps, UseCreateCaseModalReturnedValues } from '.'; +import { useCreateCaseModal } from '.'; import { TestProviders } from '../../common/mock'; jest.mock('../../common/lib/kibana'); diff --git a/x-pack/plugins/cases/public/components/use_create_case_modal/index.tsx b/x-pack/plugins/cases/public/components/use_create_case_modal/index.tsx index 1654bfe86a620..f640fd2b3df7c 100644 --- a/x-pack/plugins/cases/public/components/use_create_case_modal/index.tsx +++ b/x-pack/plugins/cases/public/components/use_create_case_modal/index.tsx @@ -6,7 +6,7 @@ */ import React, { useState, useCallback, useMemo } from 'react'; -import { Case } from '../../../common/ui/types'; +import type { Case } from '../../../common/ui/types'; import { CreateCaseModal } from './create_case_modal'; export interface UseCreateCaseModalProps { diff --git a/x-pack/plugins/cases/public/components/use_push_to_service/callout/callout.test.tsx b/x-pack/plugins/cases/public/components/use_push_to_service/callout/callout.test.tsx index b77abd0fd189c..5b49febdf4642 100644 --- a/x-pack/plugins/cases/public/components/use_push_to_service/callout/callout.test.tsx +++ b/x-pack/plugins/cases/public/components/use_push_to_service/callout/callout.test.tsx @@ -8,7 +8,8 @@ import React from 'react'; import { mount } from 'enzyme'; -import { CallOut, CallOutProps } from './callout'; +import type { CallOutProps } from './callout'; +import { CallOut } from './callout'; import { CLOSED_CASE_PUSH_ERROR_ID } from './types'; import { TestProviders } from '../../../common/mock'; diff --git a/x-pack/plugins/cases/public/components/use_push_to_service/callout/callout.tsx b/x-pack/plugins/cases/public/components/use_push_to_service/callout/callout.tsx index a6acf692be10e..ffd19f8366252 100644 --- a/x-pack/plugins/cases/public/components/use_push_to_service/callout/callout.tsx +++ b/x-pack/plugins/cases/public/components/use_push_to_service/callout/callout.tsx @@ -9,7 +9,8 @@ import { EuiCallOut, EuiButton, EuiDescriptionList } from '@elastic/eui'; import { isEmpty } from 'lodash/fp'; import React, { memo, useCallback, useMemo } from 'react'; -import { CLOSED_CASE_PUSH_ERROR_ID, ErrorMessage } from './types'; +import type { ErrorMessage } from './types'; +import { CLOSED_CASE_PUSH_ERROR_ID } from './types'; import * as i18n from './translations'; export interface CallOutProps { diff --git a/x-pack/plugins/cases/public/components/use_push_to_service/callout/index.test.tsx b/x-pack/plugins/cases/public/components/use_push_to_service/callout/index.test.tsx index fb37a1b99b380..e6fdc2eb1bac7 100644 --- a/x-pack/plugins/cases/public/components/use_push_to_service/callout/index.test.tsx +++ b/x-pack/plugins/cases/public/components/use_push_to_service/callout/index.test.tsx @@ -10,7 +10,8 @@ import { mount } from 'enzyme'; import { TestProviders } from '../../../common/mock'; import { createCalloutId } from './helpers'; -import { CaseCallOut, CaseCallOutProps } from '.'; +import type { CaseCallOutProps } from '.'; +import { CaseCallOut } from '.'; describe('CaseCallOut ', () => { beforeEach(() => { diff --git a/x-pack/plugins/cases/public/components/use_push_to_service/callout/index.tsx b/x-pack/plugins/cases/public/components/use_push_to_service/callout/index.tsx index fb9145d2a941a..08192a1efc68f 100644 --- a/x-pack/plugins/cases/public/components/use_push_to_service/callout/index.tsx +++ b/x-pack/plugins/cases/public/components/use_push_to_service/callout/index.tsx @@ -9,7 +9,7 @@ import { EuiSpacer } from '@elastic/eui'; import React, { memo, useCallback, useMemo } from 'react'; import { CallOut } from './callout'; -import { ErrorMessage } from './types'; +import type { ErrorMessage } from './types'; import { createCalloutId } from './helpers'; import { useConfigureCasesNavigation } from '../../../common/navigation'; diff --git a/x-pack/plugins/cases/public/components/use_push_to_service/helpers.tsx b/x-pack/plugins/cases/public/components/use_push_to_service/helpers.tsx index 625c15dee2e05..0a58678da6d0e 100644 --- a/x-pack/plugins/cases/public/components/use_push_to_service/helpers.tsx +++ b/x-pack/plugins/cases/public/components/use_push_to_service/helpers.tsx @@ -10,8 +10,9 @@ import { FormattedMessage } from '@kbn/i18n-react'; import React from 'react'; import * as i18n from './translations'; -import { ActionLicense } from '../../containers/types'; -import { CLOSED_CASE_PUSH_ERROR_ID, ErrorMessage } from './callout/types'; +import type { ActionLicense } from '../../containers/types'; +import type { ErrorMessage } from './callout/types'; +import { CLOSED_CASE_PUSH_ERROR_ID } from './callout/types'; export const getLicenseError = () => ({ id: 'license-error', diff --git a/x-pack/plugins/cases/public/components/use_push_to_service/index.test.tsx b/x-pack/plugins/cases/public/components/use_push_to_service/index.test.tsx index f56a55fdeb7b1..2cd381e7035b2 100644 --- a/x-pack/plugins/cases/public/components/use_push_to_service/index.test.tsx +++ b/x-pack/plugins/cases/public/components/use_push_to_service/index.test.tsx @@ -10,7 +10,8 @@ import { renderHook, act } from '@testing-library/react-hooks'; import { render, screen } from '@testing-library/react'; import '../../common/mock/match_media'; -import { usePushToService, ReturnUsePushToService, UsePushToService } from '.'; +import type { ReturnUsePushToService, UsePushToService } from '.'; +import { usePushToService } from '.'; import { noPushCasesPermissions, readCasesPermissions, TestProviders } from '../../common/mock'; import { CaseStatuses, ConnectorTypes } from '../../../common/api'; import { usePostPushToService } from '../../containers/use_post_push_to_service'; diff --git a/x-pack/plugins/cases/public/components/use_push_to_service/index.tsx b/x-pack/plugins/cases/public/components/use_push_to_service/index.tsx index a9e8f7c176b74..0980ae199038f 100644 --- a/x-pack/plugins/cases/public/components/use_push_to_service/index.tsx +++ b/x-pack/plugins/cases/public/components/use_push_to_service/index.tsx @@ -18,9 +18,10 @@ import { getCaseClosedInfo, } from './helpers'; import * as i18n from './translations'; -import { CaseConnector, ActionConnector, CaseStatuses } from '../../../common/api'; -import { CaseServices } from '../../containers/use_get_case_user_actions'; -import { ErrorMessage } from './callout/types'; +import type { CaseConnector, ActionConnector } from '../../../common/api'; +import { CaseStatuses } from '../../../common/api'; +import type { CaseServices } from '../../containers/use_get_case_user_actions'; +import type { ErrorMessage } from './callout/types'; import { useRefreshCaseViewPage } from '../case_view/use_on_refresh_case_view_page'; import { useGetActionLicense } from '../../containers/use_get_action_license'; import { useCasesContext } from '../cases_context/use_cases_context'; diff --git a/x-pack/plugins/cases/public/components/user_actions/assignees.tsx b/x-pack/plugins/cases/public/components/user_actions/assignees.tsx index af3b4795744c3..a17aa030e4c6d 100644 --- a/x-pack/plugins/cases/public/components/user_actions/assignees.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/assignees.tsx @@ -6,12 +6,13 @@ */ import { EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui'; -import { UserProfileWithAvatar } from '@kbn/user-profile-components'; +import type { UserProfileWithAvatar } from '@kbn/user-profile-components'; import React, { memo } from 'react'; -import { SnakeToCamelCase } from '../../../common/types'; -import { Actions, AssigneesUserAction, User } from '../../../common/api'; +import type { SnakeToCamelCase } from '../../../common/types'; +import type { AssigneesUserAction, User } from '../../../common/api'; +import { Actions } from '../../../common/api'; import { getName } from '../user_profiles/display_name'; -import { Assignee } from '../user_profiles/types'; +import type { Assignee } from '../user_profiles/types'; import { UserToolTip } from '../user_profiles/user_tooltip'; import { createCommonUpdateUserActionBuilder } from './common'; import type { UserActionBuilder, UserActionResponse } from './types'; diff --git a/x-pack/plugins/cases/public/components/user_actions/builder.tsx b/x-pack/plugins/cases/public/components/user_actions/builder.tsx index 903c1c190d8dd..96e2ba248c729 100644 --- a/x-pack/plugins/cases/public/components/user_actions/builder.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/builder.tsx @@ -15,7 +15,7 @@ import { createSeverityUserActionBuilder } from './severity'; import { createStatusUserActionBuilder } from './status'; import { createTagsUserActionBuilder } from './tags'; import { createTitleUserActionBuilder } from './title'; -import { UserActionBuilderMap } from './types'; +import type { UserActionBuilderMap } from './types'; export const builderMap: UserActionBuilderMap = { connector: createConnectorUserActionBuilder, diff --git a/x-pack/plugins/cases/public/components/user_actions/comment/actions.tsx b/x-pack/plugins/cases/public/components/user_actions/comment/actions.tsx index e23514557b631..b82e10b8065a4 100644 --- a/x-pack/plugins/cases/public/components/user_actions/comment/actions.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/comment/actions.tsx @@ -10,10 +10,10 @@ import classNames from 'classnames'; import { ThemeContext } from 'styled-components'; import { EuiToken } from '@elastic/eui'; -import { CommentResponseActionsType } from '../../../../common/api'; -import { UserActionBuilder, UserActionBuilderArgs } from '../types'; +import type { CommentResponseActionsType } from '../../../../common/api'; +import type { UserActionBuilder, UserActionBuilderArgs } from '../types'; import { UserActionTimestamp } from '../timestamp'; -import { SnakeToCamelCase } from '../../../../common/types'; +import type { SnakeToCamelCase } from '../../../../common/types'; import { UserActionCopyLink } from '../copy_link'; import { MarkdownRenderer } from '../../markdown_editor'; import { ContentWrapper } from '../markdown_form'; diff --git a/x-pack/plugins/cases/public/components/user_actions/comment/alert.test.tsx b/x-pack/plugins/cases/public/components/user_actions/comment/alert.test.tsx index 03515b6a2b244..0edb463860f06 100644 --- a/x-pack/plugins/cases/public/components/user_actions/comment/alert.test.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/comment/alert.test.tsx @@ -6,10 +6,10 @@ */ import { omit, merge } from 'lodash'; -import { CommentResponseAlertsType } from '../../../../common/api'; -import { SnakeToCamelCase } from '../../../../common/types'; +import type { CommentResponseAlertsType } from '../../../../common/api'; +import type { SnakeToCamelCase } from '../../../../common/types'; import { getRuleId, getRuleInfo, getRuleName } from './alert'; -import { Ecs } from '../../../containers/types'; +import type { Ecs } from '../../../containers/types'; describe('rule getters', () => { describe.each([ diff --git a/x-pack/plugins/cases/public/components/user_actions/comment/alert.tsx b/x-pack/plugins/cases/public/components/user_actions/comment/alert.tsx index d8218f86bb8ee..20afa12a377bf 100644 --- a/x-pack/plugins/cases/public/components/user_actions/comment/alert.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/comment/alert.tsx @@ -7,13 +7,14 @@ import React from 'react'; import { get, isEmpty } from 'lodash'; -import { EuiCommentProps, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import type { EuiCommentProps } from '@elastic/eui'; +import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { ALERT_RULE_NAME, ALERT_RULE_UUID } from '@kbn/rule-data-utils'; -import { CommentResponseAlertsType } from '../../../../common/api'; -import { UserActionBuilder, UserActionBuilderArgs } from '../types'; +import type { CommentResponseAlertsType } from '../../../../common/api'; +import type { UserActionBuilder, UserActionBuilderArgs } from '../types'; import { UserActionTimestamp } from '../timestamp'; -import { SnakeToCamelCase } from '../../../../common/types'; +import type { SnakeToCamelCase } from '../../../../common/types'; import { MultipleAlertsCommentEvent, SingleAlertCommentEvent } from './alert_event'; import { UserActionCopyLink } from '../copy_link'; import { UserActionShowAlert } from './show_alert'; diff --git a/x-pack/plugins/cases/public/components/user_actions/comment/alert_event.test.tsx b/x-pack/plugins/cases/public/components/user_actions/comment/alert_event.test.tsx index 6bd9748349420..60d5759de6e21 100644 --- a/x-pack/plugins/cases/public/components/user_actions/comment/alert_event.test.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/comment/alert_event.test.tsx @@ -8,7 +8,8 @@ import React from 'react'; import { mount } from 'enzyme'; -import { AppMockRenderer, createAppMockRenderer, TestProviders } from '../../../common/mock'; +import type { AppMockRenderer } from '../../../common/mock'; +import { createAppMockRenderer, TestProviders } from '../../../common/mock'; import { useKibana } from '../../../common/lib/kibana'; import { MultipleAlertsCommentEvent, SingleAlertCommentEvent } from './alert_event'; diff --git a/x-pack/plugins/cases/public/components/user_actions/comment/alert_event.tsx b/x-pack/plugins/cases/public/components/user_actions/comment/alert_event.tsx index 81f45bbb267e9..94f9d290e3757 100644 --- a/x-pack/plugins/cases/public/components/user_actions/comment/alert_event.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/comment/alert_event.tsx @@ -11,7 +11,7 @@ import { EuiLoadingSpinner } from '@elastic/eui'; import * as i18n from '../translations'; import { LinkAnchor } from '../../links'; -import { RuleDetailsNavigation } from '../types'; +import type { RuleDetailsNavigation } from '../types'; interface SingleAlertProps { actionId: string; diff --git a/x-pack/plugins/cases/public/components/user_actions/comment/comment.test.tsx b/x-pack/plugins/cases/public/components/user_actions/comment/comment.test.tsx index 2614da12c2472..46562a028e536 100644 --- a/x-pack/plugins/cases/public/components/user_actions/comment/comment.test.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/comment/comment.test.tsx @@ -26,7 +26,8 @@ import { hostIsolationComment, persistableStateAttachment, } from '../../../containers/mock'; -import { AppMockRenderer, createAppMockRenderer, TestProviders } from '../../../common/mock'; +import type { AppMockRenderer } from '../../../common/mock'; +import { createAppMockRenderer, TestProviders } from '../../../common/mock'; import { createCommentUserActionBuilder } from './comment'; import { getMockBuilderArgs } from '../mock'; import { useCaseViewParams } from '../../../common/navigation'; diff --git a/x-pack/plugins/cases/public/components/user_actions/comment/comment.tsx b/x-pack/plugins/cases/public/components/user_actions/comment/comment.tsx index d4fec4afc7bbe..4e2ecb85e22ba 100644 --- a/x-pack/plugins/cases/public/components/user_actions/comment/comment.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/comment/comment.tsx @@ -5,12 +5,13 @@ * 2.0. */ -import { EuiCommentProps } from '@elastic/eui'; +import type { EuiCommentProps } from '@elastic/eui'; -import { CommentUserAction, Actions, CommentType } from '../../../../common/api'; -import { UserActionBuilder, UserActionBuilderArgs, UserActionResponse } from '../types'; +import type { CommentUserAction } from '../../../../common/api'; +import { Actions, CommentType } from '../../../../common/api'; +import type { UserActionBuilder, UserActionBuilderArgs, UserActionResponse } from '../types'; import { createCommonUpdateUserActionBuilder } from '../common'; -import { Comment } from '../../../containers/types'; +import type { Comment } from '../../../containers/types'; import * as i18n from '../translations'; import { createUserAttachmentUserActionBuilder } from './user'; import { createAlertAttachmentUserActionBuilder } from './alert'; diff --git a/x-pack/plugins/cases/public/components/user_actions/comment/external_reference.tsx b/x-pack/plugins/cases/public/components/user_actions/comment/external_reference.tsx index 2a625eb02d6ad..8e4f627fd73f4 100644 --- a/x-pack/plugins/cases/public/components/user_actions/comment/external_reference.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/comment/external_reference.tsx @@ -5,9 +5,9 @@ * 2.0. */ -import { CommentResponseExternalReferenceType } from '../../../../common/api'; -import { UserActionBuilder, UserActionBuilderArgs } from '../types'; -import { SnakeToCamelCase } from '../../../../common/types'; +import type { CommentResponseExternalReferenceType } from '../../../../common/api'; +import type { UserActionBuilder, UserActionBuilderArgs } from '../types'; +import type { SnakeToCamelCase } from '../../../../common/types'; import { createRegisteredAttachmentUserActionBuilder } from './registered_attachments'; type BuilderArgs = Pick< diff --git a/x-pack/plugins/cases/public/components/user_actions/comment/host_isolation_event.tsx b/x-pack/plugins/cases/public/components/user_actions/comment/host_isolation_event.tsx index e08c2f85e8c31..a638c1a69b30e 100644 --- a/x-pack/plugins/cases/public/components/user_actions/comment/host_isolation_event.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/comment/host_isolation_event.tsx @@ -8,7 +8,7 @@ import React, { memo, useCallback } from 'react'; import * as i18n from '../translations'; import { LinkAnchor } from '../../links'; -import { ActionsNavigation } from '../types'; +import type { ActionsNavigation } from '../types'; interface EndpointInfo { endpointId: string; diff --git a/x-pack/plugins/cases/public/components/user_actions/comment/persistable_state.tsx b/x-pack/plugins/cases/public/components/user_actions/comment/persistable_state.tsx index 769bd4b489534..040fbe794580d 100644 --- a/x-pack/plugins/cases/public/components/user_actions/comment/persistable_state.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/comment/persistable_state.tsx @@ -5,9 +5,9 @@ * 2.0. */ -import { CommentResponseTypePersistableState } from '../../../../common/api'; -import { UserActionBuilder, UserActionBuilderArgs } from '../types'; -import { SnakeToCamelCase } from '../../../../common/types'; +import type { CommentResponseTypePersistableState } from '../../../../common/api'; +import type { UserActionBuilder, UserActionBuilderArgs } from '../types'; +import type { SnakeToCamelCase } from '../../../../common/types'; import { createRegisteredAttachmentUserActionBuilder } from './registered_attachments'; type BuilderArgs = Pick< diff --git a/x-pack/plugins/cases/public/components/user_actions/comment/registered_attachments.tsx b/x-pack/plugins/cases/public/components/user_actions/comment/registered_attachments.tsx index dd8a873c5dd2d..fc2c24f225898 100644 --- a/x-pack/plugins/cases/public/components/user_actions/comment/registered_attachments.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/comment/registered_attachments.tsx @@ -15,12 +15,12 @@ import React, { Suspense } from 'react'; import { memoize } from 'lodash'; import { EuiCallOut, EuiCode, EuiLoadingSpinner } from '@elastic/eui'; -import { AttachmentType } from '../../../client/attachment_framework/types'; -import { AttachmentTypeRegistry } from '../../../../common/registry'; -import { CommentResponse } from '../../../../common/api'; -import { UserActionBuilder, UserActionBuilderArgs } from '../types'; +import type { AttachmentType } from '../../../client/attachment_framework/types'; +import type { AttachmentTypeRegistry } from '../../../../common/registry'; +import type { CommentResponse } from '../../../../common/api'; +import type { UserActionBuilder, UserActionBuilderArgs } from '../types'; import { UserActionTimestamp } from '../timestamp'; -import { SnakeToCamelCase } from '../../../../common/types'; +import type { SnakeToCamelCase } from '../../../../common/types'; import { ATTACHMENT_NOT_REGISTERED_ERROR, DEFAULT_EVENT_ATTACHMENT_TITLE } from './translations'; import { UserActionContentToolbar } from '../content_toolbar'; import * as i18n from '../translations'; diff --git a/x-pack/plugins/cases/public/components/user_actions/comment/show_alert.test.tsx b/x-pack/plugins/cases/public/components/user_actions/comment/show_alert.test.tsx index cc570b245ec90..2e26b0f03ea82 100644 --- a/x-pack/plugins/cases/public/components/user_actions/comment/show_alert.test.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/comment/show_alert.test.tsx @@ -6,7 +6,8 @@ */ import React from 'react'; -import { mount, ReactWrapper } from 'enzyme'; +import type { ReactWrapper } from 'enzyme'; +import { mount } from 'enzyme'; import { UserActionShowAlert } from './show_alert'; const props = { diff --git a/x-pack/plugins/cases/public/components/user_actions/comment/show_alert_table_link.tsx b/x-pack/plugins/cases/public/components/user_actions/comment/show_alert_table_link.tsx index 3ec52e83e5dda..257a639e4e5cd 100644 --- a/x-pack/plugins/cases/public/components/user_actions/comment/show_alert_table_link.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/comment/show_alert_table_link.tsx @@ -7,8 +7,8 @@ import { EuiButtonIcon, EuiToolTip } from '@elastic/eui'; import React, { useCallback } from 'react'; +import { CASE_VIEW_PAGE_TABS } from '../../../../common/types'; import { useCaseViewNavigation, useCaseViewParams } from '../../../common/navigation'; -import { CASE_VIEW_PAGE_TABS } from '../../case_view/types'; import { SHOW_ALERT_TABLE_TOOLTIP } from '../translations'; export const ShowAlertTableLink = () => { diff --git a/x-pack/plugins/cases/public/components/user_actions/comment/user.tsx b/x-pack/plugins/cases/public/components/user_actions/comment/user.tsx index d3ba82c3594c3..91df42cee7e4e 100644 --- a/x-pack/plugins/cases/public/components/user_actions/comment/user.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/comment/user.tsx @@ -8,13 +8,13 @@ import React from 'react'; import classNames from 'classnames'; -import { CommentResponseUserType } from '../../../../common/api'; +import type { CommentResponseUserType } from '../../../../common/api'; import { UserActionTimestamp } from '../timestamp'; -import { SnakeToCamelCase } from '../../../../common/types'; +import type { SnakeToCamelCase } from '../../../../common/types'; import { UserActionMarkdown } from '../markdown_form'; import { UserActionContentToolbar } from '../content_toolbar'; import * as i18n from '../translations'; -import { UserActionBuilderArgs, UserActionBuilder } from '../types'; +import type { UserActionBuilderArgs, UserActionBuilder } from '../types'; import { HoverableUsernameResolver } from '../../user_profiles/hoverable_username_resolver'; import { HoverableAvatarResolver } from '../../user_profiles/hoverable_avatar_resolver'; diff --git a/x-pack/plugins/cases/public/components/user_actions/common.tsx b/x-pack/plugins/cases/public/components/user_actions/common.tsx index a2b883b6869ca..c5d86a9ba5ad0 100644 --- a/x-pack/plugins/cases/public/components/user_actions/common.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/common.tsx @@ -6,11 +6,13 @@ */ import React from 'react'; -import { EuiCommentProps, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import type { EuiCommentProps } from '@elastic/eui'; +import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; -import { Actions, ConnectorUserAction, UserAction } from '../../../common/api'; +import type { ConnectorUserAction, UserAction } from '../../../common/api'; +import { Actions } from '../../../common/api'; import { UserActionTimestamp } from './timestamp'; -import { UserActionBuilder, UserActionBuilderArgs, UserActionResponse } from './types'; +import type { UserActionBuilder, UserActionBuilderArgs, UserActionResponse } from './types'; import { UserActionCopyLink } from './copy_link'; import { UserActionMoveToReference } from './move_to_reference'; import { HoverableUserWithAvatarResolver } from '../user_profiles/hoverable_user_with_avatar_resolver'; diff --git a/x-pack/plugins/cases/public/components/user_actions/connector.tsx b/x-pack/plugins/cases/public/components/user_actions/connector.tsx index 8a9aaa4c3c83a..391ad4a369f44 100644 --- a/x-pack/plugins/cases/public/components/user_actions/connector.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/connector.tsx @@ -5,8 +5,9 @@ * 2.0. */ -import { ConnectorUserAction, NONE_CONNECTOR_ID } from '../../../common/api'; -import { UserActionBuilder, UserActionResponse } from './types'; +import type { ConnectorUserAction } from '../../../common/api'; +import { NONE_CONNECTOR_ID } from '../../../common/api'; +import type { UserActionBuilder, UserActionResponse } from './types'; import { createCommonUpdateUserActionBuilder } from './common'; import * as i18n from './translations'; diff --git a/x-pack/plugins/cases/public/components/user_actions/constants.ts b/x-pack/plugins/cases/public/components/user_actions/constants.ts index 11e16affad7d8..034d01d9d5b4b 100644 --- a/x-pack/plugins/cases/public/components/user_actions/constants.ts +++ b/x-pack/plugins/cases/public/components/user_actions/constants.ts @@ -7,7 +7,7 @@ import { omit } from 'lodash'; import { ActionTypes } from '../../../common/api'; -import { SupportedUserActionTypes } from './types'; +import type { SupportedUserActionTypes } from './types'; export const DRAFT_COMMENT_STORAGE_ID = 'xpack.cases.commentDraft'; diff --git a/x-pack/plugins/cases/public/components/user_actions/content_toolbar.test.tsx b/x-pack/plugins/cases/public/components/user_actions/content_toolbar.test.tsx index bba8303149ae9..bc8d79b25e4e6 100644 --- a/x-pack/plugins/cases/public/components/user_actions/content_toolbar.test.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/content_toolbar.test.tsx @@ -6,8 +6,10 @@ */ import React from 'react'; -import { mount, ReactWrapper } from 'enzyme'; -import { UserActionContentToolbar, UserActionContentToolbarProps } from './content_toolbar'; +import type { ReactWrapper } from 'enzyme'; +import { mount } from 'enzyme'; +import type { UserActionContentToolbarProps } from './content_toolbar'; +import { UserActionContentToolbar } from './content_toolbar'; import { TestProviders } from '../../common/mock'; jest.mock('../../common/navigation/hooks'); diff --git a/x-pack/plugins/cases/public/components/user_actions/content_toolbar.tsx b/x-pack/plugins/cases/public/components/user_actions/content_toolbar.tsx index b824f6f20276f..a37f2f894608b 100644 --- a/x-pack/plugins/cases/public/components/user_actions/content_toolbar.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/content_toolbar.tsx @@ -6,10 +6,12 @@ */ import React, { memo } from 'react'; -import { EuiCommentProps, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import type { EuiCommentProps } from '@elastic/eui'; +import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { UserActionCopyLink } from './copy_link'; -import { Actions, UserActionPropertyActions } from './property_actions'; +import type { Actions } from './property_actions'; +import { UserActionPropertyActions } from './property_actions'; export interface UserActionContentToolbarProps { commentMarkdown?: string; diff --git a/x-pack/plugins/cases/public/components/user_actions/copy_link.test.tsx b/x-pack/plugins/cases/public/components/user_actions/copy_link.test.tsx index d4b093eed12f7..110b2aa9f23b7 100644 --- a/x-pack/plugins/cases/public/components/user_actions/copy_link.test.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/copy_link.test.tsx @@ -6,7 +6,8 @@ */ import React from 'react'; -import { mount, ReactWrapper } from 'enzyme'; +import type { ReactWrapper } from 'enzyme'; +import { mount } from 'enzyme'; import copy from 'copy-to-clipboard'; import { useKibana } from '../../common/lib/kibana'; diff --git a/x-pack/plugins/cases/public/components/user_actions/description.tsx b/x-pack/plugins/cases/public/components/user_actions/description.tsx index ea640e9e693b5..d37992577aeb8 100644 --- a/x-pack/plugins/cases/public/components/user_actions/description.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/description.tsx @@ -7,7 +7,7 @@ import React from 'react'; import classNames from 'classnames'; -import { EuiCommentProps } from '@elastic/eui'; +import type { EuiCommentProps } from '@elastic/eui'; import type { UserActionBuilder, UserActionBuilderArgs, UserActionTreeProps } from './types'; import { createCommonUpdateUserActionBuilder } from './common'; diff --git a/x-pack/plugins/cases/public/components/user_actions/helpers.test.ts b/x-pack/plugins/cases/public/components/user_actions/helpers.test.ts index eb2b7297a9e2e..9b07c99f94278 100644 --- a/x-pack/plugins/cases/public/components/user_actions/helpers.test.ts +++ b/x-pack/plugins/cases/public/components/user_actions/helpers.test.ts @@ -7,7 +7,7 @@ import { CommentType } from '../../../common/api'; import { SECURITY_SOLUTION_OWNER } from '../../../common/constants'; -import { Comment } from '../../containers/types'; +import type { Comment } from '../../containers/types'; import { isUserActionTypeSupported, getManualAlertIdsWithNoRuleId } from './helpers'; const comments: Comment[] = [ diff --git a/x-pack/plugins/cases/public/components/user_actions/helpers.ts b/x-pack/plugins/cases/public/components/user_actions/helpers.ts index 140165f3d5963..fe9e5b2bb5cff 100644 --- a/x-pack/plugins/cases/public/components/user_actions/helpers.ts +++ b/x-pack/plugins/cases/public/components/user_actions/helpers.ts @@ -10,7 +10,7 @@ import { isEmpty } from 'lodash'; import { CommentType } from '../../../common/api'; import type { Comment } from '../../containers/types'; import { SUPPORTED_ACTION_TYPES } from './constants'; -import { SupportedUserActionTypes } from './types'; +import type { SupportedUserActionTypes } from './types'; export const isUserActionTypeSupported = (type: string): type is SupportedUserActionTypes => SUPPORTED_ACTION_TYPES.includes(type as SupportedUserActionTypes); diff --git a/x-pack/plugins/cases/public/components/user_actions/index.test.tsx b/x-pack/plugins/cases/public/components/user_actions/index.test.tsx index aeeff9c99921f..3566de547d354 100644 --- a/x-pack/plugins/cases/public/components/user_actions/index.test.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/index.test.tsx @@ -21,7 +21,8 @@ import { hostReleaseComment, } from '../../containers/mock'; import { UserActions } from '.'; -import { AppMockRenderer, createAppMockRenderer, TestProviders } from '../../common/mock'; +import type { AppMockRenderer } from '../../common/mock'; +import { createAppMockRenderer, TestProviders } from '../../common/mock'; import { Actions } from '../../../common/api'; import { userProfiles, userProfilesMap } from '../../containers/user_profiles/api.mock'; diff --git a/x-pack/plugins/cases/public/components/user_actions/index.tsx b/x-pack/plugins/cases/public/components/user_actions/index.tsx index 6d96d9613a754..fe28487cd41d4 100644 --- a/x-pack/plugins/cases/public/components/user_actions/index.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/index.tsx @@ -5,13 +5,8 @@ * 2.0. */ -import { - EuiFlexGroup, - EuiFlexItem, - EuiLoadingSpinner, - EuiCommentList, - EuiCommentProps, -} from '@elastic/eui'; +import type { EuiCommentProps } from '@elastic/eui'; +import { EuiFlexGroup, EuiFlexItem, EuiLoadingSpinner, EuiCommentList } from '@elastic/eui'; import React, { useMemo, useState, useEffect } from 'react'; import styled from 'styled-components'; diff --git a/x-pack/plugins/cases/public/components/user_actions/markdown_form.test.tsx b/x-pack/plugins/cases/public/components/user_actions/markdown_form.test.tsx index ae242fc64aafa..3925065054c2f 100644 --- a/x-pack/plugins/cases/public/components/user_actions/markdown_form.test.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/markdown_form.test.tsx @@ -8,7 +8,8 @@ import React from 'react'; import { mount } from 'enzyme'; import { UserActionMarkdown } from './markdown_form'; -import { AppMockRenderer, createAppMockRenderer, TestProviders } from '../../common/mock'; +import type { AppMockRenderer } from '../../common/mock'; +import { createAppMockRenderer, TestProviders } from '../../common/mock'; import { waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; const onChangeEditable = jest.fn(); 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 f63ce9b3fce88..784e163fa963d 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 @@ -11,7 +11,8 @@ import styled from 'styled-components'; import * as i18n from '../case_view/translations'; import { Form, useForm, UseField } from '../../common/shared_imports'; -import { schema, Content } from './schema'; +import type { Content } from './schema'; +import { schema } from './schema'; import { MarkdownRenderer, MarkdownEditorForm } from '../markdown_editor'; export const ContentWrapper = styled.div` diff --git a/x-pack/plugins/cases/public/components/user_actions/mock.ts b/x-pack/plugins/cases/public/components/user_actions/mock.ts index b963947a6282d..33eae2b43fbae 100644 --- a/x-pack/plugins/cases/public/components/user_actions/mock.ts +++ b/x-pack/plugins/cases/public/components/user_actions/mock.ts @@ -11,7 +11,7 @@ import { ExternalReferenceAttachmentTypeRegistry } from '../../client/attachment import { PersistableStateAttachmentTypeRegistry } from '../../client/attachment_framework/persistable_state_registry'; import { basicCase, basicPush, getUserAction } from '../../containers/mock'; import { userProfiles, userProfilesMap } from '../../containers/user_profiles/api.mock'; -import { UserActionBuilderArgs } from './types'; +import type { UserActionBuilderArgs } from './types'; export const getMockBuilderArgs = (): UserActionBuilderArgs => { const userAction = getUserAction('title', Actions.update); diff --git a/x-pack/plugins/cases/public/components/user_actions/move_to_reference.test.tsx b/x-pack/plugins/cases/public/components/user_actions/move_to_reference.test.tsx index cd207c635e9d4..5ebfa36fdaebb 100644 --- a/x-pack/plugins/cases/public/components/user_actions/move_to_reference.test.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/move_to_reference.test.tsx @@ -6,7 +6,8 @@ */ import React from 'react'; -import { mount, ReactWrapper } from 'enzyme'; +import type { ReactWrapper } from 'enzyme'; +import { mount } from 'enzyme'; import { UserActionMoveToReference } from './move_to_reference'; const outlineComment = jest.fn(); diff --git a/x-pack/plugins/cases/public/components/user_actions/property_actions.test.tsx b/x-pack/plugins/cases/public/components/user_actions/property_actions.test.tsx index 01a4605f1651f..75d2b3027f37b 100644 --- a/x-pack/plugins/cases/public/components/user_actions/property_actions.test.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/property_actions.test.tsx @@ -6,7 +6,8 @@ */ import React from 'react'; -import { UserActionPropertyActions, UserActionPropertyActionsProps } from './property_actions'; +import type { UserActionPropertyActionsProps } from './property_actions'; +import { UserActionPropertyActions } from './property_actions'; import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { waitForEuiPopoverOpen } from '@elastic/eui/lib/test/rtl'; diff --git a/x-pack/plugins/cases/public/components/user_actions/pushed.tsx b/x-pack/plugins/cases/public/components/user_actions/pushed.tsx index 2a50cc0e0eb57..fd16b13b3f62d 100644 --- a/x-pack/plugins/cases/public/components/user_actions/pushed.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/pushed.tsx @@ -6,14 +6,16 @@ */ import React from 'react'; -import { EuiCommentProps, EuiFlexGroup, EuiFlexItem, EuiLink } from '@elastic/eui'; +import type { EuiCommentProps } from '@elastic/eui'; +import { EuiFlexGroup, EuiFlexItem, EuiLink } from '@elastic/eui'; -import { Actions, NONE_CONNECTOR_ID, PushedUserAction } from '../../../common/api'; -import { UserActionBuilder, UserActionResponse } from './types'; +import type { PushedUserAction } from '../../../common/api'; +import { Actions, NONE_CONNECTOR_ID } from '../../../common/api'; +import type { UserActionBuilder, UserActionResponse } from './types'; import { createCommonUpdateUserActionBuilder } from './common'; import * as i18n from './translations'; -import { CaseServices } from '../../containers/use_get_case_user_actions'; -import { CaseExternalService } from '../../containers/types'; +import type { CaseServices } from '../../containers/use_get_case_user_actions'; +import type { CaseExternalService } from '../../containers/types'; const getPushInfo = ( caseServices: CaseServices, 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 8c455818bf910..ecc1f981829b0 100644 --- a/x-pack/plugins/cases/public/components/user_actions/schema.ts +++ b/x-pack/plugins/cases/public/components/user_actions/schema.ts @@ -5,7 +5,8 @@ * 2.0. */ -import { FIELD_TYPES, fieldValidators, FormSchema } from '../../common/shared_imports'; +import type { FormSchema } from '../../common/shared_imports'; +import { FIELD_TYPES, fieldValidators } from '../../common/shared_imports'; import * as i18n from '../../common/translations'; const { emptyField } = fieldValidators; diff --git a/x-pack/plugins/cases/public/components/user_actions/settings.test.tsx b/x-pack/plugins/cases/public/components/user_actions/settings.test.tsx index 12960e8293edc..79f06edcb91b9 100644 --- a/x-pack/plugins/cases/public/components/user_actions/settings.test.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/settings.test.tsx @@ -8,7 +8,8 @@ import { EuiCommentList } from '@elastic/eui'; import React from 'react'; import { Actions } from '../../../common/api'; -import { AppMockRenderer, createAppMockRenderer } from '../../common/mock'; +import type { AppMockRenderer } from '../../common/mock'; +import { createAppMockRenderer } from '../../common/mock'; import { getUserAction } from '../../containers/mock'; import { getMockBuilderArgs } from './mock'; import { createSettingsUserActionBuilder } from './settings'; diff --git a/x-pack/plugins/cases/public/components/user_actions/settings.tsx b/x-pack/plugins/cases/public/components/user_actions/settings.tsx index be64b223e369b..5d81078bf4c76 100644 --- a/x-pack/plugins/cases/public/components/user_actions/settings.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/settings.tsx @@ -5,9 +5,9 @@ * 2.0. */ -import { ReactNode } from 'react'; -import { SettingsUserAction } from '../../../common/api'; -import { UserActionBuilder, UserActionResponse } from './types'; +import type { ReactNode } from 'react'; +import type { SettingsUserAction } from '../../../common/api'; +import type { UserActionBuilder, UserActionResponse } from './types'; import { createCommonUpdateUserActionBuilder } from './common'; import { DISABLED_SETTING, ENABLED_SETTING, SYNC_ALERTS_LC } from './translations'; diff --git a/x-pack/plugins/cases/public/components/user_actions/severity.test.tsx b/x-pack/plugins/cases/public/components/user_actions/severity.test.tsx index d92a5cb5a153d..0107b86660826 100644 --- a/x-pack/plugins/cases/public/components/user_actions/severity.test.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/severity.test.tsx @@ -8,7 +8,8 @@ import { EuiCommentList } from '@elastic/eui'; import { Actions, CaseSeverity } from '../../../common/api'; import React from 'react'; -import { AppMockRenderer, createAppMockRenderer } from '../../common/mock'; +import type { AppMockRenderer } from '../../common/mock'; +import { createAppMockRenderer } from '../../common/mock'; import { getUserAction } from '../../containers/mock'; import { getMockBuilderArgs } from './mock'; import { createSeverityUserActionBuilder } from './severity'; diff --git a/x-pack/plugins/cases/public/components/user_actions/severity.tsx b/x-pack/plugins/cases/public/components/user_actions/severity.tsx index e2aa8d8a59b43..3878e046adb61 100644 --- a/x-pack/plugins/cases/public/components/user_actions/severity.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/severity.tsx @@ -7,10 +7,10 @@ import { EuiFlexGroup, EuiFlexItem, EuiHealth } from '@elastic/eui'; import React from 'react'; -import { SeverityUserAction } from '../../../common/api/cases/user_actions/severity'; +import type { SeverityUserAction } from '../../../common/api/cases/user_actions/severity'; import { SET_SEVERITY_TO } from '../create/translations'; import { createCommonUpdateUserActionBuilder } from './common'; -import { UserActionBuilder, UserActionResponse } from './types'; +import type { UserActionBuilder, UserActionResponse } from './types'; import { severities } from '../severity/config'; const getLabelTitle = (userAction: UserActionResponse) => { diff --git a/x-pack/plugins/cases/public/components/user_actions/status.tsx b/x-pack/plugins/cases/public/components/user_actions/status.tsx index 362fd8e3a05aa..a1c8e2210b322 100644 --- a/x-pack/plugins/cases/public/components/user_actions/status.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/status.tsx @@ -7,10 +7,11 @@ import React from 'react'; import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; -import { CaseStatuses, StatusUserAction } from '../../../common/api'; -import { UserActionBuilder, UserActionResponse } from './types'; +import { Status } from '@kbn/cases-components'; +import type { CaseStatuses, StatusUserAction } from '../../../common/api'; +import type { UserActionBuilder, UserActionResponse } from './types'; import { createCommonUpdateUserActionBuilder } from './common'; -import { Status, statuses } from '../status'; +import { statuses } from '../status'; import * as i18n from './translations'; const isStatusValid = (status: string): status is CaseStatuses => @@ -28,7 +29,7 @@ const getLabelTitle = (userAction: UserActionResponse) => { > {i18n.MARKED_CASE_AS} - + ); diff --git a/x-pack/plugins/cases/public/components/user_actions/tags.tsx b/x-pack/plugins/cases/public/components/user_actions/tags.tsx index 0cff9123ec7f7..bbcad0e8486f5 100644 --- a/x-pack/plugins/cases/public/components/user_actions/tags.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/tags.tsx @@ -8,8 +8,9 @@ import React from 'react'; import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; -import { Actions, TagsUserAction } from '../../../common/api'; -import { UserActionBuilder, UserActionResponse } from './types'; +import type { TagsUserAction } from '../../../common/api'; +import { Actions } from '../../../common/api'; +import type { UserActionBuilder, UserActionResponse } from './types'; import { createCommonUpdateUserActionBuilder } from './common'; import { Tags } from '../tags/tags'; import * as i18n from './translations'; diff --git a/x-pack/plugins/cases/public/components/user_actions/timestamp.test.tsx b/x-pack/plugins/cases/public/components/user_actions/timestamp.test.tsx index d380f246566e9..979366922e616 100644 --- a/x-pack/plugins/cases/public/components/user_actions/timestamp.test.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/timestamp.test.tsx @@ -6,7 +6,8 @@ */ import React from 'react'; -import { mount, ReactWrapper } from 'enzyme'; +import type { ReactWrapper } from 'enzyme'; +import { mount } from 'enzyme'; import { TestProviders } from '../../common/mock'; import { UserActionTimestamp } from './timestamp'; diff --git a/x-pack/plugins/cases/public/components/user_actions/title.tsx b/x-pack/plugins/cases/public/components/user_actions/title.tsx index bff9c28f8c2c6..c495aa0372f21 100644 --- a/x-pack/plugins/cases/public/components/user_actions/title.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/title.tsx @@ -5,8 +5,8 @@ * 2.0. */ -import { TitleUserAction } from '../../../common/api'; -import { UserActionBuilder, UserActionResponse } from './types'; +import type { TitleUserAction } from '../../../common/api'; +import type { UserActionBuilder, UserActionResponse } from './types'; import { createCommonUpdateUserActionBuilder } from './common'; import * as i18n from './translations'; diff --git a/x-pack/plugins/cases/public/components/user_actions/types.ts b/x-pack/plugins/cases/public/components/user_actions/types.ts index 7477e6df8d5dc..978de436b377e 100644 --- a/x-pack/plugins/cases/public/components/user_actions/types.ts +++ b/x-pack/plugins/cases/public/components/user_actions/types.ts @@ -5,20 +5,20 @@ * 2.0. */ -import { EuiCommentProps } from '@elastic/eui'; -import { UserProfileWithAvatar } from '@kbn/user-profile-components'; -import { SnakeToCamelCase } from '../../../common/types'; -import { ActionTypes, UserActionWithResponse } from '../../../common/api'; -import { Case, CaseUserActions, Comment, UseFetchAlertData } from '../../containers/types'; -import { CaseServices } from '../../containers/use_get_case_user_actions'; -import { AddCommentRefObject } from '../add_comment'; -import { UserActionMarkdownRefObject } from './markdown_form'; -import { CasesNavigation } from '../links'; -import { UNSUPPORTED_ACTION_TYPES } from './constants'; +import type { EuiCommentProps } from '@elastic/eui'; +import type { UserProfileWithAvatar } from '@kbn/user-profile-components'; +import type { SnakeToCamelCase } from '../../../common/types'; +import type { ActionTypes, UserActionWithResponse } from '../../../common/api'; +import type { Case, CaseUserActions, Comment, UseFetchAlertData } from '../../containers/types'; +import type { CaseServices } from '../../containers/use_get_case_user_actions'; +import type { AddCommentRefObject } from '../add_comment'; +import type { UserActionMarkdownRefObject } from './markdown_form'; +import type { CasesNavigation } from '../links'; +import type { UNSUPPORTED_ACTION_TYPES } from './constants'; import type { OnUpdateFields } from '../case_view/types'; -import { ExternalReferenceAttachmentTypeRegistry } from '../../client/attachment_framework/external_reference_registry'; -import { PersistableStateAttachmentTypeRegistry } from '../../client/attachment_framework/persistable_state_registry'; -import { CurrentUserProfile } from '../types'; +import type { ExternalReferenceAttachmentTypeRegistry } from '../../client/attachment_framework/external_reference_registry'; +import type { PersistableStateAttachmentTypeRegistry } from '../../client/attachment_framework/persistable_state_registry'; +import type { CurrentUserProfile } from '../types'; export interface UserActionTreeProps { caseServices: CaseServices; diff --git a/x-pack/plugins/cases/public/components/user_actions/use_user_actions_handler.tsx b/x-pack/plugins/cases/public/components/user_actions/use_user_actions_handler.tsx index 5dfc84008e045..2b80426e26e93 100644 --- a/x-pack/plugins/cases/public/components/user_actions/use_user_actions_handler.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/use_user_actions_handler.tsx @@ -7,12 +7,12 @@ import { useCallback, useEffect, useRef, useState } from 'react'; import { useCaseViewParams } from '../../common/navigation'; -import { Case } from '../../containers/types'; +import type { Case } from '../../containers/types'; import { useLensDraftComment } from '../markdown_editor/plugins/lens/use_lens_draft_comment'; import { useUpdateComment } from '../../containers/use_update_comment'; -import { AddCommentRefObject } from '../add_comment'; -import { UserActionMarkdownRefObject } from './markdown_form'; -import { UserActionBuilderArgs } from './types'; +import type { AddCommentRefObject } from '../add_comment'; +import type { UserActionMarkdownRefObject } from './markdown_form'; +import type { UserActionBuilderArgs } from './types'; import { NEW_COMMENT_ID } from './constants'; import { useDeleteComment } from '../../containers/use_delete_comment'; import { useRefreshCaseViewPage } from '../case_view/use_on_refresh_case_view_page'; diff --git a/x-pack/plugins/cases/public/components/user_profiles/data_test_subject.ts b/x-pack/plugins/cases/public/components/user_profiles/data_test_subject.ts index 23d952738aa4d..9247368b1da17 100644 --- a/x-pack/plugins/cases/public/components/user_profiles/data_test_subject.ts +++ b/x-pack/plugins/cases/public/components/user_profiles/data_test_subject.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { Assignee } from './types'; +import type { Assignee } from './types'; export const getUsernameDataTestSubj = (assignee: Assignee) => { return assignee.profile?.user.username ?? assignee.uid; diff --git a/x-pack/plugins/cases/public/components/user_profiles/display_name.ts b/x-pack/plugins/cases/public/components/user_profiles/display_name.ts index 4abd9f276abaa..9eb19b45d3404 100644 --- a/x-pack/plugins/cases/public/components/user_profiles/display_name.ts +++ b/x-pack/plugins/cases/public/components/user_profiles/display_name.ts @@ -5,7 +5,8 @@ * 2.0. */ -import { getUserDisplayName, UserProfileUserInfo } from '@kbn/user-profile-components'; +import type { UserProfileUserInfo } from '@kbn/user-profile-components'; +import { getUserDisplayName } from '@kbn/user-profile-components'; import { isEmpty } from 'lodash'; import * as i18n from './translations'; diff --git a/x-pack/plugins/cases/public/components/user_profiles/hoverable_avatar.tsx b/x-pack/plugins/cases/public/components/user_profiles/hoverable_avatar.tsx index 3b0b2ac4e98ae..7d9ba1b95b5a2 100644 --- a/x-pack/plugins/cases/public/components/user_profiles/hoverable_avatar.tsx +++ b/x-pack/plugins/cases/public/components/user_profiles/hoverable_avatar.tsx @@ -6,7 +6,7 @@ */ import React from 'react'; -import { UserInfoWithAvatar } from './types'; +import type { UserInfoWithAvatar } from './types'; import { CaseUserAvatar } from './user_avatar'; import { UserToolTip } from './user_tooltip'; diff --git a/x-pack/plugins/cases/public/components/user_profiles/hoverable_avatar_resolver.test.tsx b/x-pack/plugins/cases/public/components/user_profiles/hoverable_avatar_resolver.test.tsx index 43e22b26e3c22..3bce497caf716 100644 --- a/x-pack/plugins/cases/public/components/user_profiles/hoverable_avatar_resolver.test.tsx +++ b/x-pack/plugins/cases/public/components/user_profiles/hoverable_avatar_resolver.test.tsx @@ -7,7 +7,7 @@ import { fireEvent, render, screen, waitFor } from '@testing-library/react'; import React from 'react'; -import { ElasticUser } from '../../containers/types'; +import type { ElasticUser } from '../../containers/types'; import { userProfiles, userProfilesMap } from '../../containers/user_profiles/api.mock'; import { HoverableAvatarResolver } from './hoverable_avatar_resolver'; diff --git a/x-pack/plugins/cases/public/components/user_profiles/hoverable_avatar_resolver.tsx b/x-pack/plugins/cases/public/components/user_profiles/hoverable_avatar_resolver.tsx index 49dada0a2e5bd..37fb44b0c889c 100644 --- a/x-pack/plugins/cases/public/components/user_profiles/hoverable_avatar_resolver.tsx +++ b/x-pack/plugins/cases/public/components/user_profiles/hoverable_avatar_resolver.tsx @@ -5,9 +5,9 @@ * 2.0. */ -import { UserProfileWithAvatar } from '@kbn/user-profile-components'; +import type { UserProfileWithAvatar } from '@kbn/user-profile-components'; import React from 'react'; -import { ElasticUser } from '../../containers/types'; +import type { ElasticUser } from '../../containers/types'; import { convertToUserInfo } from './user_converter'; import { HoverableAvatar } from './hoverable_avatar'; diff --git a/x-pack/plugins/cases/public/components/user_profiles/hoverable_user_with_avatar.tsx b/x-pack/plugins/cases/public/components/user_profiles/hoverable_user_with_avatar.tsx index 3753b6cb00e15..d3cf70a7534cf 100644 --- a/x-pack/plugins/cases/public/components/user_profiles/hoverable_user_with_avatar.tsx +++ b/x-pack/plugins/cases/public/components/user_profiles/hoverable_user_with_avatar.tsx @@ -9,7 +9,8 @@ import React from 'react'; import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { UserToolTip } from './user_tooltip'; import { SmallUserAvatar } from './small_user_avatar'; -import { Username, UsernameProps } from './username'; +import type { UsernameProps } from './username'; +import { Username } from './username'; export type HoverableUserWithAvatarProps = UsernameProps; diff --git a/x-pack/plugins/cases/public/components/user_profiles/hoverable_user_with_avatar_resolver.test.tsx b/x-pack/plugins/cases/public/components/user_profiles/hoverable_user_with_avatar_resolver.test.tsx index 38eecedea0361..a65e2a3d9c866 100644 --- a/x-pack/plugins/cases/public/components/user_profiles/hoverable_user_with_avatar_resolver.test.tsx +++ b/x-pack/plugins/cases/public/components/user_profiles/hoverable_user_with_avatar_resolver.test.tsx @@ -7,7 +7,7 @@ import { render, screen } from '@testing-library/react'; import React from 'react'; -import { ElasticUser } from '../../containers/types'; +import type { ElasticUser } from '../../containers/types'; import { userProfiles, userProfilesMap } from '../../containers/user_profiles/api.mock'; import { HoverableUserWithAvatarResolver } from './hoverable_user_with_avatar_resolver'; diff --git a/x-pack/plugins/cases/public/components/user_profiles/hoverable_user_with_avatar_resolver.tsx b/x-pack/plugins/cases/public/components/user_profiles/hoverable_user_with_avatar_resolver.tsx index b414e10c2f6a4..a0f2fdf8c5ab4 100644 --- a/x-pack/plugins/cases/public/components/user_profiles/hoverable_user_with_avatar_resolver.tsx +++ b/x-pack/plugins/cases/public/components/user_profiles/hoverable_user_with_avatar_resolver.tsx @@ -5,13 +5,11 @@ * 2.0. */ -import { UserProfileWithAvatar } from '@kbn/user-profile-components'; +import type { UserProfileWithAvatar } from '@kbn/user-profile-components'; import React from 'react'; -import { ElasticUser } from '../../containers/types'; -import { - HoverableUserWithAvatar, - HoverableUserWithAvatarProps, -} from './hoverable_user_with_avatar'; +import type { ElasticUser } from '../../containers/types'; +import type { HoverableUserWithAvatarProps } from './hoverable_user_with_avatar'; +import { HoverableUserWithAvatar } from './hoverable_user_with_avatar'; import { convertToUserInfo } from './user_converter'; const HoverableUserWithAvatarResolverComponent: React.FC< diff --git a/x-pack/plugins/cases/public/components/user_profiles/hoverable_username_resolver.test.tsx b/x-pack/plugins/cases/public/components/user_profiles/hoverable_username_resolver.test.tsx index 562a7e0bbf5cb..aebf93d207b65 100644 --- a/x-pack/plugins/cases/public/components/user_profiles/hoverable_username_resolver.test.tsx +++ b/x-pack/plugins/cases/public/components/user_profiles/hoverable_username_resolver.test.tsx @@ -7,7 +7,7 @@ import { render, screen } from '@testing-library/react'; import React from 'react'; -import { ElasticUser } from '../../containers/types'; +import type { ElasticUser } from '../../containers/types'; import { userProfiles, userProfilesMap } from '../../containers/user_profiles/api.mock'; import { HoverableUsernameResolver } from './hoverable_username_resolver'; diff --git a/x-pack/plugins/cases/public/components/user_profiles/hoverable_username_resolver.tsx b/x-pack/plugins/cases/public/components/user_profiles/hoverable_username_resolver.tsx index 67d0c48b591c2..bc980bbffbe4a 100644 --- a/x-pack/plugins/cases/public/components/user_profiles/hoverable_username_resolver.tsx +++ b/x-pack/plugins/cases/public/components/user_profiles/hoverable_username_resolver.tsx @@ -5,10 +5,10 @@ * 2.0. */ -import { UserProfileWithAvatar } from '@kbn/user-profile-components'; +import type { UserProfileWithAvatar } from '@kbn/user-profile-components'; import React from 'react'; -import { ElasticUser } from '../../containers/types'; -import { HoverableUserWithAvatarProps } from './hoverable_user_with_avatar'; +import type { ElasticUser } from '../../containers/types'; +import type { HoverableUserWithAvatarProps } from './hoverable_user_with_avatar'; import { Username } from './username'; import { convertToUserInfo } from './user_converter'; import { UserToolTip } from './user_tooltip'; diff --git a/x-pack/plugins/cases/public/components/user_profiles/removable_user.test.tsx b/x-pack/plugins/cases/public/components/user_profiles/removable_user.test.tsx index 1db9df25a80d7..e94a78fdbaab3 100644 --- a/x-pack/plugins/cases/public/components/user_profiles/removable_user.test.tsx +++ b/x-pack/plugins/cases/public/components/user_profiles/removable_user.test.tsx @@ -7,13 +7,11 @@ import React from 'react'; import { fireEvent, screen } from '@testing-library/react'; -import { RemovableUser, UserRepresentationProps } from './removable_user'; +import type { UserRepresentationProps } from './removable_user'; +import { RemovableUser } from './removable_user'; import { userProfiles } from '../../containers/user_profiles/api.mock'; -import { - AppMockRenderer, - createAppMockRenderer, - noUpdateCasesPermissions, -} from '../../common/mock'; +import type { AppMockRenderer } from '../../common/mock'; +import { createAppMockRenderer, noUpdateCasesPermissions } from '../../common/mock'; describe('UserRepresentation', () => { const dataTestSubjGroup = `user-profile-assigned-user-group-${userProfiles[0].user.username}`; diff --git a/x-pack/plugins/cases/public/components/user_profiles/removable_user.tsx b/x-pack/plugins/cases/public/components/user_profiles/removable_user.tsx index 286fe9b8c3d47..72ee046e8936e 100644 --- a/x-pack/plugins/cases/public/components/user_profiles/removable_user.tsx +++ b/x-pack/plugins/cases/public/components/user_profiles/removable_user.tsx @@ -8,7 +8,7 @@ import React, { useCallback, useState } from 'react'; import { EuiButtonIcon, EuiFlexGroup, EuiFlexItem, EuiToolTip } from '@elastic/eui'; import * as i18n from './translations'; -import { Assignee } from './types'; +import type { Assignee } from './types'; import { HoverableUserWithAvatar } from './hoverable_user_with_avatar'; import { useCasesContext } from '../cases_context/use_cases_context'; diff --git a/x-pack/plugins/cases/public/components/user_profiles/small_user_avatar.tsx b/x-pack/plugins/cases/public/components/user_profiles/small_user_avatar.tsx index 43fead044bda3..b5a50afc1bde0 100644 --- a/x-pack/plugins/cases/public/components/user_profiles/small_user_avatar.tsx +++ b/x-pack/plugins/cases/public/components/user_profiles/small_user_avatar.tsx @@ -6,7 +6,8 @@ */ import React from 'react'; -import { CaseUserAvatar, CaseUserAvatarProps } from './user_avatar'; +import type { CaseUserAvatarProps } from './user_avatar'; +import { CaseUserAvatar } from './user_avatar'; const SmallUserAvatarComponent: React.FC> = ({ userInfo, diff --git a/x-pack/plugins/cases/public/components/user_profiles/sort.ts b/x-pack/plugins/cases/public/components/user_profiles/sort.ts index e1e8018a21e35..83a4608095b0b 100644 --- a/x-pack/plugins/cases/public/components/user_profiles/sort.ts +++ b/x-pack/plugins/cases/public/components/user_profiles/sort.ts @@ -5,9 +5,9 @@ * 2.0. */ -import { UserProfileWithAvatar } from '@kbn/user-profile-components'; +import type { UserProfileWithAvatar } from '@kbn/user-profile-components'; import { sortBy } from 'lodash'; -import { CurrentUserProfile } from '../types'; +import type { CurrentUserProfile } from '../types'; export const getSortField = (profile: UserProfileWithAvatar) => profile.user.full_name?.toLowerCase() ?? diff --git a/x-pack/plugins/cases/public/components/user_profiles/types.ts b/x-pack/plugins/cases/public/components/user_profiles/types.ts index a4de60b78aae5..2d2384d21b67b 100644 --- a/x-pack/plugins/cases/public/components/user_profiles/types.ts +++ b/x-pack/plugins/cases/public/components/user_profiles/types.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { UserProfileWithAvatar } from '@kbn/user-profile-components'; +import type { UserProfileWithAvatar } from '@kbn/user-profile-components'; export interface Assignee { uid: string; diff --git a/x-pack/plugins/cases/public/components/user_profiles/unknown_user.tsx b/x-pack/plugins/cases/public/components/user_profiles/unknown_user.tsx index b98eef9efbd9f..8a51e558cc4e8 100644 --- a/x-pack/plugins/cases/public/components/user_profiles/unknown_user.tsx +++ b/x-pack/plugins/cases/public/components/user_profiles/unknown_user.tsx @@ -7,7 +7,8 @@ import React from 'react'; -import { UserAvatar, UserAvatarProps } from '@kbn/user-profile-components'; +import type { UserAvatarProps } from '@kbn/user-profile-components'; +import { UserAvatar } from '@kbn/user-profile-components'; interface CaseUnknownUserAvatarProps { size: UserAvatarProps['size']; diff --git a/x-pack/plugins/cases/public/components/user_profiles/user_avatar.test.tsx b/x-pack/plugins/cases/public/components/user_profiles/user_avatar.test.tsx index 8ccd8a2ced6d3..b253858a290c1 100644 --- a/x-pack/plugins/cases/public/components/user_profiles/user_avatar.test.tsx +++ b/x-pack/plugins/cases/public/components/user_profiles/user_avatar.test.tsx @@ -7,10 +7,11 @@ import React from 'react'; import { screen } from '@testing-library/react'; -import { AppMockRenderer, createAppMockRenderer } from '../../common/mock'; +import type { AppMockRenderer } from '../../common/mock'; +import { createAppMockRenderer } from '../../common/mock'; import { userProfiles } from '../../containers/user_profiles/api.mock'; import { CaseUserAvatar } from './user_avatar'; -import { UserInfoWithAvatar } from './types'; +import type { UserInfoWithAvatar } from './types'; describe('CaseUserAvatar', () => { let appMockRender: AppMockRenderer; diff --git a/x-pack/plugins/cases/public/components/user_profiles/user_avatar.tsx b/x-pack/plugins/cases/public/components/user_profiles/user_avatar.tsx index abca77a4108e7..1eea00dcb08f7 100644 --- a/x-pack/plugins/cases/public/components/user_profiles/user_avatar.tsx +++ b/x-pack/plugins/cases/public/components/user_profiles/user_avatar.tsx @@ -7,9 +7,10 @@ import React from 'react'; -import { UserAvatar, UserAvatarProps } from '@kbn/user-profile-components'; +import type { UserAvatarProps } from '@kbn/user-profile-components'; +import { UserAvatar } from '@kbn/user-profile-components'; import { CaseUnknownUserAvatar } from './unknown_user'; -import { UserInfoWithAvatar } from './types'; +import type { UserInfoWithAvatar } from './types'; export interface CaseUserAvatarProps { size: UserAvatarProps['size']; diff --git a/x-pack/plugins/cases/public/components/user_profiles/user_converter.ts b/x-pack/plugins/cases/public/components/user_profiles/user_converter.ts index b325d4f88aa93..716b74a90aad5 100644 --- a/x-pack/plugins/cases/public/components/user_profiles/user_converter.ts +++ b/x-pack/plugins/cases/public/components/user_profiles/user_converter.ts @@ -5,10 +5,10 @@ * 2.0. */ -import { UserProfileWithAvatar } from '@kbn/user-profile-components'; +import type { UserProfileWithAvatar } from '@kbn/user-profile-components'; import { isEmpty } from 'lodash'; -import { ElasticUser } from '../../containers/types'; -import { UserInfoWithAvatar } from './types'; +import type { ElasticUser } from '../../containers/types'; +import type { UserInfoWithAvatar } from './types'; export const convertToUserInfo = ( user: ElasticUser, diff --git a/x-pack/plugins/cases/public/components/user_profiles/user_tooltip.test.tsx b/x-pack/plugins/cases/public/components/user_profiles/user_tooltip.test.tsx index ded2808533ee4..d105cc1db0053 100644 --- a/x-pack/plugins/cases/public/components/user_profiles/user_tooltip.test.tsx +++ b/x-pack/plugins/cases/public/components/user_profiles/user_tooltip.test.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import { UserProfileWithAvatar } from '@kbn/user-profile-components'; +import type { UserProfileWithAvatar } from '@kbn/user-profile-components'; import { render, screen, fireEvent, waitFor } from '@testing-library/react'; import React from 'react'; import { UserToolTip } from './user_tooltip'; diff --git a/x-pack/plugins/cases/public/components/user_profiles/user_tooltip.tsx b/x-pack/plugins/cases/public/components/user_profiles/user_tooltip.tsx index a171e4ddd084a..6b9549fe4d618 100644 --- a/x-pack/plugins/cases/public/components/user_profiles/user_tooltip.tsx +++ b/x-pack/plugins/cases/public/components/user_profiles/user_tooltip.tsx @@ -8,11 +8,11 @@ import React from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiText, EuiToolTip } from '@elastic/eui'; -import { UserProfileUserInfo } from '@kbn/user-profile-components'; +import type { UserProfileUserInfo } from '@kbn/user-profile-components'; import { CaseUserAvatar } from './user_avatar'; import { getName } from './display_name'; import * as i18n from './translations'; -import { UserInfoWithAvatar } from './types'; +import type { UserInfoWithAvatar } from './types'; const UserFullInformation: React.FC<{ userInfo?: UserInfoWithAvatar }> = React.memo( ({ userInfo }) => { diff --git a/x-pack/plugins/cases/public/components/user_profiles/username.tsx b/x-pack/plugins/cases/public/components/user_profiles/username.tsx index 17e54c8e0460d..41c694e530b6e 100644 --- a/x-pack/plugins/cases/public/components/user_profiles/username.tsx +++ b/x-pack/plugins/cases/public/components/user_profiles/username.tsx @@ -8,7 +8,7 @@ import { EuiText } from '@elastic/eui'; import React from 'react'; import { getName } from './display_name'; -import { UserInfoWithAvatar } from './types'; +import type { UserInfoWithAvatar } from './types'; export interface UsernameProps { userInfo?: UserInfoWithAvatar; diff --git a/x-pack/plugins/cases/public/components/utils.ts b/x-pack/plugins/cases/public/components/utils.ts index 403f55574f9a6..45b2247b7bcac 100644 --- a/x-pack/plugins/cases/public/components/utils.ts +++ b/x-pack/plugins/cases/public/components/utils.ts @@ -5,12 +5,12 @@ * 2.0. */ -import { IconType } from '@elastic/eui'; +import type { IconType } from '@elastic/eui'; import { ConnectorTypes } from '../../common/api'; -import { FieldConfig, ValidationConfig } from '../common/shared_imports'; -import { CasesPluginStart } from '../types'; +import type { FieldConfig, ValidationConfig } from '../common/shared_imports'; +import type { CasesPluginStart } from '../types'; import { connectorValidator as swimlaneConnectorValidator } from './connectors/swimlane/validator'; -import { CaseActionConnector } from './types'; +import type { CaseActionConnector } from './types'; export const getConnectorById = ( id: string, diff --git a/x-pack/plugins/cases/public/containers/__mocks__/api.ts b/x-pack/plugins/cases/public/containers/__mocks__/api.ts index d01f927d3c324..f16c0260533a7 100644 --- a/x-pack/plugins/cases/public/containers/__mocks__/api.ts +++ b/x-pack/plugins/cases/public/containers/__mocks__/api.ts @@ -5,15 +5,15 @@ * 2.0. */ -import { +import type { ActionLicense, Cases, Case, CasesStatus, CaseUserActions, FetchCasesProps, - SortFieldCase, } from '../types'; +import { SortFieldCase } from '../types'; import { actionLicenses, allCases, @@ -27,16 +27,17 @@ import { pushedCase, tags, } from '../mock'; -import { CaseUpdateRequest, ResolvedCase, SeverityAll } from '../../../common/ui/types'; -import { +import type { CaseUpdateRequest, ResolvedCase } from '../../../common/ui/types'; +import { SeverityAll } from '../../../common/ui/types'; +import type { CasePatchRequest, CasePostRequest, CommentRequest, - CaseStatuses, SingleCaseMetricsResponse, } from '../../../common/api'; +import { CaseStatuses } from '../../../common/api'; import type { ValidFeatureId } from '@kbn/rule-data-utils'; -import { UserProfile } from '@kbn/security-plugin/common'; +import type { UserProfile } from '@kbn/security-plugin/common'; import { userProfiles } from '../user_profiles/api.mock'; export const getCase = async ( diff --git a/x-pack/plugins/cases/public/containers/api.ts b/x-pack/plugins/cases/public/containers/api.ts index ff8d05ef653d9..4ce79cf6d22d5 100644 --- a/x-pack/plugins/cases/public/containers/api.ts +++ b/x-pack/plugins/cases/public/containers/api.ts @@ -8,16 +8,14 @@ import type { ValidFeatureId } from '@kbn/rule-data-utils'; import { BASE_RAC_ALERTS_API_PATH } from '@kbn/rule-registry-plugin/common/constants'; import { isEmpty } from 'lodash'; -import { +import type { Cases, CaseUpdateRequest, FetchCasesProps, ResolvedCase, - SeverityAll, - SortFieldCase, - StatusAll, } from '../../common/ui/types'; -import { +import { SeverityAll, SortFieldCase, StatusAll } from '../../common/ui/types'; +import type { BulkCreateCommentRequest, CasePatchRequest, CasePostRequest, @@ -26,16 +24,18 @@ import { CasesResponse, CaseUserActionsResponse, CommentRequest, + User, + SingleCaseMetricsResponse, + CasesFindResponse, +} from '../../common/api'; +import { CommentType, getCaseCommentsUrl, getCaseDetailsUrl, getCaseDetailsMetricsUrl, getCasePushUrl, getCaseUserActionUrl, - User, getCaseCommentDeleteUrl, - SingleCaseMetricsResponse, - CasesFindResponse, } from '../../common/api'; import { CASE_REPORTERS_URL, @@ -57,7 +57,7 @@ import { convertCaseResolveToCamelCase, } from '../api/utils'; -import { +import type { ActionLicense, Case, SingleCaseMetrics, diff --git a/x-pack/plugins/cases/public/containers/configure/__mocks__/api.ts b/x-pack/plugins/cases/public/containers/configure/__mocks__/api.ts index b24213cc43af7..0d85e75478be3 100644 --- a/x-pack/plugins/cases/public/containers/configure/__mocks__/api.ts +++ b/x-pack/plugins/cases/public/containers/configure/__mocks__/api.ts @@ -5,15 +5,15 @@ * 2.0. */ -import { +import type { CasesConfigurePatch, CasesConfigureRequest, ActionConnector, ActionTypeConnector, } from '../../../../common/api'; -import { ApiProps } from '../../types'; -import { CaseConfigure } from '../types'; +import type { ApiProps } from '../../types'; +import type { CaseConfigure } from '../types'; import { caseConfigurationCamelCaseResponseMock } from '../mock'; import { actionTypesMock, connectorsMock } from '../../../common/mock/connectors'; diff --git a/x-pack/plugins/cases/public/containers/configure/api.ts b/x-pack/plugins/cases/public/containers/configure/api.ts index b9d0b219c91ca..72702e27fbb56 100644 --- a/x-pack/plugins/cases/public/containers/configure/api.ts +++ b/x-pack/plugins/cases/public/containers/configure/api.ts @@ -8,21 +8,21 @@ import { isEmpty } from 'lodash/fp'; import { CasesConnectorFeatureId } from '@kbn/actions-plugin/common'; import { getAllConnectorTypesUrl } from '../../../common/utils/connectors_api'; -import { +import type { ActionConnector, ActionTypeConnector, CasesConfigurePatch, CasesConfigureRequest, CasesConfigureResponse, CasesConfigurationsResponse, - getCaseConfigurationDetailsUrl, } from '../../../common/api'; +import { getCaseConfigurationDetailsUrl } from '../../../common/api'; import { CASE_CONFIGURE_CONNECTORS_URL, CASE_CONFIGURE_URL } from '../../../common/constants'; import { KibanaServices } from '../../common/lib/kibana'; import { convertToCamelCase, convertArrayToCamelCase } from '../../api/utils'; -import { ApiProps } from '../types'; +import type { ApiProps } from '../types'; import { decodeCaseConfigurationsResponse, decodeCaseConfigureResponse } from '../utils'; -import { CaseConfigure } from './types'; +import type { CaseConfigure } from './types'; export const fetchConnectors = async ({ signal }: ApiProps): Promise => { const response = await KibanaServices.get().http.fetch( diff --git a/x-pack/plugins/cases/public/containers/configure/mock.ts b/x-pack/plugins/cases/public/containers/configure/mock.ts index c75d2c839534d..039f24a18fbfd 100644 --- a/x-pack/plugins/cases/public/containers/configure/mock.ts +++ b/x-pack/plugins/cases/public/containers/configure/mock.ts @@ -5,9 +5,10 @@ * 2.0. */ -import { CasesConfigureResponse, CasesConfigureRequest, ConnectorTypes } from '../../../common/api'; +import type { CasesConfigureResponse, CasesConfigureRequest } from '../../../common/api'; +import { ConnectorTypes } from '../../../common/api'; import { SECURITY_SOLUTION_OWNER } from '../../../common/constants'; -import { CaseConfigure, CaseConnectorMapping } from './types'; +import type { CaseConfigure, CaseConnectorMapping } from './types'; export const mappings: CaseConnectorMapping[] = [ { diff --git a/x-pack/plugins/cases/public/containers/configure/types.ts b/x-pack/plugins/cases/public/containers/configure/types.ts index 55401a2fbfd2c..c1e2366f6a37b 100644 --- a/x-pack/plugins/cases/public/containers/configure/types.ts +++ b/x-pack/plugins/cases/public/containers/configure/types.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { ElasticUser } from '../types'; -import { +import type { ElasticUser } from '../types'; +import type { ActionConnector, ActionTypeConnector, ActionType, diff --git a/x-pack/plugins/cases/public/containers/configure/use_action_types.test.tsx b/x-pack/plugins/cases/public/containers/configure/use_action_types.test.tsx index df0804690b1b9..9739b29a484b0 100644 --- a/x-pack/plugins/cases/public/containers/configure/use_action_types.test.tsx +++ b/x-pack/plugins/cases/public/containers/configure/use_action_types.test.tsx @@ -7,7 +7,8 @@ import { renderHook } from '@testing-library/react-hooks'; import * as api from './api'; -import { AppMockRenderer, createAppMockRenderer } from '../../common/mock'; +import type { AppMockRenderer } from '../../common/mock'; +import { createAppMockRenderer } from '../../common/mock'; import { useGetActionTypes } from './use_action_types'; import { useToasts } from '../../common/lib/kibana'; diff --git a/x-pack/plugins/cases/public/containers/configure/use_action_types.tsx b/x-pack/plugins/cases/public/containers/configure/use_action_types.tsx index 8503ccd6eddf8..4aa10bfb4918b 100644 --- a/x-pack/plugins/cases/public/containers/configure/use_action_types.tsx +++ b/x-pack/plugins/cases/public/containers/configure/use_action_types.tsx @@ -10,7 +10,7 @@ import * as i18n from '../translations'; import { fetchActionTypes } from './api'; import { useToasts } from '../../common/lib/kibana'; import { casesQueriesKeys } from '../constants'; -import { ServerError } from '../../types'; +import type { ServerError } from '../../types'; export const useGetActionTypes = () => { const toasts = useToasts(); diff --git a/x-pack/plugins/cases/public/containers/configure/use_configure.test.tsx b/x-pack/plugins/cases/public/containers/configure/use_configure.test.tsx index 1c9139b913617..ddea0187f7948 100644 --- a/x-pack/plugins/cases/public/containers/configure/use_configure.test.tsx +++ b/x-pack/plugins/cases/public/containers/configure/use_configure.test.tsx @@ -7,12 +7,8 @@ import React from 'react'; import { renderHook, act } from '@testing-library/react-hooks'; -import { - initialState, - useCaseConfigure, - ReturnUseCaseConfigure, - ConnectorConfiguration, -} from './use_configure'; +import type { ReturnUseCaseConfigure, ConnectorConfiguration } from './use_configure'; +import { initialState, useCaseConfigure } from './use_configure'; import { mappings, caseConfigurationCamelCaseResponseMock } from './mock'; import * as api from './api'; import { ConnectorTypes } from '../../../common/api'; diff --git a/x-pack/plugins/cases/public/containers/configure/use_configure.tsx b/x-pack/plugins/cases/public/containers/configure/use_configure.tsx index 21c6e9e0b388e..53c63eccc6ae5 100644 --- a/x-pack/plugins/cases/public/containers/configure/use_configure.tsx +++ b/x-pack/plugins/cases/public/containers/configure/use_configure.tsx @@ -9,7 +9,7 @@ import { useEffect, useCallback, useReducer, useRef } from 'react'; import { getCaseConfigure, patchCaseConfigure, postCaseConfigure } from './api'; import * as i18n from './translations'; -import { ClosureType, CaseConfigure, CaseConnector, CaseConnectorMapping } from './types'; +import type { ClosureType, CaseConfigure, CaseConnector, CaseConnectorMapping } from './types'; import { ConnectorTypes } from '../../../common/api'; import { useToasts } from '../../common/lib/kibana'; import { useCasesContext } from '../../components/cases_context/use_cases_context'; diff --git a/x-pack/plugins/cases/public/containers/configure/use_connectors.tsx b/x-pack/plugins/cases/public/containers/configure/use_connectors.tsx index 5e96dd86ae985..f9c19ee1776bd 100644 --- a/x-pack/plugins/cases/public/containers/configure/use_connectors.tsx +++ b/x-pack/plugins/cases/public/containers/configure/use_connectors.tsx @@ -10,7 +10,7 @@ import { fetchConnectors } from './api'; import { useApplicationCapabilities, useToasts } from '../../common/lib/kibana'; import * as i18n from './translations'; import { casesQueriesKeys } from '../constants'; -import { ServerError } from '../../types'; +import type { ServerError } from '../../types'; export function useGetConnectors() { const toasts = useToasts(); diff --git a/x-pack/plugins/cases/public/containers/constants.ts b/x-pack/plugins/cases/public/containers/constants.ts index a6acbbd68d412..f6b69fbac920a 100644 --- a/x-pack/plugins/cases/public/containers/constants.ts +++ b/x-pack/plugins/cases/public/containers/constants.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { SingleCaseMetricsFeature } from './types'; +import type { SingleCaseMetricsFeature } from './types'; export const DEFAULT_TABLE_ACTIVE_PAGE = 1; export const DEFAULT_TABLE_LIMIT = 5; diff --git a/x-pack/plugins/cases/public/containers/mock.ts b/x-pack/plugins/cases/public/containers/mock.ts index b7f1ab268a034..cada10b9eb109 100644 --- a/x-pack/plugins/cases/public/containers/mock.ts +++ b/x-pack/plugins/cases/public/containers/mock.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { ActionLicense, Cases, Case, CasesStatus, CaseUserActions, Comment } from './types'; +import type { ActionLicense, Cases, Case, CasesStatus, CaseUserActions, Comment } from './types'; import type { ResolvedCase, @@ -16,31 +16,33 @@ import type { ExternalReferenceComment, PersistableComment, } from '../../common/ui/types'; -import { - Actions, - ActionTypes, +import type { CaseConnector, CaseResponse, CasesFindResponse, CasesResponse, CasesStatusResponse, - CaseStatuses, CaseUserActionResponse, CaseUserActionsResponse, CommentResponse, - CommentType, - ConnectorTypes, UserAction, UserActionTypes, UserActionWithResponse, CommentUserAction, +} from '../../common/api'; +import { + Actions, + ActionTypes, + CaseStatuses, + CommentType, + ConnectorTypes, CaseSeverity, ExternalReferenceStorageType, } from '../../common/api'; import { SECURITY_SOLUTION_OWNER } from '../../common/constants'; -import { SnakeToCamelCase } from '../../common/types'; +import type { SnakeToCamelCase } from '../../common/types'; import { covertToSnakeCase } from './utils'; -import { +import type { ExternalReferenceAttachmentType, AttachmentViewObject, PersistableStateAttachmentType, diff --git a/x-pack/plugins/cases/public/containers/use_bulk_update_case.test.tsx b/x-pack/plugins/cases/public/containers/use_bulk_update_case.test.tsx index d46f79569622f..be89dc92f9d06 100644 --- a/x-pack/plugins/cases/public/containers/use_bulk_update_case.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_bulk_update_case.test.tsx @@ -10,7 +10,8 @@ import { useUpdateCases } from './use_bulk_update_case'; import { allCases } from './mock'; import { useToasts } from '../common/lib/kibana'; import * as api from './api'; -import { createAppMockRenderer, AppMockRenderer } from '../common/mock'; +import type { AppMockRenderer } from '../common/mock'; +import { createAppMockRenderer } from '../common/mock'; import { casesQueriesKeys } from './constants'; jest.mock('./api'); diff --git a/x-pack/plugins/cases/public/containers/use_bulk_update_case.tsx b/x-pack/plugins/cases/public/containers/use_bulk_update_case.tsx index e0866bf0166a6..85a5a743d16d3 100644 --- a/x-pack/plugins/cases/public/containers/use_bulk_update_case.tsx +++ b/x-pack/plugins/cases/public/containers/use_bulk_update_case.tsx @@ -8,9 +8,9 @@ import { useQueryClient, useMutation } from '@tanstack/react-query'; import * as i18n from './translations'; import { updateCases } from './api'; -import { CaseUpdateRequest } from './types'; +import type { CaseUpdateRequest } from './types'; import { useCasesToast } from '../common/use_cases_toast'; -import { ServerError } from '../types'; +import type { ServerError } from '../types'; import { casesQueriesKeys, casesMutationsKeys } from './constants'; interface MutationArgs { diff --git a/x-pack/plugins/cases/public/containers/use_create_attachments.test.tsx b/x-pack/plugins/cases/public/containers/use_create_attachments.test.tsx index 7a4b1c7f6523a..59119e0b6f7e4 100644 --- a/x-pack/plugins/cases/public/containers/use_create_attachments.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_create_attachments.test.tsx @@ -9,7 +9,8 @@ import { renderHook, act } from '@testing-library/react-hooks'; import { CommentType } from '../../common/api'; import { SECURITY_SOLUTION_OWNER } from '../../common/constants'; -import { useCreateAttachments, UseCreateAttachments } from './use_create_attachments'; +import type { UseCreateAttachments } from './use_create_attachments'; +import { useCreateAttachments } from './use_create_attachments'; import { basicCaseId } from './mock'; import * as api from './api'; import { useToasts } from '../common/lib/kibana'; diff --git a/x-pack/plugins/cases/public/containers/use_create_attachments.tsx b/x-pack/plugins/cases/public/containers/use_create_attachments.tsx index 779677cd89cc6..074b85839c4d9 100644 --- a/x-pack/plugins/cases/public/containers/use_create_attachments.tsx +++ b/x-pack/plugins/cases/public/containers/use_create_attachments.tsx @@ -9,9 +9,9 @@ import { useReducer, useCallback, useRef, useEffect } from 'react'; import { createAttachments } from './api'; import * as i18n from './translations'; -import { Case } from './types'; +import type { Case } from './types'; import { useToasts } from '../common/lib/kibana'; -import { CaseAttachmentsWithoutOwner } from '../types'; +import type { CaseAttachmentsWithoutOwner } from '../types'; interface NewCommentState { isLoading: boolean; diff --git a/x-pack/plugins/cases/public/containers/use_delete_cases.test.tsx b/x-pack/plugins/cases/public/containers/use_delete_cases.test.tsx index 623a01746e3cb..2059b7331e298 100644 --- a/x-pack/plugins/cases/public/containers/use_delete_cases.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_delete_cases.test.tsx @@ -10,7 +10,8 @@ import { renderHook, act } from '@testing-library/react-hooks'; import { useDeleteCases } from './use_delete_cases'; import * as api from './api'; import { useToasts } from '../common/lib/kibana'; -import { AppMockRenderer, createAppMockRenderer } from '../common/mock'; +import type { AppMockRenderer } from '../common/mock'; +import { createAppMockRenderer } from '../common/mock'; import { casesQueriesKeys } from './constants'; jest.mock('./api'); diff --git a/x-pack/plugins/cases/public/containers/use_delete_cases.tsx b/x-pack/plugins/cases/public/containers/use_delete_cases.tsx index da2258f8f5d82..a08a8bed37d3a 100644 --- a/x-pack/plugins/cases/public/containers/use_delete_cases.tsx +++ b/x-pack/plugins/cases/public/containers/use_delete_cases.tsx @@ -8,7 +8,7 @@ import { useMutation, useQueryClient } from '@tanstack/react-query'; import * as i18n from './translations'; import { deleteCases } from './api'; -import { ServerError } from '../types'; +import type { ServerError } from '../types'; import { casesQueriesKeys, casesMutationsKeys } from './constants'; import { useCasesToast } from '../common/use_cases_toast'; diff --git a/x-pack/plugins/cases/public/containers/use_delete_comment.test.tsx b/x-pack/plugins/cases/public/containers/use_delete_comment.test.tsx index ed038e23f8d7d..dd280e8abb0bf 100644 --- a/x-pack/plugins/cases/public/containers/use_delete_comment.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_delete_comment.test.tsx @@ -6,7 +6,8 @@ */ import { act, renderHook } from '@testing-library/react-hooks'; -import { useDeleteComment, UseDeleteComment } from './use_delete_comment'; +import type { UseDeleteComment } from './use_delete_comment'; +import { useDeleteComment } from './use_delete_comment'; import * as api from './api'; import { basicCaseId } from './mock'; import { useRefreshCaseViewPage } from '../components/case_view/use_on_refresh_case_view_page'; diff --git a/x-pack/plugins/cases/public/containers/use_get_action_license.test.tsx b/x-pack/plugins/cases/public/containers/use_get_action_license.test.tsx index 9ad55fe496a0e..d2bf757697a4b 100644 --- a/x-pack/plugins/cases/public/containers/use_get_action_license.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_get_action_license.test.tsx @@ -8,7 +8,8 @@ import { renderHook } from '@testing-library/react-hooks'; import * as api from './api'; import { useGetActionLicense } from './use_get_action_license'; -import { AppMockRenderer, createAppMockRenderer } from '../common/mock'; +import type { AppMockRenderer } from '../common/mock'; +import { createAppMockRenderer } from '../common/mock'; import { useToasts } from '../common/lib/kibana'; jest.mock('./api'); diff --git a/x-pack/plugins/cases/public/containers/use_get_action_license.tsx b/x-pack/plugins/cases/public/containers/use_get_action_license.tsx index 7f05012cbbe6a..6522d5a530671 100644 --- a/x-pack/plugins/cases/public/containers/use_get_action_license.tsx +++ b/x-pack/plugins/cases/public/containers/use_get_action_license.tsx @@ -11,7 +11,7 @@ import { getActionLicense } from './api'; import * as i18n from './translations'; import { ConnectorTypes } from '../../common/api'; import { casesQueriesKeys } from './constants'; -import { ServerError } from '../types'; +import type { ServerError } from '../types'; const MINIMUM_LICENSE_REQUIRED_CONNECTOR = ConnectorTypes.jira; diff --git a/x-pack/plugins/cases/public/containers/use_get_case.tsx b/x-pack/plugins/cases/public/containers/use_get_case.tsx index bf588cc1e71d0..11be6abfdf765 100644 --- a/x-pack/plugins/cases/public/containers/use_get_case.tsx +++ b/x-pack/plugins/cases/public/containers/use_get_case.tsx @@ -6,11 +6,11 @@ */ import { useQuery } from '@tanstack/react-query'; -import { ResolvedCase } from './types'; +import type { ResolvedCase } from './types'; import * as i18n from './translations'; import { useToasts } from '../common/lib/kibana'; import { resolveCase } from './api'; -import { ServerError } from '../types'; +import type { ServerError } from '../types'; import { casesQueriesKeys } from './constants'; export const useGetCase = (caseId: string) => { diff --git a/x-pack/plugins/cases/public/containers/use_get_case_metrics.test.tsx b/x-pack/plugins/cases/public/containers/use_get_case_metrics.test.tsx index 7f61397728170..76c79c0538a5d 100644 --- a/x-pack/plugins/cases/public/containers/use_get_case_metrics.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_get_case_metrics.test.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { renderHook, act } from '@testing-library/react-hooks'; -import { SingleCaseMetricsFeature } from '../../common/ui'; +import type { SingleCaseMetricsFeature } from '../../common/ui'; import { useGetCaseMetrics } from './use_get_case_metrics'; import { basicCase } from './mock'; import * as api from './api'; diff --git a/x-pack/plugins/cases/public/containers/use_get_case_metrics.tsx b/x-pack/plugins/cases/public/containers/use_get_case_metrics.tsx index 32d63fcc3b42e..0c6b535d0e533 100644 --- a/x-pack/plugins/cases/public/containers/use_get_case_metrics.tsx +++ b/x-pack/plugins/cases/public/containers/use_get_case_metrics.tsx @@ -6,10 +6,10 @@ */ import { useQuery } from '@tanstack/react-query'; -import { SingleCaseMetrics, SingleCaseMetricsFeature } from './types'; +import type { SingleCaseMetrics, SingleCaseMetricsFeature } from './types'; import { useToasts } from '../common/lib/kibana'; import { getSingleCaseMetrics } from './api'; -import { ServerError } from '../types'; +import type { ServerError } from '../types'; import { ERROR_TITLE } from './translations'; import { casesQueriesKeys } from './constants'; diff --git a/x-pack/plugins/cases/public/containers/use_get_case_user_actions.test.tsx b/x-pack/plugins/cases/public/containers/use_get_case_user_actions.test.tsx index cdabd8965e202..45e92fac48bfe 100644 --- a/x-pack/plugins/cases/public/containers/use_get_case_user_actions.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_get_case_user_actions.test.tsx @@ -6,11 +6,8 @@ */ import { renderHook, act } from '@testing-library/react-hooks'; -import { - getPushedInfo, - useGetCaseUserActions, - UseGetCaseUserActions, -} from './use_get_case_user_actions'; +import type { UseGetCaseUserActions } from './use_get_case_user_actions'; +import { getPushedInfo, useGetCaseUserActions } from './use_get_case_user_actions'; import { basicCase, basicPush, diff --git a/x-pack/plugins/cases/public/containers/use_get_case_user_actions.tsx b/x-pack/plugins/cases/public/containers/use_get_case_user_actions.tsx index c92d56b41ea76..2714e7ef3e9b1 100644 --- a/x-pack/plugins/cases/public/containers/use_get_case_user_actions.tsx +++ b/x-pack/plugins/cases/public/containers/use_get_case_user_actions.tsx @@ -9,15 +9,16 @@ import { isEmpty, uniqBy } from 'lodash/fp'; import deepEqual from 'fast-deep-equal'; import { useQuery } from '@tanstack/react-query'; -import { CaseUserActions, CaseExternalService } from '../../common/ui/types'; -import { ActionTypes, CaseConnector, NONE_CONNECTOR_ID } from '../../common/api'; +import type { CaseUserActions, CaseExternalService } from '../../common/ui/types'; +import type { CaseConnector } from '../../common/api'; +import { ActionTypes, NONE_CONNECTOR_ID } from '../../common/api'; import { getCaseUserActions } from './api'; import { isPushedUserAction, isConnectorUserAction, isCreateCaseUserAction, } from '../../common/utils/user_actions'; -import { ServerError } from '../types'; +import type { ServerError } from '../types'; import { useToasts } from '../common/lib/kibana'; import { ERROR_TITLE } from './translations'; import { casesQueriesKeys } from './constants'; diff --git a/x-pack/plugins/cases/public/containers/use_get_cases.test.tsx b/x-pack/plugins/cases/public/containers/use_get_cases.test.tsx index 8d2947a3d351c..39cedf782857f 100644 --- a/x-pack/plugins/cases/public/containers/use_get_cases.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_get_cases.test.tsx @@ -8,7 +8,8 @@ import { renderHook } from '@testing-library/react-hooks'; import { DEFAULT_FILTER_OPTIONS, DEFAULT_QUERY_PARAMS, useGetCases } from './use_get_cases'; import * as api from './api'; -import { AppMockRenderer, createAppMockRenderer } from '../common/mock'; +import type { AppMockRenderer } from '../common/mock'; +import { createAppMockRenderer } from '../common/mock'; import { useToasts } from '../common/lib/kibana'; jest.mock('./api'); diff --git a/x-pack/plugins/cases/public/containers/use_get_cases.tsx b/x-pack/plugins/cases/public/containers/use_get_cases.tsx index d630534957e53..b9f55cc77682f 100644 --- a/x-pack/plugins/cases/public/containers/use_get_cases.tsx +++ b/x-pack/plugins/cases/public/containers/use_get_cases.tsx @@ -5,13 +5,15 @@ * 2.0. */ -import { useQuery, UseQueryResult } from '@tanstack/react-query'; +import type { UseQueryResult } from '@tanstack/react-query'; +import { useQuery } from '@tanstack/react-query'; import { casesQueriesKeys, DEFAULT_TABLE_ACTIVE_PAGE, DEFAULT_TABLE_LIMIT } from './constants'; -import { Cases, FilterOptions, QueryParams, SortFieldCase, StatusAll, SeverityAll } from './types'; +import type { Cases, FilterOptions, QueryParams } from './types'; +import { SortFieldCase, StatusAll, SeverityAll } from './types'; import { useToasts } from '../common/lib/kibana'; import * as i18n from './translations'; import { getCases } from './api'; -import { ServerError } from '../types'; +import type { ServerError } from '../types'; const DEFAULT_SEARCH_FIELDS = ['title', 'description']; diff --git a/x-pack/plugins/cases/public/containers/use_get_cases_metrics.test.tsx b/x-pack/plugins/cases/public/containers/use_get_cases_metrics.test.tsx index 0b0cdc59a487e..31bb539fbea17 100644 --- a/x-pack/plugins/cases/public/containers/use_get_cases_metrics.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_get_cases_metrics.test.tsx @@ -7,7 +7,8 @@ import { renderHook } from '@testing-library/react-hooks'; import * as api from '../api'; -import { AppMockRenderer, createAppMockRenderer } from '../common/mock'; +import type { AppMockRenderer } from '../common/mock'; +import { createAppMockRenderer } from '../common/mock'; import { useGetCasesMetrics } from './use_get_cases_metrics'; import { SECURITY_SOLUTION_OWNER } from '../../common/constants'; import { useToasts } from '../common/lib/kibana'; diff --git a/x-pack/plugins/cases/public/containers/use_get_cases_metrics.tsx b/x-pack/plugins/cases/public/containers/use_get_cases_metrics.tsx index b43266e55340d..b8bd1664cfe0c 100644 --- a/x-pack/plugins/cases/public/containers/use_get_cases_metrics.tsx +++ b/x-pack/plugins/cases/public/containers/use_get_cases_metrics.tsx @@ -10,9 +10,9 @@ import { useCasesContext } from '../components/cases_context/use_cases_context'; import * as i18n from './translations'; import { useHttp } from '../common/lib/kibana'; import { getCasesMetrics } from '../api'; -import { CasesMetrics } from './types'; +import type { CasesMetrics } from './types'; import { useCasesToast } from '../common/use_cases_toast'; -import { ServerError } from '../types'; +import type { ServerError } from '../types'; import { casesQueriesKeys } from './constants'; export const useGetCasesMetrics = () => { diff --git a/x-pack/plugins/cases/public/containers/use_get_cases_status.test.tsx b/x-pack/plugins/cases/public/containers/use_get_cases_status.test.tsx index 4f2572093a285..fed7159ac15e3 100644 --- a/x-pack/plugins/cases/public/containers/use_get_cases_status.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_get_cases_status.test.tsx @@ -8,7 +8,8 @@ import { renderHook } from '@testing-library/react-hooks'; import { useGetCasesStatus } from './use_get_cases_status'; import * as api from '../api'; -import { AppMockRenderer, createAppMockRenderer } from '../common/mock'; +import type { AppMockRenderer } from '../common/mock'; +import { createAppMockRenderer } from '../common/mock'; import { SECURITY_SOLUTION_OWNER } from '../../common/constants'; import { useToasts } from '../common/lib/kibana'; diff --git a/x-pack/plugins/cases/public/containers/use_get_cases_status.tsx b/x-pack/plugins/cases/public/containers/use_get_cases_status.tsx index c2ba6659edcbd..89f9cb0e7afd5 100644 --- a/x-pack/plugins/cases/public/containers/use_get_cases_status.tsx +++ b/x-pack/plugins/cases/public/containers/use_get_cases_status.tsx @@ -8,11 +8,11 @@ import { useQuery } from '@tanstack/react-query'; import { useCasesContext } from '../components/cases_context/use_cases_context'; import * as i18n from './translations'; -import { CasesStatus } from './types'; +import type { CasesStatus } from './types'; import { useHttp } from '../common/lib/kibana'; import { getCasesStatus } from '../api'; import { useCasesToast } from '../common/use_cases_toast'; -import { ServerError } from '../types'; +import type { ServerError } from '../types'; import { casesQueriesKeys } from './constants'; export const useGetCasesStatus = () => { diff --git a/x-pack/plugins/cases/public/containers/use_get_tags.tsx b/x-pack/plugins/cases/public/containers/use_get_tags.tsx index da56521536cbe..1c7528604b342 100644 --- a/x-pack/plugins/cases/public/containers/use_get_tags.tsx +++ b/x-pack/plugins/cases/public/containers/use_get_tags.tsx @@ -8,7 +8,7 @@ import { useQuery } from '@tanstack/react-query'; import { useToasts } from '../common/lib/kibana'; import { useCasesContext } from '../components/cases_context/use_cases_context'; -import { ServerError } from '../types'; +import type { ServerError } from '../types'; import { getTags } from './api'; import { casesQueriesKeys } from './constants'; import * as i18n from './translations'; diff --git a/x-pack/plugins/cases/public/containers/use_messages_storage.test.tsx b/x-pack/plugins/cases/public/containers/use_messages_storage.test.tsx index 73bfc49f077ae..8f12ab8e56daf 100644 --- a/x-pack/plugins/cases/public/containers/use_messages_storage.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_messages_storage.test.tsx @@ -6,7 +6,8 @@ */ import { renderHook, act } from '@testing-library/react-hooks'; -import { useMessagesStorage, UseMessagesStorage } from './use_messages_storage'; +import type { UseMessagesStorage } from './use_messages_storage'; +import { useMessagesStorage } from './use_messages_storage'; describe('useLocalStorage', () => { beforeEach(() => { diff --git a/x-pack/plugins/cases/public/containers/use_post_case.test.tsx b/x-pack/plugins/cases/public/containers/use_post_case.test.tsx index 5d5b6ced44afc..5740bcf4c0be8 100644 --- a/x-pack/plugins/cases/public/containers/use_post_case.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_post_case.test.tsx @@ -6,7 +6,8 @@ */ import { renderHook, act } from '@testing-library/react-hooks'; -import { usePostCase, UsePostCase } from './use_post_case'; +import type { UsePostCase } from './use_post_case'; +import { usePostCase } from './use_post_case'; import * as api from './api'; import { ConnectorTypes } from '../../common/api'; import { SECURITY_SOLUTION_OWNER } from '../../common/constants'; diff --git a/x-pack/plugins/cases/public/containers/use_post_case.tsx b/x-pack/plugins/cases/public/containers/use_post_case.tsx index dc23c503b333b..804a109c4483e 100644 --- a/x-pack/plugins/cases/public/containers/use_post_case.tsx +++ b/x-pack/plugins/cases/public/containers/use_post_case.tsx @@ -6,10 +6,10 @@ */ import { useReducer, useCallback, useRef, useEffect } from 'react'; -import { CasePostRequest } from '../../common/api'; +import type { CasePostRequest } from '../../common/api'; import { postCase } from './api'; import * as i18n from './translations'; -import { Case } from './types'; +import type { Case } from './types'; import { useToasts } from '../common/lib/kibana'; interface NewCaseState { isLoading: boolean; diff --git a/x-pack/plugins/cases/public/containers/use_post_push_to_service.test.tsx b/x-pack/plugins/cases/public/containers/use_post_push_to_service.test.tsx index dedde459ad557..6ab6c97f06465 100644 --- a/x-pack/plugins/cases/public/containers/use_post_push_to_service.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_post_push_to_service.test.tsx @@ -6,10 +6,12 @@ */ import { renderHook, act } from '@testing-library/react-hooks'; -import { usePostPushToService, UsePostPushToService } from './use_post_push_to_service'; +import type { UsePostPushToService } from './use_post_push_to_service'; +import { usePostPushToService } from './use_post_push_to_service'; import { pushedCase } from './mock'; import * as api from './api'; -import { CaseConnector, ConnectorTypes } from '../../common/api'; +import type { CaseConnector } from '../../common/api'; +import { ConnectorTypes } from '../../common/api'; jest.mock('./api'); jest.mock('../common/lib/kibana'); diff --git a/x-pack/plugins/cases/public/containers/use_post_push_to_service.tsx b/x-pack/plugins/cases/public/containers/use_post_push_to_service.tsx index 90f1fbe212a02..3a5e8bddcea63 100644 --- a/x-pack/plugins/cases/public/containers/use_post_push_to_service.tsx +++ b/x-pack/plugins/cases/public/containers/use_post_push_to_service.tsx @@ -6,11 +6,11 @@ */ import { useReducer, useCallback, useRef, useEffect } from 'react'; -import { CaseConnector } from '../../common/api'; +import type { CaseConnector } from '../../common/api'; import { pushCase } from './api'; import * as i18n from './translations'; -import { Case } from './types'; +import type { Case } from './types'; import { useToasts } from '../common/lib/kibana'; interface PushToServiceState { diff --git a/x-pack/plugins/cases/public/containers/use_update_case.test.tsx b/x-pack/plugins/cases/public/containers/use_update_case.test.tsx index 28bfeca01d446..4a3e7a59fdb0b 100644 --- a/x-pack/plugins/cases/public/containers/use_update_case.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_update_case.test.tsx @@ -6,10 +6,11 @@ */ import { renderHook, act } from '@testing-library/react-hooks'; -import { useUpdateCase, UseUpdateCase } from './use_update_case'; +import type { UseUpdateCase } from './use_update_case'; +import { useUpdateCase } from './use_update_case'; import { basicCase } from './mock'; import * as api from './api'; -import { UpdateKey } from './types'; +import type { UpdateKey } from './types'; import { useRefreshCaseViewPage } from '../components/case_view/use_on_refresh_case_view_page'; jest.mock('./api'); diff --git a/x-pack/plugins/cases/public/containers/use_update_case.tsx b/x-pack/plugins/cases/public/containers/use_update_case.tsx index 4b7433ca79474..8f5d86da1beaa 100644 --- a/x-pack/plugins/cases/public/containers/use_update_case.tsx +++ b/x-pack/plugins/cases/public/containers/use_update_case.tsx @@ -9,7 +9,7 @@ import { useReducer, useCallback, useRef, useEffect } from 'react'; import { useToasts } from '../common/lib/kibana'; import { patchCase } from './api'; -import { UpdateKey, UpdateByKey } from '../../common/ui/types'; +import type { UpdateKey, UpdateByKey } from '../../common/ui/types'; import * as i18n from './translations'; import { createUpdateSuccessToaster } from './utils'; import { useRefreshCaseViewPage } from '../components/case_view/use_on_refresh_case_view_page'; diff --git a/x-pack/plugins/cases/public/containers/use_update_comment.test.tsx b/x-pack/plugins/cases/public/containers/use_update_comment.test.tsx index 27786f445ef20..b90c16fca4c8b 100644 --- a/x-pack/plugins/cases/public/containers/use_update_comment.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_update_comment.test.tsx @@ -7,7 +7,8 @@ import React from 'react'; import { renderHook, act } from '@testing-library/react-hooks'; -import { useUpdateComment, UseUpdateComment } from './use_update_comment'; +import type { UseUpdateComment } from './use_update_comment'; +import { useUpdateComment } from './use_update_comment'; import { basicCase } from './mock'; import * as api from './api'; import { TestProviders } from '../common/mock'; diff --git a/x-pack/plugins/cases/public/containers/user_profiles/__mocks__/api.ts b/x-pack/plugins/cases/public/containers/user_profiles/__mocks__/api.ts index 6901852a405fa..e027466eb1abb 100644 --- a/x-pack/plugins/cases/public/containers/user_profiles/__mocks__/api.ts +++ b/x-pack/plugins/cases/public/containers/user_profiles/__mocks__/api.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { UserProfile } from '@kbn/security-plugin/common'; +import type { UserProfile } from '@kbn/security-plugin/common'; import { userProfiles } from '../api.mock'; export const suggestUserProfiles = async (): Promise => userProfiles; diff --git a/x-pack/plugins/cases/public/containers/user_profiles/api.mock.ts b/x-pack/plugins/cases/public/containers/user_profiles/api.mock.ts index 1296cf9878827..42438f16dfa37 100644 --- a/x-pack/plugins/cases/public/containers/user_profiles/api.mock.ts +++ b/x-pack/plugins/cases/public/containers/user_profiles/api.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/public/containers/user_profiles/api.test.ts b/x-pack/plugins/cases/public/containers/user_profiles/api.test.ts index 0f7c9d9c31fa9..ad7550ee857af 100644 --- a/x-pack/plugins/cases/public/containers/user_profiles/api.test.ts +++ b/x-pack/plugins/cases/public/containers/user_profiles/api.test.ts @@ -6,7 +6,7 @@ */ import { securityMock } from '@kbn/security-plugin/public/mocks'; -import { SecurityPluginStart } from '@kbn/security-plugin/public'; +import type { SecurityPluginStart } from '@kbn/security-plugin/public'; import { GENERAL_CASES_OWNER } from '../../../common/constants'; import { createStartServicesMock } from '../../common/lib/kibana/kibana_react.mock'; import { bulkGetUserProfiles, getCurrentUserProfile, suggestUserProfiles } from './api'; diff --git a/x-pack/plugins/cases/public/containers/user_profiles/api.ts b/x-pack/plugins/cases/public/containers/user_profiles/api.ts index cfd1c04d0afbc..895bb9cafcce9 100644 --- a/x-pack/plugins/cases/public/containers/user_profiles/api.ts +++ b/x-pack/plugins/cases/public/containers/user_profiles/api.ts @@ -5,9 +5,9 @@ * 2.0. */ -import { HttpStart } from '@kbn/core/public'; -import { UserProfile } from '@kbn/security-plugin/common'; -import { SecurityPluginStart } from '@kbn/security-plugin/public'; +import type { HttpStart } from '@kbn/core/public'; +import type { UserProfile } from '@kbn/security-plugin/common'; +import type { SecurityPluginStart } from '@kbn/security-plugin/public'; import { INTERNAL_SUGGEST_USER_PROFILES_URL, DEFAULT_USER_SIZE } from '../../../common/constants'; export interface SuggestUserProfilesArgs { diff --git a/x-pack/plugins/cases/public/containers/user_profiles/use_assignees.test.ts b/x-pack/plugins/cases/public/containers/user_profiles/use_assignees.test.ts index db4527ae31e43..f8b38e4d31dbf 100644 --- a/x-pack/plugins/cases/public/containers/user_profiles/use_assignees.test.ts +++ b/x-pack/plugins/cases/public/containers/user_profiles/use_assignees.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { UserProfileWithAvatar } from '@kbn/user-profile-components'; +import type { UserProfileWithAvatar } from '@kbn/user-profile-components'; import { renderHook } from '@testing-library/react-hooks'; import { userProfiles, userProfilesMap } from './api.mock'; import { useAssignees } from './use_assignees'; diff --git a/x-pack/plugins/cases/public/containers/user_profiles/use_assignees.ts b/x-pack/plugins/cases/public/containers/user_profiles/use_assignees.ts index 2e1bb0a61dbda..069eae715f2b9 100644 --- a/x-pack/plugins/cases/public/containers/user_profiles/use_assignees.ts +++ b/x-pack/plugins/cases/public/containers/user_profiles/use_assignees.ts @@ -5,12 +5,12 @@ * 2.0. */ -import { UserProfileWithAvatar } from '@kbn/user-profile-components'; +import type { UserProfileWithAvatar } from '@kbn/user-profile-components'; import { useMemo } from 'react'; -import { CaseAssignees } from '../../../common/api'; -import { CurrentUserProfile } from '../../components/types'; +import type { CaseAssignees } from '../../../common/api'; +import type { CurrentUserProfile } from '../../components/types'; import { bringCurrentUserToFrontAndSort } from '../../components/user_profiles/sort'; -import { Assignee, AssigneeWithProfile } from '../../components/user_profiles/types'; +import type { Assignee, AssigneeWithProfile } from '../../components/user_profiles/types'; interface PartitionedAssignees { usersWithProfiles: UserProfileWithAvatar[]; diff --git a/x-pack/plugins/cases/public/containers/user_profiles/use_bulk_get_user_profiles.test.ts b/x-pack/plugins/cases/public/containers/user_profiles/use_bulk_get_user_profiles.test.ts index af0482f41b25a..1574c1ddd2580 100644 --- a/x-pack/plugins/cases/public/containers/user_profiles/use_bulk_get_user_profiles.test.ts +++ b/x-pack/plugins/cases/public/containers/user_profiles/use_bulk_get_user_profiles.test.ts @@ -7,7 +7,8 @@ import { renderHook } from '@testing-library/react-hooks'; import { useToasts, useKibana } from '../../common/lib/kibana'; -import { AppMockRenderer, createAppMockRenderer } from '../../common/mock'; +import type { AppMockRenderer } from '../../common/mock'; +import { createAppMockRenderer } from '../../common/mock'; import * as api from './api'; import { useBulkGetUserProfiles } from './use_bulk_get_user_profiles'; import { userProfilesIds } from './api.mock'; diff --git a/x-pack/plugins/cases/public/containers/user_profiles/use_bulk_get_user_profiles.ts b/x-pack/plugins/cases/public/containers/user_profiles/use_bulk_get_user_profiles.ts index b2928295dbb37..a9e60f3e854a9 100644 --- a/x-pack/plugins/cases/public/containers/user_profiles/use_bulk_get_user_profiles.ts +++ b/x-pack/plugins/cases/public/containers/user_profiles/use_bulk_get_user_profiles.ts @@ -5,11 +5,12 @@ * 2.0. */ -import { useQuery, UseQueryResult } from '@tanstack/react-query'; -import { UserProfileWithAvatar } from '@kbn/user-profile-components'; +import type { UseQueryResult } from '@tanstack/react-query'; +import { useQuery } from '@tanstack/react-query'; +import type { UserProfileWithAvatar } from '@kbn/user-profile-components'; import * as i18n from '../translations'; import { useKibana, useToasts } from '../../common/lib/kibana'; -import { ServerError } from '../../types'; +import type { ServerError } from '../../types'; import { casesQueriesKeys } from '../constants'; import { bulkGetUserProfiles } from './api'; diff --git a/x-pack/plugins/cases/public/containers/user_profiles/use_get_current_user_profile.test.ts b/x-pack/plugins/cases/public/containers/user_profiles/use_get_current_user_profile.test.ts index ebc896a480cb0..70fac4dd84fe3 100644 --- a/x-pack/plugins/cases/public/containers/user_profiles/use_get_current_user_profile.test.ts +++ b/x-pack/plugins/cases/public/containers/user_profiles/use_get_current_user_profile.test.ts @@ -8,7 +8,8 @@ import { renderHook } from '@testing-library/react-hooks'; import { useToasts, useKibana } from '../../common/lib/kibana'; import { createStartServicesMock } from '../../common/lib/kibana/kibana_react.mock'; -import { AppMockRenderer, createAppMockRenderer } from '../../common/mock'; +import type { AppMockRenderer } from '../../common/mock'; +import { createAppMockRenderer } from '../../common/mock'; import * as api from './api'; import { useGetCurrentUserProfile } from './use_get_current_user_profile'; diff --git a/x-pack/plugins/cases/public/containers/user_profiles/use_get_current_user_profile.ts b/x-pack/plugins/cases/public/containers/user_profiles/use_get_current_user_profile.ts index d6e3483672554..e98f08ab486f9 100644 --- a/x-pack/plugins/cases/public/containers/user_profiles/use_get_current_user_profile.ts +++ b/x-pack/plugins/cases/public/containers/user_profiles/use_get_current_user_profile.ts @@ -5,11 +5,12 @@ * 2.0. */ -import { useQuery, UseQueryResult } from '@tanstack/react-query'; -import { UserProfile } from '@kbn/security-plugin/common'; +import type { UseQueryResult } from '@tanstack/react-query'; +import { useQuery } from '@tanstack/react-query'; +import type { UserProfile } from '@kbn/security-plugin/common'; import * as i18n from '../translations'; import { useKibana, useToasts } from '../../common/lib/kibana'; -import { ServerError } from '../../types'; +import type { ServerError } from '../../types'; import { casesQueriesKeys } from '../constants'; import { getCurrentUserProfile } from './api'; diff --git a/x-pack/plugins/cases/public/containers/user_profiles/use_suggest_user_profiles.test.ts b/x-pack/plugins/cases/public/containers/user_profiles/use_suggest_user_profiles.test.ts index 2d4482b94a9c6..7daf1d1d5cf62 100644 --- a/x-pack/plugins/cases/public/containers/user_profiles/use_suggest_user_profiles.test.ts +++ b/x-pack/plugins/cases/public/containers/user_profiles/use_suggest_user_profiles.test.ts @@ -8,7 +8,8 @@ import { GENERAL_CASES_OWNER } from '../../../common/constants'; import { renderHook } from '@testing-library/react-hooks'; import { useToasts } from '../../common/lib/kibana'; -import { AppMockRenderer, createAppMockRenderer } from '../../common/mock'; +import type { AppMockRenderer } from '../../common/mock'; +import { createAppMockRenderer } from '../../common/mock'; import * as api from './api'; import { useSuggestUserProfiles } from './use_suggest_user_profiles'; diff --git a/x-pack/plugins/cases/public/containers/user_profiles/use_suggest_user_profiles.ts b/x-pack/plugins/cases/public/containers/user_profiles/use_suggest_user_profiles.ts index 74c492850acd4..bc14f103d1547 100644 --- a/x-pack/plugins/cases/public/containers/user_profiles/use_suggest_user_profiles.ts +++ b/x-pack/plugins/cases/public/containers/user_profiles/use_suggest_user_profiles.ts @@ -6,16 +6,18 @@ */ import { useState } from 'react'; -import { useQuery, UseQueryResult } from '@tanstack/react-query'; +import type { UseQueryResult } from '@tanstack/react-query'; +import { useQuery } from '@tanstack/react-query'; import useDebounce from 'react-use/lib/useDebounce'; -import { UserProfile } from '@kbn/security-plugin/common'; +import type { UserProfile } from '@kbn/security-plugin/common'; import { noop } from 'lodash'; import { DEFAULT_USER_SIZE, SEARCH_DEBOUNCE_MS } from '../../../common/constants'; import * as i18n from '../translations'; import { useKibana, useToasts } from '../../common/lib/kibana'; -import { ServerError } from '../../types'; +import type { ServerError } from '../../types'; import { casesQueriesKeys } from '../constants'; -import { suggestUserProfiles, SuggestUserProfilesArgs } from './api'; +import type { SuggestUserProfilesArgs } from './api'; +import { suggestUserProfiles } from './api'; type Props = Omit & { onDebounce?: () => void }; diff --git a/x-pack/plugins/cases/public/containers/utils.test.ts b/x-pack/plugins/cases/public/containers/utils.test.ts index 0dd55fbe8aaca..0886093b9164f 100644 --- a/x-pack/plugins/cases/public/containers/utils.test.ts +++ b/x-pack/plugins/cases/public/containers/utils.test.ts @@ -11,7 +11,7 @@ import { createUpdateSuccessToaster, } from './utils'; -import { Case } from './types'; +import type { Case } from './types'; const caseBeforeUpdate = { comments: [ diff --git a/x-pack/plugins/cases/public/containers/utils.ts b/x-pack/plugins/cases/public/containers/utils.ts index a9a0eff53c07c..e1f5b954a23dc 100644 --- a/x-pack/plugins/cases/public/containers/utils.ts +++ b/x-pack/plugins/cases/public/containers/utils.ts @@ -10,27 +10,29 @@ import { fold } from 'fp-ts/lib/Either'; import { identity } from 'fp-ts/lib/function'; import { pipe } from 'fp-ts/lib/pipeable'; -import { ToastInputFields } from '@kbn/core/public'; -import { +import type { ToastInputFields } from '@kbn/core/public'; +import type { CaseResponse, - CaseResponseRt, CasesResponse, + CasesConfigurationsResponse, + CasesConfigureResponse, + CaseUserActionsResponse, + CasePatchRequest, + CaseResolveResponse, + SingleCaseMetricsResponse, +} from '../../common/api'; +import { + CaseResponseRt, CasesResponseRt, throwErrors, - CasesConfigurationsResponse, CaseConfigurationsResponseRt, - CasesConfigureResponse, CaseConfigureResponseRt, - CaseUserActionsResponse, CaseUserActionsResponseRt, CommentType, - CasePatchRequest, - CaseResolveResponse, CaseResolveResponseRt, - SingleCaseMetricsResponse, SingleCaseMetricsResponseRt, } from '../../common/api'; -import { Case, UpdateByKey } from './types'; +import type { Case, UpdateByKey } from './types'; import * as i18n from './translations'; export const getTypedPayload = (a: unknown): T => a as T; diff --git a/x-pack/plugins/cases/public/index.tsx b/x-pack/plugins/cases/public/index.tsx index 0f1e8e3cad4f6..7130d412bebf1 100644 --- a/x-pack/plugins/cases/public/index.tsx +++ b/x-pack/plugins/cases/public/index.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import { PluginInitializerContext } from '@kbn/core/public'; +import type { PluginInitializerContext } from '@kbn/core/public'; import { CasesUiPlugin } from './plugin'; export function plugin(initializerContext: PluginInitializerContext) { diff --git a/x-pack/plugins/cases/public/mocks.ts b/x-pack/plugins/cases/public/mocks.ts index 10a4c1f6fd059..10678512d178e 100644 --- a/x-pack/plugins/cases/public/mocks.ts +++ b/x-pack/plugins/cases/public/mocks.ts @@ -6,7 +6,7 @@ */ import { mockCasesContext } from './mocks/mock_cases_context'; -import { CasesUiStart } from './types'; +import type { CasesUiStart } from './types'; const apiMock: jest.Mocked = { getRelatedCases: jest.fn(), diff --git a/x-pack/plugins/cases/public/plugin.ts b/x-pack/plugins/cases/public/plugin.ts index 53b3b57d4e2ef..51f2ae92e3094 100644 --- a/x-pack/plugins/cases/public/plugin.ts +++ b/x-pack/plugins/cases/public/plugin.ts @@ -5,12 +5,12 @@ * 2.0. */ -import { CoreSetup, CoreStart, Plugin, PluginInitializerContext } from '@kbn/core/public'; -import { ManagementAppMountParams } from '@kbn/management-plugin/public'; +import type { CoreSetup, CoreStart, Plugin, PluginInitializerContext } from '@kbn/core/public'; +import type { ManagementAppMountParams } from '@kbn/management-plugin/public'; import { Storage } from '@kbn/kibana-utils-plugin/public'; -import { CasesUiStart, CasesPluginSetup, CasesPluginStart, CasesUiSetup } from './types'; +import type { CasesUiStart, CasesPluginSetup, CasesPluginStart, CasesUiSetup } from './types'; import { KibanaServices } from './common/lib/kibana'; -import { CasesUiConfigType } from '../common/ui/types'; +import type { CasesUiConfigType } from '../common/ui/types'; import { APP_ID, APP_PATH } from '../common/constants'; import { APP_TITLE, APP_DESC } from './common/translations'; import { useCasesAddToExistingCaseModal } from './components/all_cases/selector_modal/use_cases_add_to_existing_case_modal'; @@ -67,7 +67,7 @@ export class CasesUiPlugin plugins.management.sections.section.insightsAndAlerting.registerApp({ id: APP_ID, title: APP_TITLE, - order: 0, + order: 1, async mount(params: ManagementAppMountParams) { const [coreStart, pluginsStart] = (await core.getStartServices()) as [ CoreStart, diff --git a/x-pack/plugins/cases/public/types.ts b/x-pack/plugins/cases/public/types.ts index 8b67eb96cda24..732fcfee5f0d6 100644 --- a/x-pack/plugins/cases/public/types.ts +++ b/x-pack/plugins/cases/public/types.ts @@ -7,7 +7,8 @@ import type { CoreStart } from '@kbn/core/public'; import type { IHttpFetchError, ResponseErrorBody } from '@kbn/core-http-browser'; -import React, { ReactElement } from 'react'; +import type { ReactElement } from 'react'; +import type React from 'react'; import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; import type { EmbeddableStart } from '@kbn/embeddable-plugin/public'; import type { Storage } from '@kbn/kibana-utils-plugin/public'; @@ -20,7 +21,7 @@ import type { SpacesPluginStart } from '@kbn/spaces-plugin/public'; import type { TriggersAndActionsUIPublicPluginStart as TriggersActionsStart } from '@kbn/triggers-actions-ui-plugin/public'; import type { DistributiveOmit } from '@elastic/eui'; import type { ApmBase } from '@elastic/apm-rum'; -import { LicensingPluginStart } from '@kbn/licensing-plugin/public'; +import type { LicensingPluginStart } from '@kbn/licensing-plugin/public'; import type { CasesByAlertId, CasesByAlertIDRequest, @@ -34,19 +35,19 @@ import type { } from '../common/api'; import type { UseCasesAddToExistingCaseModal } from './components/all_cases/selector_modal/use_cases_add_to_existing_case_modal'; import type { UseCasesAddToNewCaseFlyout } from './components/create/flyout/use_cases_add_to_new_case_flyout'; -import { canUseCases } from './client/helpers/can_use_cases'; -import { getRuleIdFromEvent } from './client/helpers/get_rule_id_from_event'; +import type { canUseCases } from './client/helpers/can_use_cases'; +import type { getRuleIdFromEvent } from './client/helpers/get_rule_id_from_event'; import type { GetCasesContextProps } from './client/ui/get_cases_context'; import type { GetCasesProps } from './client/ui/get_cases'; import type { GetAllCasesSelectorModalProps } from './client/ui/get_all_cases_selector_modal'; import type { GetCreateCaseFlyoutProps } from './client/ui/get_create_case_flyout'; import type { GetRecentCasesProps } from './client/ui/get_recent_cases'; import type { Cases, CasesStatus, CasesMetrics } from '../common/ui'; -import { groupAlertsByRule } from './client/helpers/group_alerts_by_rule'; -import { getUICapabilities } from './client/helpers/capabilities'; +import type { groupAlertsByRule } from './client/helpers/group_alerts_by_rule'; +import type { getUICapabilities } from './client/helpers/capabilities'; import type { AttachmentFramework } from './client/attachment_framework/types'; -import { ExternalReferenceAttachmentTypeRegistry } from './client/attachment_framework/external_reference_registry'; -import { PersistableStateAttachmentTypeRegistry } from './client/attachment_framework/persistable_state_registry'; +import type { ExternalReferenceAttachmentTypeRegistry } from './client/attachment_framework/external_reference_registry'; +import type { PersistableStateAttachmentTypeRegistry } from './client/attachment_framework/persistable_state_registry'; export interface CasesPluginSetup { security: SecurityPluginSetup; diff --git a/x-pack/plugins/cases/public/utils/permissions.ts b/x-pack/plugins/cases/public/utils/permissions.ts index 75e15f8859e58..29aba5648abd9 100644 --- a/x-pack/plugins/cases/public/utils/permissions.ts +++ b/x-pack/plugins/cases/public/utils/permissions.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { CasesPermissions } from '../../common'; +import type { CasesPermissions } from '../../common'; export const isReadOnlyPermissions = (permissions: CasesPermissions) => { return ( diff --git a/x-pack/plugins/cases/server/client/cases/mock.ts b/x-pack/plugins/cases/server/client/cases/mock.ts index 3f912cda3eb3c..a7ffe2a3c8bd3 100644 --- a/x-pack/plugins/cases/server/client/cases/mock.ts +++ b/x-pack/plugins/cases/server/client/cases/mock.ts @@ -8,16 +8,15 @@ import { CommentResponse, CommentType, - ConnectorMappingsAttributes, CaseUserActionsResponse, CommentResponseAlertsType, ConnectorTypes, Actions, + ConnectorMappingsAttributes, + ExternalReferenceStorageType, } from '../../../common/api'; import { SECURITY_SOLUTION_OWNER } from '../../../common/constants'; -import { BasicParams } from './types'; - export const updateUser = { updated_at: '2020-03-13T08:34:53.450Z', updated_by: { full_name: 'Another User', username: 'another', email: 'elastic@elastic.co' }, @@ -31,7 +30,7 @@ const entity = { }; export const comment: CommentResponse = { - id: 'mock-comment-1', + id: 'comment-user-1', comment: 'Wow, good luck catching that bad meanie!', type: CommentType.user as const, created_at: '2019-11-25T21:55:00.177Z', @@ -84,7 +83,7 @@ export const isolateCommentActions: CommentResponse = { }; export const releaseCommentActions: CommentResponse = { - id: 'mock-action-comment-1', + id: 'mock-action-comment-2', comment: 'Releasing this for investigation', type: CommentType.actions as const, created_at: '2019-11-25T21:55:00.177Z', @@ -115,7 +114,7 @@ export const releaseCommentActions: CommentResponse = { }; export const isolateCommentActionsMultipleTargets: CommentResponse = { - id: 'mock-action-comment-1', + id: 'mock-action-comment-3', comment: 'Isolating this for investigation', type: CommentType.actions as const, created_at: '2019-11-25T21:55:00.177Z', @@ -150,7 +149,7 @@ export const isolateCommentActionsMultipleTargets: CommentResponse = { }; export const commentAlert: CommentResponse = { - id: 'mock-comment-1', + id: 'comment-alert-1', alertId: 'alert-id-1', index: 'alert-index-1', rule: { @@ -178,15 +177,64 @@ export const commentAlert: CommentResponse = { export const commentAlertMultipleIds: CommentResponseAlertsType = { ...commentAlert, - id: 'mock-comment-2', + id: 'comment-alert-2', alertId: ['alert-id-1', 'alert-id-2'], index: 'alert-index-1', type: CommentType.alert as const, owner: SECURITY_SOLUTION_OWNER, }; -export const defaultPipes = ['informationCreated']; -export const basicParams: BasicParams = { +export const commentExternalReference: CommentResponse = { + id: 'comment-external-reference-1', + type: CommentType.externalReference as const, + externalReferenceId: 'my-id', + externalReferenceStorage: { + type: ExternalReferenceStorageType.elasticSearchDoc as const, + }, + externalReferenceAttachmentTypeId: '.test', + externalReferenceMetadata: null, + created_at: '2019-11-25T21:55:00.177Z', + created_by: { + full_name: 'elastic', + email: 'testemail@elastic.co', + username: 'elastic', + }, + owner: SECURITY_SOLUTION_OWNER, + pushed_at: null, + pushed_by: null, + updated_at: '2019-11-25T21:55:00.177Z', + updated_by: { + full_name: 'elastic', + email: 'testemail@elastic.co', + username: 'elastic', + }, + version: 'WzEsMV0=', +}; + +export const commentPersistableState: CommentResponse = { + id: 'comment-persistable-state-1', + type: CommentType.persistableState, + persistableStateAttachmentTypeId: '.test', + persistableStateAttachmentState: { foo: 'foo', injectedId: 'testRef' }, + created_at: '2019-11-25T21:55:00.177Z', + created_by: { + full_name: 'elastic', + email: 'testemail@elastic.co', + username: 'elastic', + }, + owner: SECURITY_SOLUTION_OWNER, + pushed_at: null, + pushed_by: null, + updated_at: '2019-11-25T21:55:00.177Z', + updated_by: { + full_name: 'elastic', + email: 'testemail@elastic.co', + username: 'elastic', + }, + version: 'WzEsMV0=', +}; + +export const basicParams = { description: 'a description', title: 'a title', ...entity, @@ -286,16 +334,16 @@ export const userActions: CaseUserActionsResponse = [ }, payload: { comment: { - type: CommentType.alert, - alertId: 'alert-id-1', - index: '.siem-signals-default-000008', - rule: { id: '123', name: 'rule name' }, - owner: SECURITY_SOLUTION_OWNER, + type: commentAlert.type, + alertId: commentAlert.alertId, + index: commentAlert.index, + rule: commentAlert.rule, + owner: commentAlert.owner, }, }, action_id: '7373eb60-6647-11eb-a291-51bf6b175a53', case_id: 'fcdedd20-6646-11eb-a291-51bf6b175a53', - comment_id: 'comment-alert-1', + comment_id: commentAlert.id, owner: SECURITY_SOLUTION_OWNER, }, { @@ -309,16 +357,129 @@ export const userActions: CaseUserActionsResponse = [ }, payload: { comment: { - type: CommentType.alert, - alertId: 'alert-id-2', - index: '.siem-signals-default-000008', - rule: { id: '123', name: 'rule name' }, - owner: SECURITY_SOLUTION_OWNER, + type: commentAlertMultipleIds.type, + alertId: commentAlertMultipleIds.alertId, + index: commentAlertMultipleIds.index, + rule: commentAlertMultipleIds.rule, + owner: commentAlertMultipleIds.owner, }, }, action_id: '7abc6410-6647-11eb-a291-51bf6b175a53', case_id: 'fcdedd20-6646-11eb-a291-51bf6b175a53', - comment_id: 'comment-alert-2', + comment_id: commentAlertMultipleIds.id, + owner: SECURITY_SOLUTION_OWNER, + }, + { + type: 'comment', + action: Actions.create, + created_at: '2021-02-03T17:48:30.616Z', + created_by: { + email: 'elastic@elastic.co', + full_name: 'Elastic', + username: 'elastic', + }, + payload: { + comment: { + type: isolateCommentActions.type, + owner: isolateCommentActions.owner, + comment: isolateCommentActions.comment, + actions: isolateCommentActions.actions, + }, + }, + action_id: '0818e5e0-6648-11eb-a291-51bf6b175a53', + case_id: 'fcdedd20-6646-11eb-a291-51bf6b175a53', + comment_id: isolateCommentActions.id, + owner: SECURITY_SOLUTION_OWNER, + }, + { + type: 'comment', + action: Actions.create, + created_at: '2021-02-03T17:48:30.616Z', + created_by: { + email: 'elastic@elastic.co', + full_name: 'Elastic', + username: 'elastic', + }, + payload: { + comment: { + type: releaseCommentActions.type, + owner: releaseCommentActions.owner, + comment: releaseCommentActions.comment, + actions: releaseCommentActions.actions, + }, + }, + action_id: '0818e5e0-6648-11eb-a291-51bf6b175a53', + case_id: 'fcdedd20-6646-11eb-a291-51bf6b175a53', + comment_id: releaseCommentActions.id, + owner: SECURITY_SOLUTION_OWNER, + }, + { + type: 'comment', + action: Actions.create, + created_at: '2021-02-03T17:48:30.616Z', + created_by: { + email: 'elastic@elastic.co', + full_name: 'Elastic', + username: 'elastic', + }, + payload: { + comment: { + type: isolateCommentActionsMultipleTargets.type, + owner: isolateCommentActionsMultipleTargets.owner, + comment: isolateCommentActionsMultipleTargets.comment, + actions: isolateCommentActionsMultipleTargets.actions, + }, + }, + action_id: '0818e5e0-6648-11eb-a291-51bf6b175a53', + case_id: 'fcdedd20-6646-11eb-a291-51bf6b175a53', + comment_id: isolateCommentActionsMultipleTargets.id, + owner: SECURITY_SOLUTION_OWNER, + }, + { + type: 'comment', + action: Actions.create, + created_at: '2021-02-03T17:48:30.616Z', + created_by: { + email: 'elastic@elastic.co', + full_name: 'Elastic', + username: 'elastic', + }, + payload: { + comment: { + type: commentExternalReference.type, + owner: commentExternalReference.owner, + externalReferenceId: commentExternalReference.externalReferenceId, + externalReferenceAttachmentTypeId: + commentExternalReference.externalReferenceAttachmentTypeId, + externalReferenceMetadata: commentExternalReference.externalReferenceMetadata, + externalReferenceStorage: commentExternalReference.externalReferenceStorage, + }, + }, + action_id: '0818e5e0-6648-11eb-a291-51bf6b175a53', + case_id: 'fcdedd20-6646-11eb-a291-51bf6b175a53', + comment_id: commentExternalReference.id, + owner: SECURITY_SOLUTION_OWNER, + }, + { + type: 'comment', + action: Actions.create, + created_at: '2021-02-03T17:48:30.616Z', + created_by: { + email: 'elastic@elastic.co', + full_name: 'Elastic', + username: 'elastic', + }, + payload: { + comment: { + type: commentPersistableState.type, + owner: commentPersistableState.owner, + persistableStateAttachmentState: commentPersistableState.persistableStateAttachmentState, + persistableStateAttachmentTypeId: commentPersistableState.persistableStateAttachmentTypeId, + }, + }, + action_id: '0818e5e0-6648-11eb-a291-51bf6b175a53', + case_id: 'fcdedd20-6646-11eb-a291-51bf6b175a53', + comment_id: commentPersistableState.id, owner: SECURITY_SOLUTION_OWNER, }, { @@ -357,11 +518,11 @@ export const userActions: CaseUserActionsResponse = [ username: 'elastic', }, payload: { - comment: { comment: 'a comment!', type: CommentType.user, owner: SECURITY_SOLUTION_OWNER }, + comment: { comment: comment.comment, type: comment.type, owner: comment.owner }, }, action_id: '0818e5e0-6648-11eb-a291-51bf6b175a53', case_id: 'fcdedd20-6646-11eb-a291-51bf6b175a53', - comment_id: 'comment-user-1', + comment_id: comment.id, owner: SECURITY_SOLUTION_OWNER, }, ]; diff --git a/x-pack/plugins/cases/server/client/cases/push.ts b/x-pack/plugins/cases/server/client/cases/push.ts index 6ddea5dd01bc9..6cca689057680 100644 --- a/x-pack/plugins/cases/server/client/cases/push.ts +++ b/x-pack/plugins/cases/server/client/cases/push.ts @@ -22,10 +22,11 @@ import { OWNER_FIELD, CommentType, CommentRequestAlertType, + CommentAttributes, } from '../../../common/api'; import { CASE_COMMENT_SAVED_OBJECT } from '../../../common/constants'; -import { createIncident, getCommentContextFromAttributes, getDurationInSeconds } from './utils'; +import { createIncident, getDurationInSeconds } from './utils'; import { createCaseError } from '../../common/error'; import { createAlertUpdateRequest, @@ -114,6 +115,7 @@ export const push = async ( logger, authorization, securityStartPlugin, + publicBaseUrl, } = clientArgs; try { @@ -139,32 +141,17 @@ export const push = async ( } const alertsInfo = getAlertInfoFromComments(theCase?.comments); - const alerts = await getAlerts(alertsInfo, clientArgs); - - const getMappingsResponse = await casesClientInternal.configuration.getMappings({ - connector: theCase.connector, - }); - - const mappings = - getMappingsResponse.length === 0 - ? await casesClientInternal.configuration.createMappings({ - connector: theCase.connector, - owner: theCase.owner, - }) - : getMappingsResponse[0].attributes.mappings; - const profiles = await getProfiles(theCase, securityStartPlugin); const externalServiceIncident = await createIncident({ - actionsClient, theCase, userActions, connector: connector as ActionConnector, - mappings, alerts, casesConnectors, userProfiles: profiles, + publicBaseUrl, }); const pushRes = await actionsClient.execute({ @@ -308,8 +295,7 @@ export const push = async ( attributes: { ...origComment.attributes, ...updatedComment?.attributes, - ...getCommentContextFromAttributes(origComment.attributes), - }, + } as CommentAttributes, version: updatedComment?.version ?? origComment.version, references: origComment?.references ?? [], }; diff --git a/x-pack/plugins/cases/server/client/cases/translations.ts b/x-pack/plugins/cases/server/client/cases/translations.ts new file mode 100644 index 0000000000000..819f5fd37ac14 --- /dev/null +++ b/x-pack/plugins/cases/server/client/cases/translations.ts @@ -0,0 +1,38 @@ +/* + * 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 { i18n } from '@kbn/i18n'; + +export const ADDED_BY = (user: string) => + i18n.translate('xpack.cases.server.addedBy', { + defaultMessage: 'Added by {user}', + values: { user }, + }); + +export const VIEW_IN_KIBANA = i18n.translate('xpack.cases.server.viewCaseInKibana', { + defaultMessage: 'For more details, view this case in Kibana', +}); + +export const VIEW_ALERTS_IN_KIBANA = i18n.translate('xpack.cases.server.viewAlertsInKibana', { + defaultMessage: 'For more details, view the alerts in Kibana', +}); + +export const CASE_URL = (url: string) => + i18n.translate('xpack.cases.server.caseUrl', { + defaultMessage: 'Case URL: {url}', + values: { url }, + }); + +export const ALERTS_URL = (url: string) => + i18n.translate('xpack.cases.server.alertsUrl', { + defaultMessage: 'Alerts URL: {url}', + values: { url }, + }); + +export const UNKNOWN = i18n.translate('xpack.cases.server.unknown', { + defaultMessage: 'Unknown', +}); diff --git a/x-pack/plugins/cases/server/client/cases/types.ts b/x-pack/plugins/cases/server/client/cases/types.ts index 6d56fa28dca59..0232d001dadb9 100644 --- a/x-pack/plugins/cases/server/client/cases/types.ts +++ b/x-pack/plugins/cases/server/client/cases/types.ts @@ -5,78 +5,14 @@ * 2.0. */ -import { - PushToServiceApiParams as JiraPushToServiceApiParams, - Incident as JiraIncident, -} from '@kbn/stack-connectors-plugin/server/connector_types/cases/jira/types'; -import { - PushToServiceApiParams as ResilientPushToServiceApiParams, - Incident as ResilientIncident, -} from '@kbn/stack-connectors-plugin/server/connector_types/cases/resilient/types'; -import { - PushToServiceApiParamsITSM as ServiceNowITSMPushToServiceApiParams, - PushToServiceApiParamsSIR as ServiceNowSIRPushToServiceApiParams, - ServiceNowITSMIncident, -} from '@kbn/stack-connectors-plugin/server/connector_types/lib/servicenow/types'; -import { UserProfile } from '@kbn/security-plugin/common'; -import { CaseResponse, ConnectorMappingsAttributes } from '../../../common/api'; - -export type Incident = JiraIncident | ResilientIncident | ServiceNowITSMIncident; -export type PushToServiceApiParams = - | JiraPushToServiceApiParams - | ResilientPushToServiceApiParams - | ServiceNowITSMPushToServiceApiParams - | ServiceNowSIRPushToServiceApiParams; - export type ExternalServiceParams = Record; -export interface BasicParams { - title: CaseResponse['title']; - description: CaseResponse['description']; - createdAt: CaseResponse['created_at']; - createdBy: CaseResponse['created_by']; - updatedAt: CaseResponse['updated_at']; - updatedBy: CaseResponse['updated_by']; -} - -export interface PipedField { - actionType: string; - key: string; - pipes: string[]; - value: string; -} -export interface PrepareFieldsForTransformArgs { - defaultPipes: string[]; - mappings: ConnectorMappingsAttributes[]; - params: { title: string; description: string }; -} -export interface EntityInformation { - createdAt: CaseResponse['created_at']; - createdBy: CaseResponse['created_by']; - updatedAt: CaseResponse['updated_at']; - updatedBy: CaseResponse['updated_by']; -} -export interface TransformerArgs { - date?: string; - previousValue?: string; - user?: string; - value: string; -} - -export type Transformer = (args: TransformerArgs) => TransformerArgs; -export interface TransformFieldsArgs { - currentIncident?: S; - fields: PipedField[]; - params: P; - userProfiles?: Map; -} - export interface ExternalServiceComment { comment: string; commentId: string; } -export interface MapIncident { +export interface ExternalServiceIncident { incident: ExternalServiceParams; comments: ExternalServiceComment[]; } diff --git a/x-pack/plugins/cases/server/client/cases/utils.test.ts b/x-pack/plugins/cases/server/client/cases/utils.test.ts index 3b00d4e284c21..2db72682224de 100644 --- a/x-pack/plugins/cases/server/client/cases/utils.test.ts +++ b/x-pack/plugins/cases/server/client/cases/utils.test.ts @@ -5,21 +5,19 @@ * 2.0. */ -import { actionsClientMock } from '@kbn/actions-plugin/server/actions_client.mock'; import { mockCases } from '../../routes/api/__fixtures__'; -import { BasicParams, ExternalServiceParams, Incident } from './types'; import { comment as commentObj, - mappings, - defaultPipes, - basicParams, userActions, commentAlert, commentAlertMultipleIds, + mappings, isolateCommentActions, releaseCommentActions, isolateCommentActionsMultipleTargets, + commentExternalReference, + commentPersistableState, } from './mock'; import { @@ -29,10 +27,9 @@ import { getDurationForUpdate, getEntity, getLatestPushInfo, - prepareFieldsForTransformation, - transformComments, - transformers, - transformFields, + mapCaseFieldsToExternalSystemFields, + formatComments, + addKibanaInformationToDescription, } from './utils'; import { Actions, CaseStatuses } from '../../../common/api'; import { flattenCaseSavedObject } from '../../common/utils'; @@ -40,58 +37,16 @@ import { SECURITY_SOLUTION_OWNER } from '../../../common/constants'; import { casesConnectors } from '../../connectors'; import { userProfiles, userProfilesMap } from '../user_profiles.mock'; -const formatComment = { - commentId: commentObj.id, - comment: 'Wow, good luck catching that bad meanie!', -}; - -const formatIsolateActionComment = { - commentId: isolateCommentActions.id, - comment: 'Isolating this for investigation', - actions: { - targets: [ - { - hostname: 'windows-host-1', - endpointId: '123', - }, - ], - type: 'isolate', - }, -}; - -const formatReleaseActionComment = { - commentId: releaseCommentActions.id, - comment: 'Releasing this for investigation', - actions: { - targets: [ - { - hostname: 'windows-host-1', - endpointId: '123', - }, - ], - type: 'unisolate', - }, -}; - -const formatIsolateCommentActionsMultipleTargets = { - commentId: isolateCommentActionsMultipleTargets.id, - comment: 'Isolating this for investigation', - actions: { - targets: [ - { - hostname: 'windows-host-1', - endpointId: '123', - }, - { - hostname: 'windows-host-2', - endpointId: '456', - }, - ], - type: 'isolate', - }, -}; - -const params = { ...basicParams }; +const allComments = [ + commentObj, + commentAlert, + commentAlertMultipleIds, + isolateCommentActions, + releaseCommentActions, + isolateCommentActionsMultipleTargets, + commentExternalReference, + commentPersistableState, +]; describe('utils', () => { describe('dedupAssignees', () => { @@ -114,420 +69,7 @@ describe('utils', () => { }); }); - describe('prepareFieldsForTransformation', () => { - test('prepare fields with defaults', () => { - const res = prepareFieldsForTransformation({ - defaultPipes, - params, - mappings, - }); - - expect(res).toEqual([ - { - actionType: 'overwrite', - key: 'short_description', - pipes: [], - value: 'a title', - }, - { - actionType: 'append', - key: 'description', - pipes: ['informationCreated', 'append'], - value: 'a description', - }, - ]); - }); - - test('prepare fields with default pipes', () => { - const res = prepareFieldsForTransformation({ - defaultPipes: ['myTestPipe'], - mappings, - params, - }); - - expect(res).toEqual([ - { - actionType: 'overwrite', - key: 'short_description', - pipes: [], - value: 'a title', - }, - { - actionType: 'append', - key: 'description', - pipes: ['myTestPipe', 'append'], - value: 'a description', - }, - ]); - }); - }); - - describe('transformFields', () => { - test('transform fields for creation correctly', () => { - const fields = prepareFieldsForTransformation({ - defaultPipes, - mappings, - params, - }); - - const res = transformFields({ - params, - fields, - }); - - expect(res).toEqual({ - short_description: 'a title', - description: 'a description (created at 2020-03-13T08:34:53.450Z by Elastic User)', - }); - }); - - test('transform fields for update correctly', () => { - const fields = prepareFieldsForTransformation({ - params, - mappings, - defaultPipes: ['informationUpdated'], - }); - - const res = transformFields({ - params: { - ...params, - updatedAt: '2020-03-15T08:34:53.450Z', - updatedBy: { - username: 'anotherUser', - full_name: 'Another User', - email: 'elastic@elastic.co', - }, - }, - fields, - currentIncident: { - short_description: 'first title', - description: 'first description (created at 2020-03-13T08:34:53.450Z by Elastic User)', - }, - }); - - expect(res).toEqual({ - short_description: 'a title', - description: - 'first description (created at 2020-03-13T08:34:53.450Z by Elastic User) \r\na description (updated at 2020-03-15T08:34:53.450Z by Another User)', - }); - }); - - test('add newline character to description', () => { - const fields = prepareFieldsForTransformation({ - params, - mappings, - defaultPipes: ['informationUpdated'], - }); - - const res = transformFields({ - params, - fields, - currentIncident: { - short_description: 'first title', - description: 'first description', - }, - }); - expect(res.description?.includes('\r\n')).toBe(true); - }); - - test('append username if fullname is undefined when create', () => { - const fields = prepareFieldsForTransformation({ - defaultPipes, - mappings, - params, - }); - - const res = transformFields({ - params: { - ...params, - createdBy: { full_name: '', username: 'elastic', email: 'elastic@elastic.co' }, - }, - fields, - }); - - expect(res).toEqual({ - short_description: 'a title', - description: 'a description (created at 2020-03-13T08:34:53.450Z by elastic)', - }); - }); - - test('append username if fullname is undefined when update', () => { - const fields = prepareFieldsForTransformation({ - defaultPipes: ['informationUpdated'], - mappings, - params, - }); - - const res = transformFields({ - params: { - ...params, - updatedAt: '2020-03-15T08:34:53.450Z', - updatedBy: { username: 'anotherUser', full_name: '', email: 'elastic@elastic.co' }, - }, - fields, - }); - - expect(res).toEqual({ - short_description: 'a title', - description: 'a description (updated at 2020-03-15T08:34:53.450Z by anotherUser)', - }); - }); - }); - - describe('transformComments', () => { - test('transform creation comments', () => { - const comments = [commentObj]; - const res = transformComments(comments, ['informationCreated'], new Map()); - expect(res).toEqual([ - { - ...formatComment, - comment: `${formatComment.comment} (created at ${comments[0].created_at} by ${comments[0].created_by.full_name})`, - }, - ]); - }); - - test('transform update comments', () => { - const comments = [ - { - ...commentObj, - updated_at: '2020-03-13T08:34:53.450Z', - updated_by: { - full_name: 'Another User', - username: 'another', - email: 'elastic@elastic.co', - }, - }, - ]; - const res = transformComments(comments, ['informationUpdated'], new Map()); - expect(res).toEqual([ - { - ...formatComment, - comment: `${formatComment.comment} (updated at ${comments[0].updated_at} by ${comments[0].updated_by.full_name})`, - }, - ]); - }); - - test('transform added comments', () => { - const comments = [commentObj]; - const res = transformComments(comments, ['informationAdded'], new Map()); - expect(res).toEqual([ - { - ...formatComment, - comment: `${formatComment.comment} (added at ${comments[0].created_at} by ${comments[0].created_by.full_name})`, - }, - ]); - }); - - test('transform comments without fullname', () => { - const comments = [{ ...commentObj, createdBy: { username: commentObj.created_by.username } }]; - // @ts-ignore testing no full_name - const res = transformComments(comments, ['informationAdded']); - expect(res).toEqual([ - { - ...formatComment, - comment: `${formatComment.comment} (added at ${comments[0].created_at} by ${comments[0].created_by.username})`, - }, - ]); - }); - - test('adds update user correctly', () => { - const comments = [ - { - ...commentObj, - updated_at: '2020-04-13T08:34:53.450Z', - updated_by: { full_name: 'Elastic2', username: 'elastic', email: 'elastic@elastic.co' }, - }, - ]; - const res = transformComments(comments, ['informationAdded'], new Map()); - expect(res).toEqual([ - { - ...formatComment, - comment: `${formatComment.comment} (added at ${comments[0].updated_at} by ${comments[0].updated_by.full_name})`, - }, - ]); - }); - - test('adds update user with empty fullname correctly', () => { - const comments = [ - { - ...commentObj, - updated_at: '2020-04-13T08:34:53.450Z', - updated_by: { full_name: '', username: 'elastic2', email: 'elastic@elastic.co' }, - }, - ]; - const res = transformComments(comments, ['informationAdded'], new Map()); - expect(res).toEqual([ - { - ...formatComment, - comment: `${formatComment.comment} (added at ${comments[0].updated_at} by ${comments[0].updated_by.username})`, - }, - ]); - }); - - test('transform isolate action comment', () => { - const comments = [isolateCommentActions]; - const res = transformComments(comments, ['informationCreated'], new Map()); - const actionText = `Isolated host ${formatIsolateActionComment.actions.targets[0].hostname} with comment: ${formatIsolateActionComment.comment}`; - expect(res).toEqual([ - { - commentId: formatIsolateActionComment.commentId, - comment: `${actionText} (created at ${comments[0].created_at} by ${comments[0].created_by.full_name})`, - }, - ]); - }); - - test('transform release action comment', () => { - const comments = [releaseCommentActions]; - const res = transformComments(comments, ['informationCreated'], new Map()); - const actionText = `Released host ${formatReleaseActionComment.actions.targets[0].hostname} with comment: ${formatReleaseActionComment.comment}`; - expect(res).toEqual([ - { - commentId: formatReleaseActionComment.commentId, - comment: `${actionText} (created at ${comments[0].created_at} by ${comments[0].created_by.full_name})`, - }, - ]); - }); - - test('transform isolate action comment with multiple hosts', () => { - const comments = [isolateCommentActionsMultipleTargets]; - const res = transformComments(comments, ['informationCreated'], new Map()); - const actionText = `Isolated host ${formatIsolateCommentActionsMultipleTargets.actions.targets[0].hostname} and 1 more with comment: ${formatIsolateCommentActionsMultipleTargets.comment}`; - expect(res).toEqual([ - { - commentId: formatIsolateCommentActionsMultipleTargets.commentId, - comment: `${actionText} (created at ${comments[0].created_at} by ${comments[0].created_by.full_name})`, - }, - ]); - }); - }); - - describe('transformers', () => { - const { informationCreated, informationUpdated, informationAdded, append } = transformers; - describe('informationCreated', () => { - test('transforms correctly', () => { - const res = informationCreated({ - value: 'a value', - date: '2020-04-15T08:19:27.400Z', - user: 'elastic', - }); - expect(res).toEqual({ value: 'a value (created at 2020-04-15T08:19:27.400Z by elastic)' }); - }); - - test('transforms correctly without optional fields', () => { - const res = informationCreated({ - value: 'a value', - }); - expect(res).toEqual({ value: 'a value (created at by )' }); - }); - - test('returns correctly rest fields', () => { - const res = informationCreated({ - value: 'a value', - date: '2020-04-15T08:19:27.400Z', - user: 'elastic', - previousValue: 'previous value', - }); - expect(res).toEqual({ - value: 'a value (created at 2020-04-15T08:19:27.400Z by elastic)', - previousValue: 'previous value', - }); - }); - }); - - describe('informationUpdated', () => { - test('transforms correctly', () => { - const res = informationUpdated({ - value: 'a value', - date: '2020-04-15T08:19:27.400Z', - user: 'elastic', - }); - expect(res).toEqual({ value: 'a value (updated at 2020-04-15T08:19:27.400Z by elastic)' }); - }); - - test('transforms correctly without optional fields', () => { - const res = informationUpdated({ - value: 'a value', - }); - expect(res).toEqual({ value: 'a value (updated at by )' }); - }); - - test('returns correctly rest fields', () => { - const res = informationUpdated({ - value: 'a value', - date: '2020-04-15T08:19:27.400Z', - user: 'elastic', - previousValue: 'previous value', - }); - expect(res).toEqual({ - value: 'a value (updated at 2020-04-15T08:19:27.400Z by elastic)', - previousValue: 'previous value', - }); - }); - }); - - describe('informationAdded', () => { - test('transforms correctly', () => { - const res = informationAdded({ - value: 'a value', - date: '2020-04-15T08:19:27.400Z', - user: 'elastic', - }); - expect(res).toEqual({ value: 'a value (added at 2020-04-15T08:19:27.400Z by elastic)' }); - }); - - test('transforms correctly without optional fields', () => { - const res = informationAdded({ - value: 'a value', - }); - expect(res).toEqual({ value: 'a value (added at by )' }); - }); - - test('returns correctly rest fields', () => { - const res = informationAdded({ - value: 'a value', - date: '2020-04-15T08:19:27.400Z', - user: 'elastic', - previousValue: 'previous value', - }); - expect(res).toEqual({ - value: 'a value (added at 2020-04-15T08:19:27.400Z by elastic)', - previousValue: 'previous value', - }); - }); - }); - - describe('append', () => { - test('transforms correctly', () => { - const res = append({ - value: 'a value', - previousValue: 'previous value', - }); - expect(res).toEqual({ value: 'previous value \r\na value' }); - }); - - test('transforms correctly without optional fields', () => { - const res = append({ - value: 'a value', - }); - expect(res).toEqual({ value: 'a value' }); - }); - - test('returns correctly rest fields', () => { - const res = append({ - value: 'a value', - user: 'elastic', - previousValue: 'previous value', - }); - expect(res).toEqual({ - value: 'previous value \r\na value', - user: 'elastic', - }); - }); - }); - }); - describe('createIncident', () => { - let actionsMock = actionsClientMock.create(); const theCase = { ...flattenCaseSavedObject({ savedObject: mockCases[0], @@ -549,11 +91,9 @@ describe('utils', () => { it('creates an external incident', async () => { const res = await createIncident({ - actionsClient: actionsMock, theCase, userActions: [], connector, - mappings, alerts: [], casesConnectors, }); @@ -564,94 +104,81 @@ describe('utils', () => { labels: ['defacement'], issueType: null, parent: null, - short_description: 'Super Bad Security Issue', + summary: 'Super Bad Security Issue', description: - 'This is a brand new case of a bad meanie defacing data (created at 2019-11-25T21:54:48.952Z by elastic)', + 'This is a brand new case of a bad meanie defacing data\n\nAdded by elastic.', externalId: null, }, comments: [], }); }); - it('it creates comments correctly', async () => { + it('formats the connector fields correctly', async () => { + const caseWithConnector = { + ...flattenCaseSavedObject({ + savedObject: mockCases[2], + }), + comments: [], + totalComments: 0, + }; + const res = await createIncident({ - actionsClient: actionsMock, - theCase: { - ...theCase, - comments: [{ ...commentObj, id: 'comment-user-1' }], - }, - userActions, + theCase: caseWithConnector, + userActions: [], connector, - mappings, alerts: [], casesConnectors, }); - expect(res.comments).toEqual([ - { - comment: - 'Wow, good luck catching that bad meanie! (added at 2019-11-25T21:55:00.177Z by elastic)', - commentId: 'comment-user-1', + expect(res).toEqual({ + incident: { + priority: 'High', + labels: ['LOLBins'], + issueType: 'Task', + parent: null, + summary: 'Another bad one', + description: 'Oh no, a bad meanie going LOLBins all over the place!\n\nAdded by elastic.', + externalId: null, }, - ]); + comments: [], + }); }); - it('it does NOT creates comments when mapping is nothing', async () => { + it('creates comments correctly', async () => { const res = await createIncident({ - actionsClient: actionsMock, theCase: { ...theCase, - comments: [{ ...commentObj, id: 'comment-user-1' }], + comments: [commentObj], }, userActions, connector, - mappings: [ - mappings[0], - mappings[1], - { - source: 'comments', - target: 'comments', - action_type: 'nothing', - }, - ], alerts: [], casesConnectors, }); - expect(res.comments).toEqual([]); + expect(res.comments).toEqual([ + { + comment: 'Wow, good luck catching that bad meanie!\n\nAdded by elastic.', + commentId: 'comment-user-1', + }, + ]); }); - it('it adds the total alert comments correctly', async () => { + it('adds the total alert comments correctly', async () => { const res = await createIncident({ - actionsClient: actionsMock, theCase: { ...theCase, - comments: [ - { ...commentObj, id: 'comment-user-1' }, - { ...commentAlert, id: 'comment-alert-1' }, - { - ...commentAlertMultipleIds, - }, - ], + comments: [commentObj, commentAlert, commentAlertMultipleIds], }, userActions, connector, - mappings: [ - ...mappings, - { - source: 'comments', - target: 'comments', - action_type: 'nothing', - }, - ], alerts: [], casesConnectors, }); expect(res.comments).toEqual([ { - comment: - 'Wow, good luck catching that bad meanie! (added at 2019-11-25T21:55:00.177Z by elastic)', + comment: 'Wow, good luck catching that bad meanie!\n\nAdded by elastic.', commentId: 'comment-user-1', }, { @@ -661,24 +188,21 @@ describe('utils', () => { ]); }); - it('it filters out the alerts from the comments correctly', async () => { + it('filters out the alerts from the comments correctly', async () => { const res = await createIncident({ - actionsClient: actionsMock, theCase: { ...theCase, comments: [{ ...commentObj, id: 'comment-user-1' }, commentAlertMultipleIds], }, userActions, connector, - mappings, alerts: [], casesConnectors, }); expect(res.comments).toEqual([ { - comment: - 'Wow, good luck catching that bad meanie! (added at 2019-11-25T21:55:00.177Z by elastic)', + comment: 'Wow, good luck catching that bad meanie!\n\nAdded by elastic.', commentId: 'comment-user-1', }, { @@ -690,7 +214,6 @@ describe('utils', () => { it('does not add the alerts count comment if all alerts have been pushed', async () => { const res = await createIncident({ - actionsClient: actionsMock, theCase: { ...theCase, comments: [ @@ -700,40 +223,26 @@ describe('utils', () => { }, userActions, connector, - mappings, alerts: [], casesConnectors, }); expect(res.comments).toEqual([ { - comment: - 'Wow, good luck catching that bad meanie! (added at 2019-11-25T21:55:00.177Z by elastic)', + comment: 'Wow, good luck catching that bad meanie!\n\nAdded by elastic.', commentId: 'comment-user-1', }, ]); }); - it('updates an existing incident', async () => { - const existingIncidentData = { - priority: null, - issueType: null, - parent: null, - short_description: 'fun title', - description: 'fun description', - }; - - const execute = jest.fn().mockReturnValue(existingIncidentData); - actionsMock = { ...actionsMock, execute }; - + it('adds the backlink to cases correctly', async () => { const res = await createIncident({ - actionsClient: actionsMock, theCase, - userActions, + userActions: [], connector, - mappings, alerts: [], casesConnectors, + publicBaseUrl: 'https://example.com', }); expect(res).toEqual({ @@ -742,238 +251,599 @@ describe('utils', () => { labels: ['defacement'], issueType: null, parent: null, + summary: 'Super Bad Security Issue', description: - 'fun description \r\nThis is a brand new case of a bad meanie defacing data (updated at 2019-11-25T21:54:48.952Z by elastic)', - externalId: 'external-id', - short_description: 'Super Bad Security Issue', + 'This is a brand new case of a bad meanie defacing data\n\nAdded by elastic.\nFor more details, view this case in Kibana.\nCase URL: https://example.com/app/security/cases/mock-id-1', + externalId: null, }, comments: [], }); }); - it('throws error when existing incident throws', async () => { - expect.assertions(2); - const execute = jest.fn().mockImplementation(() => { - throw new Error('exception'); + it('adds the user profile correctly to description', async () => { + const res = await createIncident({ + theCase: { + ...theCase, + created_by: { ...theCase.created_by, profile_uid: userProfiles[0].uid }, + updated_by: null, + }, + userActions: [], + connector, + alerts: [], + casesConnectors, + userProfiles: userProfilesMap, }); - actionsMock = { ...actionsMock, execute }; - createIncident({ - actionsClient: actionsMock, - theCase, + expect(res).toEqual({ + incident: { + priority: null, + labels: ['defacement'], + issueType: null, + parent: null, + summary: 'Super Bad Security Issue', + description: + 'This is a brand new case of a bad meanie defacing data\n\nAdded by Damaged Raccoon.', + externalId: null, + }, + comments: [], + }); + }); + + it('adds the user profile correctly to comments', async () => { + const res = await createIncident({ + theCase: { + ...theCase, + created_by: { ...theCase.created_by, profile_uid: userProfiles[0].uid }, + updated_by: null, + comments: [ + { + ...commentObj, + created_by: { ...theCase.created_by, profile_uid: userProfiles[0].uid }, + updated_by: null, + }, + ], + totalComment: 1, + }, userActions, connector, - mappings, alerts: [], casesConnectors, - }).catch((e) => { - expect(e).not.toBeNull(); - expect(e).toEqual( - new Error( - `Retrieving Incident by id external-id from .jira failed with exception: Error: exception` - ) - ); + userProfiles: userProfilesMap, }); - }); - describe('getLatestPushInfo', () => { - it('it returns the latest push information correctly', async () => { - const res = getLatestPushInfo('456', userActions); - expect(res).toEqual({ - index: 4, - pushedInfo: { - connector_id: '456', - connector_name: 'ServiceNow SN', - external_id: 'external-id', - external_title: 'SIR0010037', - external_url: - 'https://dev92273.service-now.com/nav_to.do?uri=sn_si_incident.do?sys_id=external-id', - pushed_at: '2021-02-03T17:45:29.400Z', - pushed_by: { - email: 'elastic@elastic.co', - full_name: 'Elastic', - username: 'elastic', - }, + expect(res).toEqual({ + incident: { + priority: null, + labels: ['defacement'], + issueType: null, + parent: null, + summary: 'Super Bad Security Issue', + description: + 'This is a brand new case of a bad meanie defacing data\n\nAdded by Damaged Raccoon.', + externalId: 'external-id', + }, + comments: [ + { + comment: 'Wow, good luck catching that bad meanie!\n\nAdded by Damaged Raccoon.', + commentId: 'comment-user-1', }, - }); + ], }); + }); - it('it returns null when there are not actions', async () => { - const res = getLatestPushInfo('456', []); - expect(res).toBe(null); + it('does not map if the connector is not registered', async () => { + const res = await createIncident({ + theCase, + userActions: [], + // @ts-expect-error: not existing connector + connector: { actionTypeId: '.not-exist' }, + alerts: [], + casesConnectors, }); - it('it returns null when there are no push user action', async () => { - const res = getLatestPushInfo('456', [userActions[0]]); - expect(res).toBe(null); + expect(res).toEqual({ + incident: { + externalId: null, + }, + comments: [], }); + }); + + it('adds a backlink to the total alert comments correctly', async () => { + const res = await createIncident({ + theCase: { + ...theCase, + comments: [commentObj, commentAlert, commentAlertMultipleIds], + }, + userActions, + connector, + alerts: [], + casesConnectors, + publicBaseUrl: 'https://example.com', + }); + + expect(res.comments).toEqual([ + { + comment: 'Wow, good luck catching that bad meanie!\n\nAdded by elastic.', + commentId: 'comment-user-1', + }, + { + comment: + 'Elastic Alerts attached to the case: 3\n\nFor more details, view the alerts in Kibana\nAlerts URL: https://example.com/app/security/cases/mock-id-1/?tabId=alerts', + commentId: 'mock-id-1-total-alerts', + }, + ]); + }); + }); - it('it returns the correct push information when with multiple push on different connectors', async () => { - const res = getLatestPushInfo('456', [ - ...userActions.slice(0, 3), + describe('mapCaseFieldsToExternalSystemFields', () => { + const caseFields = { title: 'My title', description: 'my desc' }; + + it('maps correctly', () => { + expect(mapCaseFieldsToExternalSystemFields(caseFields, mappings)).toEqual({ + description: 'my desc', + short_description: 'My title', + }); + }); + + it('does not map unknown case fields', () => { + // @ts-expect-error + expect(mapCaseFieldsToExternalSystemFields({ notCaseField: 'test' }, mappings)).toEqual({}); + }); + + it('does not map unknown source', () => { + expect( + mapCaseFieldsToExternalSystemFields(caseFields, [ { - type: 'pushed', - action: Actions.push_to_service, - created_at: '2021-02-03T17:45:29.400Z', - created_by: { - email: 'elastic@elastic.co', - full_name: 'Elastic', - username: 'elastic', - }, - payload: { - externalService: { - pushed_at: '2021-02-03T17:45:29.400Z', - pushed_by: { - username: 'elastic', - full_name: 'Elastic', - email: 'elastic@elastic.co', - }, - connector_id: '123', - connector_name: 'ServiceNow SN', - external_id: 'external-id', - external_title: 'SIR0010037', - external_url: - 'https://dev92273.service-now.com/nav_to.do?uri=sn_si_incident.do?sys_id=external-id', - }, - }, - action_id: '9b91d8f0-6647-11eb-a291-51bf6b175a53', - case_id: 'fcdedd20-6646-11eb-a291-51bf6b175a53', - comment_id: null, - owner: SECURITY_SOLUTION_OWNER, + // @ts-expect-error + source: 'not-a-case-field', + target: 'short_description', + action_type: 'overwrite', }, - ]); - - expect(res).toEqual({ - index: 1, - pushedInfo: { - connector_id: '456', - connector_name: 'ServiceNow SN', - external_id: 'external-id', - external_title: 'SIR0010037', - external_url: - 'https://dev92273.service-now.com/nav_to.do?uri=sn_si_incident.do?sys_id=external-id', - pushed_at: '2021-02-03T17:41:26.108Z', - pushed_by: { - email: 'elastic@elastic.co', - full_name: 'Elastic', - username: 'elastic', - }, + ]) + ).toEqual({}); + }); + + it('does not map if target=not_mapped', () => { + expect( + mapCaseFieldsToExternalSystemFields(caseFields, [ + { + source: 'title', + target: 'not_mapped', + action_type: 'overwrite', }, - }); - }); + ]) + ).toEqual({}); }); + }); + + describe('formatComments', () => { + it('formats comments correctly', () => { + const theCase = { + ...flattenCaseSavedObject({ + savedObject: mockCases[0], + }), + comments: allComments, + totalComments: allComments.length, + }; - describe('getClosedInfoForUpdate', () => { - const date = '2021-02-03T17:41:26.108Z'; - const user = { full_name: 'Elastic', username: 'elastic', email: 'elastic@elastic.co' }; + const latestPushInfo = getLatestPushInfo('not-exists', userActions); - it('returns the correct closed info when the case closes', async () => { - expect( - getClosedInfoForUpdate({ status: CaseStatuses.closed, closedDate: date, user }) - ).toEqual({ - closed_at: date, - closed_by: user, - }); - }); + expect( + formatComments({ userActions, theCase, latestPushInfo, userProfiles: userProfilesMap }) + ).toEqual([ + { + comment: 'Wow, good luck catching that bad meanie!\n\nAdded by elastic.', + commentId: 'comment-user-1', + }, + { + comment: + 'Isolated host windows-host-1 with comment: Isolating this for investigation\n\nAdded by elastic.', + commentId: 'mock-action-comment-1', + }, + { + comment: + 'Released host windows-host-1 with comment: Releasing this for investigation\n\nAdded by elastic.', + commentId: 'mock-action-comment-2', + }, + { + comment: + 'Isolated host windows-host-1 and 1 more with comment: Isolating this for investigation\n\nAdded by elastic.', + commentId: 'mock-action-comment-3', + }, + { + comment: 'Elastic Alerts attached to the case: 3', + commentId: 'mock-id-1-total-alerts', + }, + ]); + }); + + it('filters unsupported comments and adds the user profile information correctly', () => { + const theCase = { + ...flattenCaseSavedObject({ + savedObject: mockCases[0], + }), + comments: allComments.map((theComment) => ({ + ...theComment, + created_by: { ...theComment.created_by, profile_uid: userProfiles[0].uid }, + updated_by: null, + })), + totalComments: allComments.length, + }; + + const latestPushInfo = getLatestPushInfo('not-exists', userActions); + + expect( + formatComments({ userActions, theCase, latestPushInfo, userProfiles: userProfilesMap }) + ).toEqual([ + { + comment: 'Wow, good luck catching that bad meanie!\n\nAdded by Damaged Raccoon.', + commentId: 'comment-user-1', + }, + { + comment: + 'Isolated host windows-host-1 with comment: Isolating this for investigation\n' + + '\n' + + 'Added by Damaged Raccoon.', + commentId: 'mock-action-comment-1', + }, + { + comment: + 'Released host windows-host-1 with comment: Releasing this for investigation\n' + + '\n' + + 'Added by Damaged Raccoon.', + commentId: 'mock-action-comment-2', + }, + { + comment: + 'Isolated host windows-host-1 and 1 more with comment: Isolating this for investigation\n' + + '\n' + + 'Added by Damaged Raccoon.', + commentId: 'mock-action-comment-3', + }, + { + comment: 'Elastic Alerts attached to the case: 3', + commentId: 'mock-id-1-total-alerts', + }, + ]); + }); + + it('formats only comments that have not been pushed', () => { + const theCase = { + ...flattenCaseSavedObject({ + savedObject: mockCases[0], + }), + comments: allComments, + totalComments: allComments.length, + }; + + const latestPushInfo = getLatestPushInfo('456', userActions); + expect( + formatComments({ userActions, theCase, latestPushInfo, userProfiles: userProfilesMap }) + ).toEqual([ + { + comment: 'Wow, good luck catching that bad meanie!\n\nAdded by elastic.', + commentId: 'comment-user-1', + }, + { + comment: 'Elastic Alerts attached to the case: 3', + commentId: 'mock-id-1-total-alerts', + }, + ]); + }); + + it('filters out alert comments correctly and appends the total alerts on the end', () => { + const theCase = { + ...flattenCaseSavedObject({ + savedObject: mockCases[0], + }), + comments: [commentAlert], + totalComments: 1, + }; - it.each([[CaseStatuses.open], [CaseStatuses['in-progress']]])( - 'returns the correct closed info when the case %s', - async (status) => { - expect(getClosedInfoForUpdate({ status, closedDate: date, user })).toEqual({ - closed_at: null, - closed_by: null, - }); - } + const latestPushInfo = getLatestPushInfo('not-exists', userActions); + + expect( + formatComments({ userActions, theCase, latestPushInfo, userProfiles: userProfilesMap }) + ).toEqual([ + { + comment: 'Elastic Alerts attached to the case: 1', + commentId: 'mock-id-1-total-alerts', + }, + ]); + }); + + it('returns an empty array when there are no comments', () => { + const theCase = { + ...flattenCaseSavedObject({ + savedObject: mockCases[0], + }), + comments: [], + totalComments: 0, + }; + + const latestPushInfo = getLatestPushInfo('456', userActions); + + expect( + formatComments({ userActions, theCase, latestPushInfo, userProfiles: userProfilesMap }) + ).toEqual([]); + }); + + it('returns an empty array when there the comment has been pushed', () => { + const theCase = { + ...flattenCaseSavedObject({ + savedObject: mockCases[0], + }), + comments: [isolateCommentActions], + totalComments: 1, + }; + + const latestPushInfo = getLatestPushInfo('456', userActions); + + expect( + formatComments({ userActions, theCase, latestPushInfo, userProfiles: userProfilesMap }) + ).toEqual([]); + }); + + it('adds a backlink to the total alerts comment', () => { + const theCase = { + ...flattenCaseSavedObject({ + savedObject: mockCases[0], + }), + comments: [commentAlert], + totalComments: 1, + }; + + const latestPushInfo = getLatestPushInfo('not-exists', userActions); + + expect( + formatComments({ + userActions, + theCase, + latestPushInfo, + userProfiles: userProfilesMap, + publicBaseUrl: 'https://example.com', + }) + ).toEqual([ + { + comment: + 'Elastic Alerts attached to the case: 1\n\nFor more details, view the alerts in Kibana\nAlerts URL: https://example.com/app/security/cases/mock-id-1/?tabId=alerts', + commentId: 'mock-id-1-total-alerts', + }, + ]); + }); + }); + + describe('addKibanaInformationToDescription', () => { + const theCase = { + ...flattenCaseSavedObject({ + savedObject: mockCases[0], + }), + comments: [], + totalComments: 0, + }; + const publicBaseUrl = 'https://example.com'; + + it('adds the kibana information to description correctly', () => { + expect( + addKibanaInformationToDescription( + { + ...theCase, + created_by: { ...theCase.created_by, profile_uid: userProfiles[0].uid }, + updated_by: null, + }, + userProfilesMap, + publicBaseUrl + ) + ).toBe( + 'This is a brand new case of a bad meanie defacing data\n\nAdded by Damaged Raccoon.\nFor more details, view this case in Kibana.\nCase URL: https://example.com/app/security/cases/mock-id-1' ); + }); + + it('adds the kibana information to description correctly without publicBaseUrl and userProfilesMap', () => { + expect(addKibanaInformationToDescription(theCase)).toBe( + 'This is a brand new case of a bad meanie defacing data\n\nAdded by elastic.' + ); + }); + }); - it('returns undefined if the status is not provided', async () => { - expect(getClosedInfoForUpdate({ closedDate: date, user })).toBe(undefined); + describe('getLatestPushInfo', () => { + it('it returns the latest push information correctly', async () => { + const res = getLatestPushInfo('456', userActions); + expect(res).toEqual({ + index: 9, + pushedInfo: { + connector_id: '456', + connector_name: 'ServiceNow SN', + external_id: 'external-id', + external_title: 'SIR0010037', + external_url: + 'https://dev92273.service-now.com/nav_to.do?uri=sn_si_incident.do?sys_id=external-id', + pushed_at: '2021-02-03T17:45:29.400Z', + pushed_by: { + email: 'elastic@elastic.co', + full_name: 'Elastic', + username: 'elastic', + }, + }, }); }); - describe('getDurationForUpdate', () => { - const createdAt = '2021-11-23T19:00:00Z'; - const closedAt = '2021-11-23T19:02:00Z'; + it('it returns null when there are not actions', async () => { + const res = getLatestPushInfo('456', []); + expect(res).toBe(null); + }); - it('returns the correct duration when the case closes', () => { - expect(getDurationForUpdate({ status: CaseStatuses.closed, closedAt, createdAt })).toEqual({ - duration: 120, - }); + it('it returns null when there are no push user action', async () => { + const res = getLatestPushInfo('456', [userActions[0]]); + expect(res).toBe(null); + }); + + it('it returns the correct push information when with multiple push on different connectors', async () => { + const res = getLatestPushInfo('456', [ + ...userActions.slice(0, 3), + { + type: 'pushed', + action: Actions.push_to_service, + created_at: '2021-02-03T17:45:29.400Z', + created_by: { + email: 'elastic@elastic.co', + full_name: 'Elastic', + username: 'elastic', + }, + payload: { + externalService: { + pushed_at: '2021-02-03T17:45:29.400Z', + pushed_by: { + username: 'elastic', + full_name: 'Elastic', + email: 'elastic@elastic.co', + }, + connector_id: '123', + connector_name: 'ServiceNow SN', + external_id: 'external-id', + external_title: 'SIR0010037', + external_url: + 'https://dev92273.service-now.com/nav_to.do?uri=sn_si_incident.do?sys_id=external-id', + }, + }, + action_id: '9b91d8f0-6647-11eb-a291-51bf6b175a53', + case_id: 'fcdedd20-6646-11eb-a291-51bf6b175a53', + comment_id: null, + owner: SECURITY_SOLUTION_OWNER, + }, + ]); + + expect(res).toEqual({ + index: 1, + pushedInfo: { + connector_id: '456', + connector_name: 'ServiceNow SN', + external_id: 'external-id', + external_title: 'SIR0010037', + external_url: + 'https://dev92273.service-now.com/nav_to.do?uri=sn_si_incident.do?sys_id=external-id', + pushed_at: '2021-02-03T17:41:26.108Z', + pushed_by: { + email: 'elastic@elastic.co', + full_name: 'Elastic', + username: 'elastic', + }, + }, }); + }); + }); - it.each([[CaseStatuses.open], [CaseStatuses['in-progress']]])( - 'returns the correct duration when the case %s', - (status) => { - expect(getDurationForUpdate({ status, closedAt, createdAt })).toEqual({ - duration: null, - }); - } - ); + describe('getClosedInfoForUpdate', () => { + const date = '2021-02-03T17:41:26.108Z'; + const user = { full_name: 'Elastic', username: 'elastic', email: 'elastic@elastic.co' }; - it('returns undefined if the status is not provided', async () => { - expect(getDurationForUpdate({ closedAt, createdAt })).toBe(undefined); + it('returns the correct closed info when the case closes', async () => { + expect( + getClosedInfoForUpdate({ status: CaseStatuses.closed, closedDate: date, user }) + ).toEqual({ + closed_at: date, + closed_by: user, }); + }); - it.each([['invalid'], [null]])( - 'returns undefined if the createdAt date is %s', - (createdAtInvalid) => { - expect( - getDurationForUpdate({ - status: CaseStatuses.closed, - closedAt, - // @ts-expect-error - createdAt: createdAtInvalid, - }) - ).toBe(undefined); - } - ); + it.each([[CaseStatuses.open], [CaseStatuses['in-progress']]])( + 'returns the correct closed info when the case %s', + async (status) => { + expect(getClosedInfoForUpdate({ status, closedDate: date, user })).toEqual({ + closed_at: null, + closed_by: null, + }); + } + ); - it.each([['invalid'], [null]])( - 'returns undefined if the closedAt date is %s', - (closedAtInvalid) => { - expect( - getDurationForUpdate({ - status: CaseStatuses.closed, - // @ts-expect-error - closedAt: closedAtInvalid, - createdAt, - }) - ).toBe(undefined); - } - ); + it('returns undefined if the status is not provided', async () => { + expect(getClosedInfoForUpdate({ closedDate: date, user })).toBe(undefined); + }); + }); + + describe('getDurationForUpdate', () => { + const createdAt = '2021-11-23T19:00:00Z'; + const closedAt = '2021-11-23T19:02:00Z'; + + it('returns the correct duration when the case closes', () => { + expect(getDurationForUpdate({ status: CaseStatuses.closed, closedAt, createdAt })).toEqual({ + duration: 120, + }); + }); + + it.each([[CaseStatuses.open], [CaseStatuses['in-progress']]])( + 'returns the correct duration when the case %s', + (status) => { + expect(getDurationForUpdate({ status, closedAt, createdAt })).toEqual({ + duration: null, + }); + } + ); - it('returns undefined if created_at > closed_at', async () => { + it('returns undefined if the status is not provided', async () => { + expect(getDurationForUpdate({ closedAt, createdAt })).toBe(undefined); + }); + + it.each([['invalid'], [null]])( + 'returns undefined if the createdAt date is %s', + (createdAtInvalid) => { expect( getDurationForUpdate({ status: CaseStatuses.closed, - closedAt: '2021-11-23T19:00:00Z', - createdAt: '2021-11-23T19:05:00Z', + closedAt, + // @ts-expect-error + createdAt: createdAtInvalid, }) ).toBe(undefined); - }); + } + ); - it('rounds the seconds correctly', () => { + it.each([['invalid'], [null]])( + 'returns undefined if the closedAt date is %s', + (closedAtInvalid) => { expect( getDurationForUpdate({ status: CaseStatuses.closed, - createdAt: '2022-04-11T15:56:00.087Z', - closedAt: '2022-04-11T15:58:56.187Z', + // @ts-expect-error + closedAt: closedAtInvalid, + createdAt, }) - ).toEqual({ - duration: 176, - }); + ).toBe(undefined); + } + ); + + it('returns undefined if created_at > closed_at', async () => { + expect( + getDurationForUpdate({ + status: CaseStatuses.closed, + closedAt: '2021-11-23T19:00:00Z', + createdAt: '2021-11-23T19:05:00Z', + }) + ).toBe(undefined); + }); + + it('rounds the seconds correctly', () => { + expect( + getDurationForUpdate({ + status: CaseStatuses.closed, + createdAt: '2022-04-11T15:56:00.087Z', + closedAt: '2022-04-11T15:58:56.187Z', + }) + ).toEqual({ + duration: 176, }); + }); - it('rounds the zero correctly', () => { - expect( - getDurationForUpdate({ - status: CaseStatuses.closed, - createdAt: '2022-04-11T15:56:00.087Z', - closedAt: '2022-04-11T15:56:00.187Z', - }) - ).toEqual({ - duration: 0, - }); + it('rounds the zero correctly', () => { + expect( + getDurationForUpdate({ + status: CaseStatuses.closed, + createdAt: '2022-04-11T15:56:00.087Z', + closedAt: '2022-04-11T15:56:00.187Z', + }) + ).toEqual({ + duration: 0, }); }); }); @@ -989,9 +859,7 @@ describe('utils', () => { it('returns the username when full name is empty for updatedBy', () => { expect( getEntity({ - createdAt: '', createdBy: { email: null, full_name: null, username: null }, - updatedAt: '', updatedBy: { email: null, full_name: '', username: 'updatedBy_username' }, }) ).toEqual('updatedBy_username'); @@ -1000,43 +868,35 @@ describe('utils', () => { it('returns the username when full name is empty for createdBy', () => { expect( getEntity({ - createdAt: '', createdBy: { email: null, full_name: '', username: 'createdBy_username' }, - updatedAt: '', updatedBy: null, }) ).toEqual('createdBy_username'); }); - it('returns an empty string with neither updatedBy or createdBy are defined', () => { + it('returns Unknown with neither updatedBy or createdBy are defined', () => { expect( getEntity({ - createdAt: '', - // @ts-expect-error createdBy should be defined but for testing purposes we want to make sure the function handles null + // @ts-expect-error createdBy: null, - updatedAt: '', updatedBy: null, }) - ).toEqual(''); + ).toEqual('Unknown'); }); - it('returns an empty string when createdBy fields are all null', () => { + it('returns Unknown when createdBy fields are all null', () => { expect( getEntity({ - createdAt: '', createdBy: { email: null, full_name: null, username: null }, - updatedAt: '', updatedBy: null, }) - ).toEqual(''); + ).toEqual('Unknown'); }); it('returns the full name of updatedBy when available', () => { expect( getEntity({ - createdAt: '', createdBy: { email: null, full_name: 'createdBy_full_name', username: null }, - updatedAt: '', updatedBy: { full_name: 'updatedBy_full_name', email: null, username: null }, }) ).toEqual('updatedBy_full_name'); @@ -1045,35 +905,29 @@ describe('utils', () => { it('returns the username of updatedBy when available', () => { expect( getEntity({ - createdAt: '', createdBy: { email: null, full_name: null, username: 'createdBy_username' }, - updatedAt: '', updatedBy: { full_name: null, email: null, username: 'updatedBy_username' }, }) ).toEqual('updatedBy_username'); }); - it('returns an empty string when updatedBy username is null', () => { + it('returns Unknown when updatedBy username is null', () => { expect( getEntity({ - createdAt: '', createdBy: { email: null, full_name: null, username: 'createdBy_username' }, - updatedAt: '', updatedBy: { full_name: null, email: null, username: null }, }) - ).toEqual(''); + ).toEqual('Unknown'); }); it('returns the full name of createdBy when available', () => { expect( getEntity({ - createdAt: '', createdBy: { email: null, full_name: 'createdBy_full_name', username: 'createdBy_username', }, - updatedAt: '', updatedBy: null, }) ).toEqual('createdBy_full_name'); @@ -1082,9 +936,7 @@ describe('utils', () => { it('returns the username of createdBy when available', () => { expect( getEntity({ - createdAt: '', createdBy: { email: null, full_name: null, username: 'createdBy_username' }, - updatedAt: '', updatedBy: null, }) ).toEqual('createdBy_username'); @@ -1093,9 +945,7 @@ describe('utils', () => { it('returns updatedBy full name when the profile uid is not found', () => { expect( getEntity({ - createdAt: '', createdBy: { email: null, full_name: null, username: 'createdBy_username' }, - updatedAt: '', updatedBy: { email: null, full_name: 'updatedBy_full_name', @@ -1109,14 +959,12 @@ describe('utils', () => { it('returns createdBy full name when the profile uid is not found', () => { expect( getEntity({ - createdAt: '', createdBy: { email: null, full_name: 'createdBy_full_name', username: 'createdBy_username', profile_uid: '123', }, - updatedAt: '', updatedBy: null, }) ).toEqual('createdBy_full_name'); @@ -1126,13 +974,11 @@ describe('utils', () => { expect( getEntity( { - createdAt: '', createdBy: { email: null, full_name: null, username: null, }, - updatedAt: '', updatedBy: { email: null, full_name: null, @@ -1149,13 +995,11 @@ describe('utils', () => { expect( getEntity( { - createdAt: '', createdBy: { email: null, full_name: null, username: null, }, - updatedAt: '', updatedBy: { email: null, full_name: null, @@ -1172,14 +1016,12 @@ describe('utils', () => { expect( getEntity( { - createdAt: '', createdBy: { email: null, full_name: null, username: null, profile_uid: userProfiles[0].uid, }, - updatedAt: '', updatedBy: null, }, userProfilesMap @@ -1191,9 +1033,7 @@ describe('utils', () => { expect( getEntity( { - updatedAt: '', updatedBy: null, - createdAt: '', createdBy: { email: null, full_name: null, diff --git a/x-pack/plugins/cases/server/client/cases/utils.ts b/x-pack/plugins/cases/server/client/cases/utils.ts index d1721c0709cda..92bba3fa7e9e1 100644 --- a/x-pack/plugins/cases/server/client/cases/utils.ts +++ b/x-pack/plugins/cases/server/client/cases/utils.ts @@ -5,10 +5,10 @@ * 2.0. */ -import { i18n } from '@kbn/i18n'; -import { flow, uniqBy, isEmpty } from 'lodash'; -import { ActionsClient } from '@kbn/actions-plugin/server'; +import { uniqBy, isEmpty } from 'lodash'; import { UserProfile } from '@kbn/security-plugin/common'; +import { IBasePath } from '@kbn/core-http-browser'; +import { CASE_VIEW_PAGE_TABS } from '../../../common/types'; import { isPushedUserAction } from '../../../common/utils/user_actions'; import { ActionConnector, @@ -16,46 +16,31 @@ import { CaseResponse, CaseUserActionsResponse, CommentResponse, - CommentResponseAlertsType, CommentType, - ConnectorMappingsAttributes, - CommentAttributes, - CommentRequestUserType, - CommentRequestAlertType, - CommentRequestActionsType, ActionTypes, CaseStatuses, User, CaseAttributes, CaseAssignees, + ConnectorMappingsAttributes, + CaseField, + ThirdPartyField, } from '../../../common/api'; import { CasesClientGetAlertsResponse } from '../alerts/types'; -import { - BasicParams, - EntityInformation, - ExternalServiceComment, - ExternalServiceParams, - Incident, - MapIncident, - PipedField, - PrepareFieldsForTransformArgs, - PushToServiceApiParams, - Transformer, - TransformerArgs, - TransformFieldsArgs, -} from './types'; +import { ExternalServiceComment, ExternalServiceIncident } from './types'; import { getAlertIds } from '../utils'; import { CasesConnectorsMap } from '../../connectors'; +import { getCaseViewPath } from '../../common/utils'; +import * as i18n from './translations'; interface CreateIncidentArgs { - actionsClient: ActionsClient; theCase: CaseResponse; userActions: CaseUserActionsResponse; connector: ActionConnector; - mappings: ConnectorMappingsAttributes[]; alerts: CasesClientGetAlertsResponse; casesConnectors: CasesConnectorsMap; userProfiles?: Map; + publicBaseUrl?: IBasePath['publicBaseUrl']; } export const dedupAssignees = (assignees?: CaseAssignees): CaseAssignees | undefined => { @@ -66,10 +51,12 @@ export const dedupAssignees = (assignees?: CaseAssignees): CaseAssignees | undef return uniqBy(assignees, 'uid'); }; +type LatestPushInfo = { index: number; pushedInfo: CaseFullExternalService } | null; + export const getLatestPushInfo = ( connectorId: string, userActions: CaseUserActionsResponse -): { index: number; pushedInfo: CaseFullExternalService } | null => { +): LatestPushInfo => { for (const [index, action] of [...userActions].reverse().entries()) { if (isPushedUserAction(action) && connectorId === action.payload.externalService.connector_id) { try { @@ -141,18 +128,32 @@ const getAlertsInfo = ( }; const addAlertMessage = ( - caseId: string, + theCase: CaseResponse, caseComments: CaseResponse['comments'], - comments: ExternalServiceComment[] + comments: ExternalServiceComment[], + publicBaseUrl?: IBasePath['publicBaseUrl'] ): ExternalServiceComment[] => { const { totalAlerts, hasUnpushedAlertComments } = getAlertsInfo(caseComments); const newComments = [...comments]; if (hasUnpushedAlertComments) { + let comment = `Elastic Alerts attached to the case: ${totalAlerts}`; + + if (publicBaseUrl) { + const alertsTableUrl = getCaseViewPath({ + publicBaseUrl, + caseId: theCase.id, + owner: theCase.owner, + tabId: CASE_VIEW_PAGE_TABS.ALERTS, + }); + + comment = `${comment}\n\n${i18n.VIEW_ALERTS_IN_KIBANA}\n${i18n.ALERTS_URL(alertsTableUrl)}`; + } + newComments.push({ - comment: `Elastic Alerts attached to the case: ${totalAlerts}`, - commentId: `${caseId}-total-alerts`, + comment, + commentId: `${theCase.id}-total-alerts`, }); } @@ -160,67 +161,80 @@ const addAlertMessage = ( }; export const createIncident = async ({ - actionsClient, theCase, userActions, connector, - mappings, alerts, casesConnectors, userProfiles, -}: CreateIncidentArgs): Promise => { - const { - comments: caseComments, - title, - description, - created_at: createdAt, - created_by: createdBy, - updated_at: updatedAt, - updated_by: updatedBy, - } = theCase; - - const params = { title, description, createdAt, createdBy, updatedAt, updatedBy }; + publicBaseUrl, +}: CreateIncidentArgs): Promise => { const latestPushInfo = getLatestPushInfo(connector.id, userActions); const externalId = latestPushInfo?.pushedInfo?.external_id ?? null; - const defaultPipes = externalId ? ['informationUpdated'] : ['informationCreated']; - let currentIncident: ExternalServiceParams | undefined; const externalServiceFields = casesConnectors.get(connector.actionTypeId)?.format(theCase, alerts) ?? {}; - let incident: Partial = { ...externalServiceFields }; - - if (externalId) { - try { - currentIncident = (await actionsClient.execute({ - actionId: connector.id, - params: { - subAction: 'getIncident', - subActionParams: { externalId }, - }, - })) as unknown as ExternalServiceParams | undefined; - } catch (ex) { - throw new Error( - `Retrieving Incident by id ${externalId} from ${connector.actionTypeId} failed with exception: ${ex}` - ); - } - } - - const fields = prepareFieldsForTransformation({ - defaultPipes, - mappings, - params, - }); + const connectorMappings = casesConnectors.get(connector.actionTypeId)?.getMapping() ?? []; + const descriptionWithKibanaInformation = addKibanaInformationToDescription( + theCase, + userProfiles, + publicBaseUrl + ); - const transformedFields = transformFields({ - params, - fields, - currentIncident, + const comments = formatComments({ + userActions, + latestPushInfo, + theCase, userProfiles, + publicBaseUrl, }); - incident = { ...incident, ...transformedFields, externalId }; + const mappedIncident = mapCaseFieldsToExternalSystemFields( + { title: theCase.title, description: descriptionWithKibanaInformation }, + connectorMappings + ); + + const incident = { + ...mappedIncident, + ...externalServiceFields, + externalId, + }; + return { incident, comments }; +}; + +export const mapCaseFieldsToExternalSystemFields = ( + caseFields: Record, unknown>, + mapping: ConnectorMappingsAttributes[] +): Record => { + const mappedCaseFields: Record = {}; + + for (const caseFieldKey of Object.keys(caseFields) as Array>) { + const mapDefinition = mapping.find( + (mappingEntry) => mappingEntry.source === caseFieldKey && mappingEntry.target !== 'not_mapped' + ); + + if (mapDefinition) { + mappedCaseFields[mapDefinition.target] = caseFields[caseFieldKey]; + } + } + return mappedCaseFields; +}; + +export const formatComments = ({ + userActions, + latestPushInfo, + theCase, + userProfiles, + publicBaseUrl, +}: { + theCase: CaseResponse; + latestPushInfo: LatestPushInfo; + userActions: CaseUserActionsResponse; + userProfiles?: Map; + publicBaseUrl?: IBasePath['publicBaseUrl']; +}): ExternalServiceComment[] => { const commentsIdsToBeUpdated = new Set( userActions .slice(latestPushInfo?.index ?? 0) @@ -228,7 +242,7 @@ export const createIncident = async ({ .map((action) => action.comment_id) ); - const commentsToBeUpdated = caseComments?.filter( + const commentsToBeUpdated = theCase.comments?.filter( (comment) => // We push only user's comments (comment.type === CommentType.user || comment.type === CommentType.actions) && @@ -238,25 +252,68 @@ export const createIncident = async ({ let comments: ExternalServiceComment[] = []; if (commentsToBeUpdated && Array.isArray(commentsToBeUpdated) && commentsToBeUpdated.length > 0) { - const commentsMapping = mappings.find((m) => m.source === 'comments'); - if (commentsMapping?.action_type !== 'nothing') { - comments = transformComments(commentsToBeUpdated, ['informationAdded'], userProfiles); - } + comments = addKibanaInformationToComments(commentsToBeUpdated, userProfiles); } - comments = addAlertMessage(theCase.id, caseComments, comments); + comments = addAlertMessage(theCase, theCase.comments, comments, publicBaseUrl); + return comments; +}; - return { incident, comments }; +export const addKibanaInformationToDescription = ( + theCase: CaseResponse, + userProfiles?: Map, + publicBaseUrl?: IBasePath['publicBaseUrl'] +) => { + const addedBy = i18n.ADDED_BY( + getEntity( + { + createdBy: theCase.created_by, + updatedBy: theCase.updated_by, + }, + userProfiles + ) + ); + + const descriptionWithKibanaInformation = `${theCase.description}\n\n${addedBy}.`; + + if (!publicBaseUrl) { + return descriptionWithKibanaInformation; + } + + const caseUrl = getCaseViewPath({ publicBaseUrl, caseId: theCase.id, owner: theCase.owner }); + + return `${descriptionWithKibanaInformation}\n${i18n.VIEW_IN_KIBANA}.\n${i18n.CASE_URL(caseUrl)}`; }; +const addKibanaInformationToComments = ( + comments: CaseResponse['comments'] = [], + userProfiles?: Map +): ExternalServiceComment[] => + comments.map((theComment) => { + const addedBy = i18n.ADDED_BY( + getEntity( + { + createdBy: theComment.created_by, + updatedBy: theComment.updated_by, + }, + userProfiles + ) + ); + + return { + comment: `${getCommentContent(theComment)}\n\n${addedBy}.`, + commentId: theComment.id, + }; + }); + export const getEntity = ( - entity: EntityInformation, + entity: { createdBy: CaseResponse['created_by']; updatedBy: CaseResponse['updated_by'] }, userProfiles?: Map ): string => { return ( getDisplayName(entity.updatedBy, userProfiles) ?? getDisplayName(entity.createdBy, userProfiles) ?? - '' + i18n.UNKNOWN ); }; @@ -279,7 +336,7 @@ const getDisplayName = ( } } - return validOrUndefined(user.full_name) ?? validOrUndefined(user.username) ?? ''; + return validOrUndefined(user.full_name) ?? validOrUndefined(user.username) ?? i18n.UNKNOWN; }; const validOrUndefined = (value: string | undefined | null): string | undefined => { @@ -290,173 +347,6 @@ const validOrUndefined = (value: string | undefined | null): string | undefined return value; }; -export const FIELD_INFORMATION = ( - mode: string, - date: string | undefined, - user: string | undefined -) => { - switch (mode) { - case 'create': - return i18n.translate('xpack.cases.connectors.cases.externalIncidentCreated', { - values: { date, user }, - defaultMessage: '(created at {date} by {user})', - }); - case 'update': - return i18n.translate('xpack.cases.connectors.cases.externalIncidentUpdated', { - values: { date, user }, - defaultMessage: '(updated at {date} by {user})', - }); - case 'add': - return i18n.translate('xpack.cases.connectors.cases.externalIncidentAdded', { - values: { date, user }, - defaultMessage: '(added at {date} by {user})', - }); - default: - return i18n.translate('xpack.cases.connectors.cases.externalIncidentDefault', { - values: { date, user }, - defaultMessage: '(created at {date} by {user})', - }); - } -}; - -export const transformers: Record = { - informationCreated: ({ value, date, user, ...rest }: TransformerArgs): TransformerArgs => ({ - value: `${value} ${FIELD_INFORMATION('create', date, user)}`, - ...rest, - }), - informationUpdated: ({ value, date, user, ...rest }: TransformerArgs): TransformerArgs => ({ - value: `${value} ${FIELD_INFORMATION('update', date, user)}`, - ...rest, - }), - informationAdded: ({ value, date, user, ...rest }: TransformerArgs): TransformerArgs => ({ - value: `${value} ${FIELD_INFORMATION('add', date, user)}`, - ...rest, - }), - append: ({ value, previousValue, ...rest }: TransformerArgs): TransformerArgs => ({ - value: previousValue ? `${previousValue} \r\n${value}` : `${value}`, - ...rest, - }), -}; - -export const prepareFieldsForTransformation = ({ - defaultPipes, - mappings, - params, -}: PrepareFieldsForTransformArgs): PipedField[] => - mappings.reduce( - (acc: PipedField[], mapping) => - mapping != null && - mapping.target != null && - mapping.target !== 'not_mapped' && - mapping.action_type !== 'nothing' && - mapping.source !== 'comments' - ? [ - ...acc, - { - key: mapping.target, - value: params[mapping.source] ?? '', - actionType: mapping.action_type, - pipes: - // Do not transform titles - mapping.source !== 'title' - ? mapping.action_type === 'append' - ? [...defaultPipes, 'append'] - : defaultPipes - : [], - }, - ] - : acc, - [] - ); - -export const transformFields = < - P extends EntityInformation, - S extends Record, - R extends {} ->({ - params, - fields, - currentIncident, - userProfiles, -}: TransformFieldsArgs): R => { - return fields.reduce((prev, cur) => { - const transform = flow(...cur.pipes.map((p) => transformers[p])); - return { - ...prev, - [cur.key]: transform({ - value: cur.value, - date: params.updatedAt ?? params.createdAt, - user: getEntity(params, userProfiles), - previousValue: currentIncident ? currentIncident[cur.key] : '', - }).value, - }; - }, {} as R); -}; - -export const transformComments = ( - comments: CaseResponse['comments'] = [], - pipes: string[], - userProfiles?: Map -): ExternalServiceComment[] => - comments.map((c) => ({ - comment: flow(...pipes.map((p) => transformers[p]))({ - value: getCommentContent(c), - date: c.updated_at ?? c.created_at, - user: getEntity( - { - createdAt: c.created_at, - createdBy: c.created_by, - updatedAt: c.updated_at, - updatedBy: c.updated_by, - }, - userProfiles - ), - }).value, - commentId: c.id, - })); - -export const isCommentAlertType = ( - comment: CommentResponse -): comment is CommentResponseAlertsType => comment.type === CommentType.alert; - -export const getCommentContextFromAttributes = ( - attributes: CommentAttributes -): CommentRequestUserType | CommentRequestAlertType | CommentRequestActionsType => { - const owner = attributes.owner; - switch (attributes.type) { - case CommentType.user: - return { - type: CommentType.user, - comment: attributes.comment, - owner, - }; - case CommentType.alert: - return { - type: attributes.type, - alertId: attributes.alertId, - index: attributes.index, - rule: attributes.rule, - owner, - }; - case CommentType.actions: - return { - type: attributes.type, - comment: attributes.comment, - actions: { - targets: attributes.actions.targets, - type: attributes.actions.type, - }, - owner, - }; - default: - return { - type: CommentType.user, - comment: '', - owner, - }; - } -}; - export const getClosedInfoForUpdate = ({ user, status, diff --git a/x-pack/plugins/cases/server/client/factory.ts b/x-pack/plugins/cases/server/client/factory.ts index 30d2e24a144a1..960c55e2882e3 100644 --- a/x-pack/plugins/cases/server/client/factory.ts +++ b/x-pack/plugins/cases/server/client/factory.ts @@ -11,6 +11,7 @@ import { Logger, ElasticsearchClient, SavedObjectsClientContract, + IBasePath, } from '@kbn/core/server'; import { SecurityPluginSetup, SecurityPluginStart } from '@kbn/security-plugin/server'; import { PluginStartContract as FeaturesPluginStart } from '@kbn/features-plugin/server'; @@ -46,6 +47,7 @@ interface CasesClientFactoryArgs { lensEmbeddableFactory: LensServerPluginSetup['lensEmbeddableFactory']; persistableStateAttachmentTypeRegistry: PersistableStateAttachmentTypeRegistry; externalReferenceAttachmentTypeRegistry: ExternalReferenceAttachmentTypeRegistry; + publicBaseUrl?: IBasePath['publicBaseUrl']; } /** @@ -126,6 +128,7 @@ export class CasesClientFactory { persistableStateAttachmentTypeRegistry: this.options.persistableStateAttachmentTypeRegistry, externalReferenceAttachmentTypeRegistry: this.options.externalReferenceAttachmentTypeRegistry, securityStartPlugin: this.options.securityPluginStart, + publicBaseUrl: this.options.publicBaseUrl, }); } diff --git a/x-pack/plugins/cases/server/client/types.ts b/x-pack/plugins/cases/server/client/types.ts index d1d9e60e45caa..81d17420b4c88 100644 --- a/x-pack/plugins/cases/server/client/types.ts +++ b/x-pack/plugins/cases/server/client/types.ts @@ -11,6 +11,7 @@ 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 { @@ -49,6 +50,7 @@ export interface CasesClientArgs { readonly persistableStateAttachmentTypeRegistry: PersistableStateAttachmentTypeRegistry; readonly externalReferenceAttachmentTypeRegistry: ExternalReferenceAttachmentTypeRegistry; readonly securityStartPlugin: SecurityPluginStart; + readonly publicBaseUrl?: IBasePath['publicBaseUrl']; } export interface ConstructQueryParams { diff --git a/x-pack/plugins/cases/server/common/utils.test.ts b/x-pack/plugins/cases/server/common/utils.test.ts index e10211cca8fe0..432fb0f92c4e6 100644 --- a/x-pack/plugins/cases/server/common/utils.test.ts +++ b/x-pack/plugins/cases/server/common/utils.test.ts @@ -7,7 +7,7 @@ import { SavedObject, SavedObjectsFindResponse } from '@kbn/core/server'; import { makeLensEmbeddableFactory } from '@kbn/lens-plugin/server/embeddable/make_lens_embeddable_factory'; -import { SECURITY_SOLUTION_OWNER } from '../../common/constants'; +import { OWNER_INFO, SECURITY_SOLUTION_OWNER } from '../../common/constants'; import { CaseConnector, CaseResponse, @@ -33,8 +33,11 @@ import { getOrUpdateLensReferences, asArray, transformNewCase, + getApplicationRoute, + getCaseViewPath, } from './utils'; import { newCase } from '../routes/api/__mocks__/request_responses'; +import { CASE_VIEW_PAGE_TABS } from '../../common/types'; interface CommentReference { ids: string[]; @@ -1184,4 +1187,98 @@ describe('common utils', () => { expect(asArray(100)).toEqual([100]); }); }); + + describe('getApplicationRoute', () => { + const owners = Object.keys(OWNER_INFO) as Array; + + it.each(owners)('returns the correct appRoute for owner: %s', (owner) => { + expect(getApplicationRoute(OWNER_INFO, owner)).toEqual(OWNER_INFO[owner].appRoute); + }); + + it('return the stack management app route if the owner info is not valid', () => { + // @ts-expect-error + expect(getApplicationRoute({ test: { appRoute: 'no-slash' } }, 'test')).toEqual( + '/app/management/insightsAndAlerting' + ); + }); + + it('return the stack management app route if the owner is not valid', () => { + expect(getApplicationRoute(OWNER_INFO, 'not-valid')).toEqual( + '/app/management/insightsAndAlerting' + ); + }); + }); + + describe('getCaseViewPath', () => { + const publicBaseUrl = 'https://example.com'; + const caseId = 'my-case-id'; + const commentId = 'my-comment-id'; + + it('returns the case view path correctly', () => { + expect(getCaseViewPath({ publicBaseUrl, caseId, owner: SECURITY_SOLUTION_OWNER })).toBe( + 'https://example.com/app/security/cases/my-case-id' + ); + }); + + it('removes the ending slash from the publicBaseUrl correctly', () => { + expect( + getCaseViewPath({ + publicBaseUrl: 'https://example.com/', + caseId, + owner: SECURITY_SOLUTION_OWNER, + }) + ).toBe('https://example.com/app/security/cases/my-case-id'); + }); + + it('remove the extra trailing slashes from case view path correctly', () => { + expect( + getCaseViewPath({ publicBaseUrl, caseId: '/my-case-id', owner: SECURITY_SOLUTION_OWNER }) + ).toBe('https://example.com/app/security/cases/my-case-id'); + }); + + it('returns the case view path correctly with invalid owner', () => { + expect(getCaseViewPath({ publicBaseUrl, caseId, owner: 'invalid' })).toBe( + 'https://example.com/app/management/insightsAndAlerting/cases/my-case-id' + ); + }); + + it('returns the case comment path correctly', () => { + expect( + getCaseViewPath({ publicBaseUrl, caseId, owner: SECURITY_SOLUTION_OWNER, commentId }) + ).toBe('https://example.com/app/security/cases/my-case-id/my-comment-id'); + }); + + it('remove the extra trailing slashes from case comment path correctly', () => { + expect( + getCaseViewPath({ + publicBaseUrl, + caseId: '/my-case-id', + owner: SECURITY_SOLUTION_OWNER, + commentId: '/my-comment-id', + }) + ).toBe('https://example.com/app/security/cases/my-case-id/my-comment-id'); + }); + + it('returns the case tab path correctly', () => { + expect( + getCaseViewPath({ + publicBaseUrl, + caseId, + owner: SECURITY_SOLUTION_OWNER, + tabId: CASE_VIEW_PAGE_TABS.ALERTS, + }) + ).toBe('https://example.com/app/security/cases/my-case-id/?tabId=alerts'); + }); + + it('remove the extra trailing slashes from case tab path correctly', () => { + expect( + getCaseViewPath({ + publicBaseUrl, + caseId: '/my-case-id', + owner: SECURITY_SOLUTION_OWNER, + tabId: CASE_VIEW_PAGE_TABS.ALERTS, + }) + ).toBe('https://example.com/app/security/cases/my-case-id/?tabId=alerts'); + }); + }); }); diff --git a/x-pack/plugins/cases/server/common/utils.ts b/x-pack/plugins/cases/server/common/utils.ts index 9ddb5feb5042f..1c41ea53105c9 100644 --- a/x-pack/plugins/cases/server/common/utils.ts +++ b/x-pack/plugins/cases/server/common/utils.ts @@ -10,9 +10,19 @@ import { SavedObjectsFindResponse, SavedObject, SavedObjectReference, + IBasePath, } from '@kbn/core/server'; import { flatMap, uniqWith, xorWith } from 'lodash'; import { LensServerPluginSetup } from '@kbn/lens-plugin/server'; +import { isValidOwner } from '../../common/utils/owner'; +import { + CASE_VIEW_COMMENT_PATH, + CASE_VIEW_PATH, + CASE_VIEW_TAB_PATH, + GENERAL_CASES_OWNER, + OWNER_INFO, +} from '../../common/constants'; +import { CASE_VIEW_PAGE_TABS } from '../../common/types'; import { AlertInfo } from './types'; import { @@ -394,3 +404,50 @@ export const asArray = (field?: T | T[] | null): T[] => { export const assertUnreachable = (x: never): never => { throw new Error('You should not reach this part of code'); }; + +export const getApplicationRoute = ( + appRouteInfo: { [K in keyof typeof OWNER_INFO]: { appRoute: string } }, + owner: string +): string => { + const appRoute = isValidOwner(owner) + ? appRouteInfo[owner].appRoute + : OWNER_INFO[GENERAL_CASES_OWNER].appRoute; + + return appRoute.startsWith('/') ? appRoute : `/${appRoute}`; +}; + +export const getCaseViewPath = (params: { + publicBaseUrl: NonNullable; + caseId: string; + owner: string; + commentId?: string; + tabId?: CASE_VIEW_PAGE_TABS; +}): string => { + const normalizePath = (path: string): string => path.replaceAll('//', '/'); + const removeEndingSlash = (path: string): string => + path.endsWith('/') ? path.slice(0, -1) : path; + + const { publicBaseUrl, caseId, owner, commentId, tabId } = params; + + const publicBaseUrlWithoutEndingSlash = removeEndingSlash(publicBaseUrl); + const appRoute = getApplicationRoute(OWNER_INFO, owner); + const basePath = `${publicBaseUrlWithoutEndingSlash}${appRoute}/cases`; + + if (commentId) { + const commentPath = normalizePath( + CASE_VIEW_COMMENT_PATH.replace(':detailName', caseId).replace(':commentId', commentId) + ); + + return `${basePath}${commentPath}`; + } + + if (tabId) { + const tabPath = normalizePath( + CASE_VIEW_TAB_PATH.replace(':detailName', caseId).replace(':tabId', tabId) + ); + + return `${basePath}${tabPath}`; + } + + return `${basePath}${normalizePath(CASE_VIEW_PATH.replace(':detailName', caseId))}`; +}; diff --git a/x-pack/plugins/cases/server/plugin.ts b/x-pack/plugins/cases/server/plugin.ts index 1f16db77ca137..2ca0c140f0202 100644 --- a/x-pack/plugins/cases/server/plugin.ts +++ b/x-pack/plugins/cases/server/plugin.ts @@ -198,6 +198,7 @@ export class CasePlugin { lensEmbeddableFactory: this.lensEmbeddableFactory!, persistableStateAttachmentTypeRegistry: this.persistableStateAttachmentTypeRegistry, externalReferenceAttachmentTypeRegistry: this.externalReferenceAttachmentTypeRegistry, + publicBaseUrl: core.http.basePath.publicBaseUrl, }); const client = core.elasticsearch.client; diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/field_data_row/action_menu/lens_utils.ts b/x-pack/plugins/data_visualizer/public/application/common/components/field_data_row/action_menu/lens_utils.ts index 034f7037fc29a..b053715090c7b 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/field_data_row/action_menu/lens_utils.ts +++ b/x-pack/plugins/data_visualizer/public/application/common/components/field_data_row/action_menu/lens_utils.ts @@ -282,7 +282,7 @@ export function getLensAttributes( ], state: { datasourceStates: { - indexpattern: { + formBased: { layers: { layer1: { columnOrder: ['col1', 'col2'], diff --git a/x-pack/plugins/enterprise_search/README.md b/x-pack/plugins/enterprise_search/README.md index 74391a9a96f5d..76160d3fcc8db 100644 --- a/x-pack/plugins/enterprise_search/README.md +++ b/x-pack/plugins/enterprise_search/README.md @@ -25,6 +25,10 @@ Problems? If you're an Elastic Enterprise Search engineer, please reach out to @ Don't forget to read Kibana's [contributing documentation](https://github.com/elastic/kibana/#building-and-running-kibana-andor-contributing-code) and developer guides for more general info on the Kibana ecosystem. +### Server development + +Kibana runs both a frontend and a backend/middleware server. For server development guidelines, see [SERVER.md](SERVER.md). + ### Kea Enterprise Search uses [Kea.js](https://github.com/keajs/kea) to manage our React/Redux state for us. Kea state is handled in our `*Logic` files and exposes [values](https://v2.keajs.org/docs/guide/concepts#values) and [actions](https://v2.keajs.org/docs/guide/concepts#actions) for our components to get and set state with. diff --git a/x-pack/plugins/enterprise_search/SERVER.md b/x-pack/plugins/enterprise_search/SERVER.md new file mode 100644 index 0000000000000..b4275f3bb545e --- /dev/null +++ b/x-pack/plugins/enterprise_search/SERVER.md @@ -0,0 +1,87 @@ +# Server architecture and guidelines + +Our Kibana Enterprise Search plugin has both a frontend, located in [public](public), and a server, located in [server](server). The server both serves the frontend, and acts as a middleware server between the frontend and Elasticsearch, Enterprise Search and any other backends the user may want to reach. That is: all calls to APIs are routed via Kibana. + +These guidelines primarily deal with our API routes and how we've designed this architecture. Note that these are guidelines, not hard and fast rules, and can be deviated from if it makes sense. + +## Architecture + +On startup, [the plugin](server/plugin.ts) registers all API routes with the main Kibana server by calling a series of `registerRoute` functions. These functions can be found in [server/routes](server/routes) and are separated into [app_search](server/routes/app_search), [workplace_search](server/routes/workplace_search) and [enterprise_search](server/routes/enterprise_search) routes. The plugin provides the routes with a set of dependencies they can use, including the request and response objects as well as an Elasticsearch client. + +### Endpoints +API endpoints are organized according to loosely applied RESTful principles. GET for fetching data, POST for creating new data, PUT for updating data. The main routes you'll likely be working with: + +`enterprise_search` +- enterprise_search/analytics +- enterprise_search/crawler +- enterprise_search/connectors +- enterprise_search/indices + +Endpoints should return and accept data in a JSON format using `snake_case` for property names. Any translation to and from `snake_case` should occur in the frontend. A notable allowed exception here is any endpoint calling the Enterprise Search Ruby app, as that app tends to accept `snake_case` but return `camelCase`. + +### Routes + +Each route path has its own file exporting a registerRoutes function, that's called by the plugin. For example, all `enterprise_search/indices` routes can be found in the [server/routes/enterprise_search/indices.ts](server/routes/enterprise_search/indices.ts) file. + +Each of the route functions is wrapped in a generic handler. If the route is just a passthrough route to the Enterprise Search Ruby app, we use the [enterpriseSearchRequestHandler](server/lib/enterprise_search_request_handler.ts). If the route instead calls Elasticsearch APIs or does more than just pass through to Enterprise Search, we use the [elasticSearchErrorHandler](x-pack/plugins/enterprise_search/server/utils/elasticsearch_error_handler.ts) to provide consistent error handling. + +Ideally, these route files do only two things: call a single library function to do the actual work we expect out of this endpoint, and handle any specific errors that don't fit into the generic error handler we use above. This minimalistic approach allows us to easily test whether the routes are calling the correct functions, and offload the actual logic to different places. + +### Library functions +Each route that does more than just pass requests to Enterprise Search should have a single library function it can call that does the actual processing work. These library functions are located in [server/lib/] and should mirror the path of the routes, prefixing the filename with the HTTP verb. So a GET request to `enterprise_search/indices/{indexName}` should end up in a `getIndex` function, located in [server/lib/indices/get_index.ts](server/lib/indices/get_index.ts). + +Where necessary for readability and/or to avoid duplicate code, these functions should call utility functions located in a `shared` folder in the nearest common parent directory. For example, a library function called by routes in just the `indices` directory should be located in [server/lib/indices/shared](server/lib/indices/shared), while a library function called by routes in both the `connectors` and `indices` directories should be located in [server/lib/shared](server/lib/shared). + +Be careful when sharing functions across multiple routes: if you're adding many inputs to a single function, it's probably better to split them up and dedicate each to a single route, even if that means more duplicate code in the system. The added complexity caused by maintaining multiple code paths in a single function is generally not worth it. + +### Types and validation + +Endpoints validate their inputs using [@kbn/config-schema](/packages/kbn-config-schema/), and we share TypeScript types between the frontend and backend in [common/types](common/types) to facilitate consistent API expectation. A few hints: + +- schema.maybe(...) allows the `...` to be optional/`undefined`. +- schema.nullable(...) allows the `...` to be `null`, which is distinct from making it optional or allowing `undefined`. +- Lean on `elasticsearch-js` (the built-in Elasticsearch client) types where possible to do the heavy lifting. + +### Working with Elasticsearch and elasticsearch-js + +Any Elasticsearch function should be available via the client, but it can be a bit hard to figure out what the required function name is. Because the (elasticsearch-js)[elasticsearch-js] documentation isn't great, a search through Kibana's codebase is often more efficient than trying to go through the docs. + +The Kibana plugin provides an Elasticsearch client object to every route. You can access this client under the obvious name `client`. That client comes with two users you can use to perform actual Elasticsearch operations: `client.asCurrentUser` and `client.asInternalUser`. `asCurrentUser` will execute operations using the permissions attached to the incoming request, which should be the permissions of the user firing that request in Kibana. `asInternalUser` will execute requests as Kibana's internal user. This user has very limited permissions and is generally only useful if you want to manipulate Kibana's Saved Objects. + +For most operations you'll want to specify a generic type argument to indicate the expected return type, as TypeScript has no way of knowing that type. See: + +``` +const connectorResult = await client.asCurrentUser.search({ + from: accumulator.length, + index, + query, + size: 1000, + }); +``` + +This will return a search object with each result document typed as the ReturnType specified in angle brankets. + +### Atomic updates + +When updating a document, you can use `client.asCurrentUser.update` to perform an atomic update. +```typescript +client.asCurrentUser.update({ + doc: { property_to_update: 'new value' }, + id: 'doc_id', + index: 'indexName', +}) +``` + This will replace the specified properties with the values you provide, while leaving unspecified properties untouched. + + If your requirements are more complicated, consider using [optimistic concurrency control](https://www.elastic.co/guide/en/elasticsearch/reference/current/optimistic-concurrency-control.html). + + +### Pagination + +For consistency in pagination, we have a [Paginate](common/types/pagination.ts) type that produces a paginated type, to be used in paginated results. This type works with Elastic EUI's paginated tables and provides a consistent interface for result types. + +For pagination inputs, take a look at [fetch_sync_jobs.ts](server/lib/connectors/fetch_sync_jobs.ts). Generally speaking you'll want to specify at minimum a `size` and a `page` index. + +### Testing + +We should aim for 100% unit test coverage in the server, although you're allowed to deviate from that if the effort to get there doesn't make add much security. We have a longer-term roadmap item to add Kibana FTR configs for end-to-end tests so that we can run these against an actual Elasticsearch backend, but we don't have these yet. diff --git a/x-pack/plugins/enterprise_search/TELEMETRY.md b/x-pack/plugins/enterprise_search/TELEMETRY.md new file mode 100644 index 0000000000000..eff8c3006b017 --- /dev/null +++ b/x-pack/plugins/enterprise_search/TELEMETRY.md @@ -0,0 +1,20 @@ +# Telemetry + +We have three forms of Telemetry in Kibana Enterprise Search: + +1. Automatic URL navigation tracking +2. Automatic click tracking +3. Manual telemetry tracking + +Automatic URL navigation tracking happens automatically and doesn't require any work from our side. + +Click tracking also happens automatically, but works by sending the DOM tree location of the clicked element. That's only useful if that element has a good click tracking id. To facilitate this, we add a `data-telemetry-id` attribute to each button and other relevant elements. The telemetry is formatted like so: + +`{app}-{ingestion type if applicable}-{page title}-{page subtitle}-{element title}` +`entSearchContent-connector-overview-generateApiKey-optimizedRequest` + +You don't need to stick to this format exactly and you can deviate with the three titles if they don't make sense. + +We also have a [telemetry endpoint](server/routes/enterprise_search/telemetry.ts) that can be used to create custom tracking counters, which are saved to Kibana's saved objects and periodically sent to the telemetry cluster. We can use this endpoint to facilitate more specific, customized telemetry needs. + +Keep in mind that tracking and telemetry can be privacy and security sensitive, and we want to make sure we only send generic data to the telemetry cluster. For example, we should not be tracking the contents of form fields or index names. diff --git a/x-pack/plugins/enterprise_search/common/types/pipelines.ts b/x-pack/plugins/enterprise_search/common/types/pipelines.ts index e9c564dd816aa..d6286718b454f 100644 --- a/x-pack/plugins/enterprise_search/common/types/pipelines.ts +++ b/x-pack/plugins/enterprise_search/common/types/pipelines.ts @@ -34,3 +34,9 @@ export interface MlInferenceHistoryItem { export interface MlInferenceHistoryResponse { history: MlInferenceHistoryItem[]; } + +export interface MlInferenceError { + message: string; + doc_count: number; + timestamp: string | undefined; // Date string +} diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/search_ui/search_ui.scss b/x-pack/plugins/enterprise_search/public/applications/app_search/components/search_ui/search_ui.scss new file mode 100644 index 0000000000000..85d01408cae96 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/search_ui/search_ui.scss @@ -0,0 +1,3 @@ +.searchUIGraphicContainer { + transform: translateZ(0); +} diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/search_ui/search_ui.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/search_ui/search_ui.tsx index 43ea60fa84617..d7398357a5e58 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/search_ui/search_ui.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/search_ui/search_ui.tsx @@ -21,6 +21,7 @@ import { SearchUIForm } from './components/search_ui_form'; import { SearchUIGraphic } from './components/search_ui_graphic'; import { SEARCH_UI_TITLE } from './i18n'; import { SearchUILogic } from './search_ui_logic'; +import './search_ui.scss'; export const SearchUI: React.FC = () => { const { loadFieldData } = useActions(SearchUILogic); @@ -76,7 +77,7 @@ export const SearchUI: React.FC = () => { - + diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/pipelines/fetch_ml_inference_pipeline_errors.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/pipelines/fetch_ml_inference_pipeline_errors.ts new file mode 100644 index 0000000000000..bb5d75ccaff88 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/pipelines/fetch_ml_inference_pipeline_errors.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { MlInferenceError } from '../../../../../common/types/pipelines'; +import { createApiLogic } from '../../../shared/api_logic/create_api_logic'; +import { HttpLogic } from '../../../shared/http'; + +export interface FetchMlInferenceErrorsApiLogicArgs { + indexName: string; +} +export interface FetchMlInferenceErrorsApiLogicResponse { + errors: MlInferenceError[]; +} + +export const fetchMlInferenceErrors = async ({ indexName }: FetchMlInferenceErrorsApiLogicArgs) => { + const route = `/internal/enterprise_search/indices/${indexName}/ml_inference/errors`; + + return await HttpLogic.values.http.get(route); +}; + +export const FetchMlInferenceErrorsApiLogic = createApiLogic( + ['fetch_ml_inference_errors_api_logic'], + fetchMlInferenceErrors +); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/crawler_domain_detail/authentication_panel/authentication_panel_actions.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/crawler_domain_detail/authentication_panel/authentication_panel_actions.tsx index 2a42a26ee8754..28285e004182e 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/crawler_domain_detail/authentication_panel/authentication_panel_actions.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/crawler_domain_detail/authentication_panel/authentication_panel_actions.tsx @@ -37,6 +37,7 @@ export const AuthenticationPanelActions: React.FC = () => { { { ) : currentAuth === null ? ( { ) : ( { diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/crawler_domain_detail/authentication_panel/authentication_panel_edit_content.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/crawler_domain_detail/authentication_panel/authentication_panel_edit_content.tsx index 8c7522dc868b4..55b930e7c9c21 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/crawler_domain_detail/authentication_panel/authentication_panel_edit_content.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/crawler_domain_detail/authentication_panel/authentication_panel_edit_content.tsx @@ -40,6 +40,7 @@ export const AuthenticationPanelEditContent: React.FC = () => { { = ({ { editingRender: (crawlRule, onChange, { isInvalid, isLoading }) => ( = ({ { editingRender: (crawlRule, onChange, { isInvalid, isLoading }) => ( { rightSideItems: [ , { @@ -78,6 +79,7 @@ export const CrawlerDomainDetail: React.FC = () => { > { } action={ { } > deduplicationEnabled @@ -125,6 +132,7 @@ export const DeduplicationPanel: React.FC = () => { { { @@ -170,6 +179,7 @@ export const DeduplicationPanel: React.FC = () => { )} , { diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/crawler_domain_detail/entry_points_table.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/crawler_domain_detail/entry_points_table.tsx index d14670f2c9ede..5f637c506e185 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/crawler_domain_detail/entry_points_table.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/crawler_domain_detail/entry_points_table.tsx @@ -37,6 +37,7 @@ export const EntryPointsTable: React.FC = ({ domain, inde { editingRender: (entryPoint, onChange, { isInvalid, isLoading }) => ( onChange(e.target.value)} diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/crawler_domain_detail/sitemaps_table.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/crawler_domain_detail/sitemaps_table.tsx index f4a4102fcac07..d4c2ab5f4955a 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/crawler_domain_detail/sitemaps_table.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/crawler_domain_detail/sitemaps_table.tsx @@ -41,6 +41,7 @@ export const SitemapsTable: React.FC = ({ domain, indexName, { editingRender: (sitemap, onChange, { isInvalid, isLoading }) => ( onChange(e.target.value)} diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/new_search_index_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/new_search_index_logic.ts index 19ff482edae89..56a525d7b91d6 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/new_search_index_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/new_search_index_logic.ts @@ -62,7 +62,6 @@ type NewSearchIndexActions = Pick< crawlerIndexCreated: Actions['apiSuccess']; setLanguageSelectValue(language: string): { language: string }; setRawName(rawName: string): { rawName: string }; - showIndexCreatedCallout: () => void; }; export const NewSearchIndexLogic = kea>({ diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/new_search_index_template.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/new_search_index_template.tsx index 6401db2a7974d..8142a26ceff93 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/new_search_index_template.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/new_search_index_template.tsx @@ -42,14 +42,15 @@ export interface Props { } export const NewSearchIndexTemplate: React.FC = ({ + buttonLoading, children, disabled, docsUrl, error, - title, onNameChange, onSubmit, - buttonLoading, + title, + type, }) => { const { fullIndexName, @@ -141,6 +142,7 @@ export const NewSearchIndexTemplate: React.FC = ({ fullWidth > = ({ )} > = ({ { const { isClientsPopoverOpen } = useValues(OverviewLogic); + const { ingestionMethod } = useValues(IndexViewLogic); const { toggleClientsPopover } = useActions(OverviewLogic); return ( @@ -119,7 +121,12 @@ export const ClientLibrariesPopover: React.FC = () => { isOpen={isClientsPopoverOpen} closePopover={toggleClientsPopover} button={ - + {i18n.translate( 'xpack.enterpriseSearch.content,overview.documentExample.clientLibraries.label', { defaultMessage: 'Client Libraries' } diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/document_list/document_list.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/document_list/document_list.tsx index 1d34dc695b0e2..bb0eab01c491e 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/document_list/document_list.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/document_list/document_list.tsx @@ -31,6 +31,7 @@ import { Result } from '../../../../../shared/result/result'; import { resultMetaData } from '../../../../../shared/result/result_metadata'; import { DocumentsLogic } from '../../documents_logic'; +import { IndexViewLogic } from '../../index_view_logic'; export const DocumentList: React.FC = () => { const { @@ -40,6 +41,7 @@ export const DocumentList: React.FC = () => { results, simplifiedMapping: mappings, } = useValues(DocumentsLogic); + const { ingestionMethod } = useValues(IndexViewLogic); const { onPaginate, setDocsPerPage } = useActions(DocumentsLogic); const [isPopoverOpen, setIsPopoverOpen] = useState(false); @@ -111,6 +113,7 @@ export const DocumentList: React.FC = () => { )} button={ = ({ indexName, onClose }) => { const { keyName, apiKey, isLoading, isSuccess } = useValues(GenerateApiKeyModalLogic); + const { ingestionMethod } = useValues(IndexViewLogic); const { setKeyName, makeRequest } = useActions(GenerateApiKeyModalLogic); return ( @@ -81,6 +84,7 @@ export const GenerateApiKeyModal: React.FC = ({ indexN setKeyName(event.currentTarget.value)} @@ -91,6 +95,7 @@ export const GenerateApiKeyModal: React.FC = ({ indexN = ({ indexN = ({ indexN - + {i18n.translate('xpack.enterpriseSearch.content.overview.generateApiKeyModal.cancel', { defaultMessage: 'Cancel', })} diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/header_actions/create_engine_menu_item.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/header_actions/create_engine_menu_item.tsx index be216d2548eb4..61f090f8e20ad 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/header_actions/create_engine_menu_item.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/header_actions/create_engine_menu_item.tsx @@ -19,11 +19,13 @@ import { KibanaLogic } from '../../../../../shared/kibana'; export interface CreateEngineMenuItemProps { indexName?: string; + ingestionMethod: string; isHiddenIndex?: boolean; } export const CreateEngineMenuItem: React.FC = ({ indexName, + ingestionMethod, isHiddenIndex, }) => { const engineCreationPath = !indexName @@ -37,6 +39,7 @@ export const CreateEngineMenuItem: React.FC = ({ { diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/header_actions/header_actions.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/header_actions/header_actions.tsx index 9f04dd7ba16ce..10d821b87b0ee 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/header_actions/header_actions.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/header_actions/header_actions.tsx @@ -8,15 +8,22 @@ import React from 'react'; import { ElasticsearchIndexWithIngestion } from '../../../../../../../common/types/indices'; -import { isCrawlerIndex, isConnectorIndex } from '../../../../utils/indices'; +import { isCrawlerIndex, isConnectorIndex, getIngestionMethod } from '../../../../utils/indices'; import { CrawlerStatusIndicator } from '../../../shared/crawler_status_indicator/crawler_status_indicator'; import { SearchEnginesPopover } from './search_engines_popover'; import { SyncButton } from './sync_button'; // Used to populate rightSideItems of an EuiPageTemplate, which is rendered right-to-left -export const getHeaderActions = (indexData?: ElasticsearchIndexWithIngestion) => [ - ...(isCrawlerIndex(indexData) ? [] : []), - ...(isConnectorIndex(indexData) ? [] : []), - , -]; +export const getHeaderActions = (indexData?: ElasticsearchIndexWithIngestion) => { + const ingestionMethod = getIngestionMethod(indexData); + return [ + ...(isCrawlerIndex(indexData) ? [] : []), + ...(isConnectorIndex(indexData) ? [] : []), + , + ]; +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/header_actions/search_engines_popover.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/header_actions/search_engines_popover.tsx index 2ac1682f8676c..47584d3021ada 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/header_actions/search_engines_popover.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/header_actions/search_engines_popover.tsx @@ -28,11 +28,13 @@ import { SearchEnginesPopoverLogic } from './search_engines_popover_logic'; export interface SearchEnginesPopoverProps { indexName?: string; + ingestionMethod: string; isHiddenIndex?: boolean; } export const SearchEnginesPopover: React.FC = ({ indexName, + ingestionMethod, isHiddenIndex, }) => { const { isSearchEnginesPopoverOpen } = useValues(SearchEnginesPopoverLogic); @@ -43,7 +45,12 @@ export const SearchEnginesPopover: React.FC = ({ isOpen={isSearchEnginesPopoverOpen} closePopover={toggleSearchEnginesPopover} button={ - + {i18n.translate('xpack.enterpriseSearch.content.index.searchEngines.label', { defaultMessage: 'Search engines', })} @@ -54,6 +61,7 @@ export const SearchEnginesPopover: React.FC = ({ size="s" items={[ { KibanaLogic.values.navigateToUrl(APP_SEARCH_PLUGIN.URL, { @@ -78,10 +86,18 @@ export const SearchEnginesPopover: React.FC = ({ } )} > - + ) : ( - + ), ]} /> diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/header_actions/sync_button.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/header_actions/sync_button.tsx index 6a6c483b30134..461bb2dd0e646 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/header_actions/sync_button.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/header_actions/sync_button.tsx @@ -16,7 +16,8 @@ import { IngestionStatus } from '../../../../types'; import { IndexViewLogic } from '../../index_view_logic'; export const SyncButton: React.FC = () => { - const { ingestionStatus, isSyncing, isWaitingForSync } = useValues(IndexViewLogic); + const { ingestionMethod, ingestionStatus, isSyncing, isWaitingForSync } = + useValues(IndexViewLogic); const { startSync } = useActions(IndexViewLogic); const getSyncButtonText = () => { @@ -39,6 +40,7 @@ export const SyncButton: React.FC = () => { }; return ( = ({ indexName }) => { - const { dismissIndexCreatedCallout } = useActions(IndexCreatedCalloutLogic); - return ( - - - {i18n.translate('xpack.enterpriseSearch.content.index.indexCreatedCallout.info', { - defaultMessage: - 'You can use App Search engines to build a search experience for your new Elasticsearch index.', - })} - - {i18n.translate('xpack.enterpriseSearch.content.index.readDocumentation.link', { - defaultMessage: 'Read the documentation', - })} - - - - - - { - // TODO bind it to AppSearch - // eslint-disable-next-line no-console - console.log(indexName); - }} - > - {i18n.translate('xpack.enterpriseSearch.content.index.createAppSearchEngine.button', { - defaultMessage: 'Create an App Search engine', - })} - - - - - {i18n.translate('xpack.enterpriseSearch.content.index.dismiss.button', { - defaultMessage: 'Dismiss', - })} - - - - - ); -}; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/index_created_callout/callout_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/index_created_callout/callout_logic.ts deleted file mode 100644 index d8421137a859d..0000000000000 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/index_created_callout/callout_logic.ts +++ /dev/null @@ -1,36 +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 { kea, MakeLogicType } from 'kea'; - -interface IndexCreatedCalloutLogicValues { - isCalloutVisible: boolean; -} - -interface IndexCreatedCalloutLogicActions { - dismissIndexCreatedCallout: void; - showIndexCreatedCallout: void; -} - -export const IndexCreatedCalloutLogic = kea< - MakeLogicType ->({ - actions: { - dismissIndexCreatedCallout: true, - showIndexCreatedCallout: true, - }, - path: ['enterprise_search', 'search_index', 'index_created_callout'], - reducers: () => ({ - isCalloutVisible: [ - false, - { - dismissIndexCreatedCallout: () => false, - showIndexCreatedCallout: () => true, - }, - ], - }), -}); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/manage_api_keys_popover/popover.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/manage_api_keys_popover/popover.tsx index b4b7e9bb038de..5d6734d5d9190 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/manage_api_keys_popover/popover.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/manage_api_keys_popover/popover.tsx @@ -21,10 +21,12 @@ import { i18n } from '@kbn/i18n'; import { KibanaLogic } from '../../../../../shared/kibana'; +import { IndexViewLogic } from '../../index_view_logic'; import { OverviewLogic } from '../../overview.logic'; export const ManageKeysPopover: React.FC = () => { const { isManageKeysPopoverOpen } = useValues(OverviewLogic); + const { ingestionMethod } = useValues(IndexViewLogic); const { toggleManageApiKeyPopover, openGenerateModal } = useActions(OverviewLogic); return ( @@ -44,6 +46,7 @@ export const ManageKeysPopover: React.FC = () => { size="s" items={[ KibanaLogic.values.navigateToUrl('/app/management/security/api_keys', { @@ -60,7 +63,11 @@ export const ManageKeysPopover: React.FC = () => {

, - +

{i18n.translate( diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_configuration.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_configuration.tsx index 233825d6af135..399006c6f3995 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_configuration.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_configuration.tsx @@ -18,7 +18,6 @@ import { EuiSpacer, EuiSteps, EuiCodeBlock, - EuiHorizontalRule, EuiCallOut, EuiButton, } from '@elastic/eui'; @@ -179,7 +178,24 @@ export const ConnectorConfiguration: React.FC = () => { } )} - + + ), + status: + !indexData.connector.status || + indexData.connector.status === ConnectorStatus.CREATED + ? 'incomplete' + : 'complete', + title: i18n.translate( + 'xpack.enterpriseSearch.content.indices.configurationConnector.steps.deployConnector.title', + { + defaultMessage: 'Deploy a connector', + } + ), + titleSize: 'xs', + }, + { + children: ( + {!indexData.connector.status || indexData.connector.status === ConnectorStatus.CREATED ? ( { )} recheckIndex()} isLoading={recheckIndexLoading} @@ -226,23 +243,8 @@ export const ConnectorConfiguration: React.FC = () => { )} /> )} - - ), - status: - !indexData.connector.status || - indexData.connector.status === ConnectorStatus.CREATED - ? 'incomplete' - : 'complete', - title: i18n.translate( - 'xpack.enterpriseSearch.content.indices.configurationConnector.steps.deployConnector.title', - { - defaultMessage: 'Deploy a connector', - } + ), - titleSize: 'xs', - }, - { - children: , status: indexData.connector.status === ConnectorStatus.CONNECTED ? 'complete' @@ -273,6 +275,7 @@ export const ConnectorConfiguration: React.FC = () => { { - setIsEditing(!isEditing)}> + setIsEditing(!isEditing)} + > {i18n.translate( 'xpack.enterpriseSearch.content.indices.configurationConnector.config.editButton.title', { diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_configuration_form.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_configuration_form.tsx index 3ef6c017a8a1e..29df3ccc5212b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_configuration_form.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_configuration_form.tsx @@ -55,7 +55,11 @@ export const ConnectorConfigurationForm = () => { - + {i18n.translate( 'xpack.enterpriseSearch.content.indices.configurationConnector.config.submitButton.title', { @@ -66,6 +70,7 @@ export const ConnectorConfigurationForm = () => { { setIsEditing(false); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_name_and_description/connector_name_and_description_form.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_name_and_description/connector_name_and_description_form.tsx index 33ea50ff8c6d6..84f9e32501f2f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_name_and_description/connector_name_and_description_form.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_name_and_description/connector_name_and_description_form.tsx @@ -76,12 +76,17 @@ export const ConnectorNameAndDescriptionForm: React.FC = () => { - + {SAVE_BUTTON_LABEL} { setIsEditing(false); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_scheduling.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_scheduling.tsx index 5438cd1a25f11..0067fc47b8290 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_scheduling.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_scheduling.tsx @@ -92,6 +92,7 @@ export const ConnectorSchedulingComponent: React.FC = () => { { { { setScheduling(schedulingInput); @@ -204,6 +207,7 @@ export const ConnectorSchedulingComponent: React.FC = () => { makeRequest({ connectorId: index.connector.id, scheduling })} > diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/native_connector_configuration/native_connector_advanced_configuration.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/native_connector_configuration/native_connector_advanced_configuration.tsx index 3e3582bb619fa..83f0a10db1538 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/native_connector_configuration/native_connector_advanced_configuration.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/native_connector_configuration/native_connector_advanced_configuration.tsx @@ -39,6 +39,7 @@ export const NativeConnectorAdvancedConfiguration: React.FC = () => { = ({ {...props} id={`checkableCard-${serviceType}`} className="connectorCheckable" + data-telemetry-id={`entSearchContent-connector-selectConnector-${serviceType}-select`} label={ {icon && ( diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/select_connector/select_connector.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/select_connector/select_connector.tsx index 737be758e8605..d60bfc9c59620 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/select_connector/select_connector.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/select_connector/select_connector.tsx @@ -136,7 +136,13 @@ export const SelectConnector: React.FC = () => { ))} - + {i18n.translate( 'xpack.enterpriseSearch.content.indices.selectConnector.selectAndConfigureButtonLabel', { diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/automatic_crawl_scheduler/automatic_crawl_scheduler.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/automatic_crawl_scheduler/automatic_crawl_scheduler.tsx index da625aae2b5c9..28c8b8ff10000 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/automatic_crawl_scheduler/automatic_crawl_scheduler.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/automatic_crawl_scheduler/automatic_crawl_scheduler.tsx @@ -96,6 +96,7 @@ export const AutomaticCrawlScheduler: React.FC = () => { > { { { - + {SAVE_BUTTON_LABEL} diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawl_custom_settings_flyout/crawl_custom_settings_flyout.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawl_custom_settings_flyout/crawl_custom_settings_flyout.tsx index d3c486fa20ca5..e64d296f1655a 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawl_custom_settings_flyout/crawl_custom_settings_flyout.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawl_custom_settings_flyout/crawl_custom_settings_flyout.tsx @@ -84,10 +84,16 @@ export const CrawlCustomSettingsFlyout: React.FC = () => { - {CANCEL_BUTTON_LABEL} + + {CANCEL_BUTTON_LABEL} + { )} > ) => diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawl_custom_settings_flyout/crawl_custom_settings_flyout_domains_panel.test.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawl_custom_settings_flyout/crawl_custom_settings_flyout_domains_panel.test.tsx index 2e74c598cbe6d..e69534e0e4ad9 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawl_custom_settings_flyout/crawl_custom_settings_flyout_domains_panel.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawl_custom_settings_flyout/crawl_custom_settings_flyout_domains_panel.test.tsx @@ -50,11 +50,13 @@ describe('CrawlCustomSettingsFlyoutDomainsPanel', () => { it('allows the user to select domains', () => { const domainAccordionWrapper = wrapper.find(EuiAccordion); - expect(domainAccordionWrapper.find(SimplifiedSelectable).props()).toEqual({ - options: ['https://www.elastic.co', 'https://www.swiftype.com'], - selectedOptions: ['https://www.elastic.co'], - onChange: MOCK_ACTIONS.onSelectDomainUrls, - }); + expect(domainAccordionWrapper.find(SimplifiedSelectable).props()).toEqual( + expect.objectContaining({ + options: ['https://www.elastic.co', 'https://www.swiftype.com'], + selectedOptions: ['https://www.elastic.co'], + onChange: MOCK_ACTIONS.onSelectDomainUrls, + }) + ); }); it('indicates how many domains are selected', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawl_custom_settings_flyout/crawl_custom_settings_flyout_domains_panel.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawl_custom_settings_flyout/crawl_custom_settings_flyout_domains_panel.tsx index 3cdeefa758fd4..446f6c043091b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawl_custom_settings_flyout/crawl_custom_settings_flyout_domains_panel.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawl_custom_settings_flyout/crawl_custom_settings_flyout_domains_panel.tsx @@ -74,6 +74,7 @@ export const CrawlCustomSettingsFlyoutDomainsPanel: React.FC = () => { } > { }); it('allows the user to select sitemap urls', () => { - expect(sitemapTab.find(SimplifiedSelectable).props()).toEqual({ - options: MOCK_VALUES.sitemapUrls, - selectedOptions: MOCK_VALUES.selectedSitemapUrls, - onChange: MOCK_ACTIONS.onSelectSitemapUrls, - }); + expect(sitemapTab.find(SimplifiedSelectable).props()).toEqual( + expect.objectContaining({ + options: MOCK_VALUES.sitemapUrls, + selectedOptions: MOCK_VALUES.selectedSitemapUrls, + onChange: MOCK_ACTIONS.onSelectSitemapUrls, + }) + ); }); it('allows the user to toggle whether to include robots.txt sitemaps', () => { @@ -111,11 +113,13 @@ describe('CrawlCustomSettingsFlyoutSeedUrlsPanel', () => { }); it('allows the user to select entry point urls', () => { - expect(entryPointsTab.find(SimplifiedSelectable).props()).toEqual({ - options: MOCK_VALUES.entryPointUrls, - selectedOptions: MOCK_VALUES.selectedEntryPointUrls, - onChange: MOCK_ACTIONS.onSelectEntryPointUrls, - }); + expect(entryPointsTab.find(SimplifiedSelectable).props()).toEqual( + expect.objectContaining({ + options: MOCK_VALUES.entryPointUrls, + selectedOptions: MOCK_VALUES.selectedEntryPointUrls, + onChange: MOCK_ACTIONS.onSelectEntryPointUrls, + }) + ); }); it('allows the user to add custom entry point urls', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawl_custom_settings_flyout/crawl_custom_settings_flyout_seed_urls_panel.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawl_custom_settings_flyout/crawl_custom_settings_flyout_seed_urls_panel.tsx index 27f3543835d11..1b0adb243af24 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawl_custom_settings_flyout/crawl_custom_settings_flyout_seed_urls_panel.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawl_custom_settings_flyout/crawl_custom_settings_flyout_seed_urls_panel.tsx @@ -113,6 +113,7 @@ export const CrawlCustomSettingsFlyoutSeedUrlsPanel: React.FC = () => { { /> { /> { <> { /> { - {CANCEL_BUTTON_LABEL} - + + {CANCEL_BUTTON_LABEL} + + {i18n.translate( 'xpack.enterpriseSearch.crawler.deleteDomainModal.deleteDomainButtonLabel', { diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/domain_management/domains_panel.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/domain_management/domains_panel.tsx index fdd56e055e1cd..41af7db78b6be 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/domain_management/domains_panel.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/domain_management/domains_panel.tsx @@ -43,7 +43,13 @@ export const DomainsPanel: React.FC = () => { - + {i18n.translate('xpack.enterpriseSearch.crawler.addDomainFlyout.openButtonLabel', { defaultMessage: 'Add domain', })} diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/domain_management/empty_state_panel.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/domain_management/empty_state_panel.tsx index 40cd93f5b8345..31e8e9d84e466 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/domain_management/empty_state_panel.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/domain_management/empty_state_panel.tsx @@ -55,7 +55,11 @@ export const EmptyStatePanel: React.FC = () => { - + {i18n.translate( 'xpack.enterpriseSearch.crawler.domainManagement.emptyState.addDomainButtonLabel', { diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/documents.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/documents.tsx index b67e866151ff0..aa0768181e1ea 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/documents.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/documents.tsx @@ -26,9 +26,11 @@ import { DocumentsLogic, DEFAULT_PAGINATION } from './documents_logic'; import { IndexNameLogic } from './index_name_logic'; import './documents.scss'; +import { IndexViewLogic } from './index_view_logic'; export const SearchIndexDocuments: React.FC = () => { const { indexName } = useValues(IndexNameLogic); + const { ingestionMethod } = useValues(IndexViewLogic); const { simplifiedMapping } = useValues(DocumentsLogic); const { makeRequest, makeMappingRequest, setSearchQuery } = useActions(DocumentsLogic); @@ -58,6 +60,7 @@ export const SearchIndexDocuments: React.FC = () => { { const { apiKey, isGenerateModalOpen } = useValues(OverviewLogic); - const { indexName } = useValues(IndexViewLogic); + const { indexName, ingestionMethod } = useValues(IndexViewLogic); const { closeGenerateModal } = useActions(OverviewLogic); const { defaultPipeline } = useValues(SettingsLogic); @@ -58,6 +58,7 @@ export const GenerateApiKeyPanel: React.FC = () => { setOptimizedRequest(event.target.checked)} label={i18n.translate( 'xpack.enterpriseSearch.content.overview.optimizedRequest.label', 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/custom_pipeline_panel.tsx index 702ecf89c9580..0a15e03eb2326 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/custom_pipeline_panel.tsx @@ -15,9 +15,10 @@ import { EuiButtonEmptyTo } from '../../../../shared/react_router_helpers'; export const CustomPipelinePanel: React.FC<{ indexName: string; + ingestionMethod: string; pipelineSuffix: string; processorsCount: number; -}> = ({ indexName, pipelineSuffix, processorsCount }) => { +}> = ({ indexName, ingestionMethod, pipelineSuffix, processorsCount }) => { return ( @@ -29,6 +30,7 @@ export const CustomPipelinePanel: React.FC<{ diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/inference_errors.test.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/inference_errors.test.tsx new file mode 100644 index 0000000000000..38db0f4a0e2e9 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/inference_errors.test.tsx @@ -0,0 +1,63 @@ +/* + * 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 { setMockValues } from '../../../../__mocks__/kea_logic'; + +import React from 'react'; + +import { shallow } from 'enzyme'; + +import { EuiBasicTable, EuiLoadingSpinner } from '@elastic/eui'; + +import { InferenceErrors } from './inference_errors'; + +describe('InferenceErrors', () => { + const indexName = 'unit-test-index'; + const defaultValues = { + indexName, + isLoading: true, + }; + beforeEach(() => { + jest.clearAllMocks(); + setMockValues(defaultValues); + }); + it('renders spinner when loading data', () => { + const wrapper = shallow(); + expect(wrapper.find(EuiLoadingSpinner)).toHaveLength(1); + expect(wrapper.find(EuiBasicTable)).toHaveLength(0); + }); + it('renders expected table columns', () => { + setMockValues({ + ...defaultValues, + inferenceErrors: [], + isLoading: false, + }); + const wrapper = shallow(); + expect(wrapper.find(EuiLoadingSpinner)).toHaveLength(0); + expect(wrapper.find(EuiBasicTable)).toHaveLength(1); + const table = wrapper.find(EuiBasicTable); + expect(table.prop('tableLayout')).toEqual('auto'); + expect(table.prop('columns')).toEqual([ + { + dataType: 'date', + field: 'timestamp', + name: expect.any(String), + }, + { + dataType: 'string', + field: 'message', + name: expect.any(String), + textOnly: true, + }, + { + dataType: 'number', + field: 'doc_count', + name: expect.any(String), + }, + ]); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/inference_errors.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/inference_errors.tsx new file mode 100644 index 0000000000000..0d11185a48705 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/inference_errors.tsx @@ -0,0 +1,93 @@ +/* + * 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 { EuiBasicTable, EuiBasicTableColumn, EuiSpacer, EuiLoadingSpinner } from '@elastic/eui'; + +import { i18n } from '@kbn/i18n'; + +import { MlInferenceError } from '../../../../../../common/types/pipelines'; +import { DataPanel } from '../../../../shared/data_panel/data_panel'; + +import { InferenceErrorsLogic } from './inference_errors_logic'; + +export const InferenceErrors: React.FC = () => { + const { indexName, isLoading, inferenceErrors } = useValues(InferenceErrorsLogic); + const { fetchIndexInferenceErrorLogs } = useActions(InferenceErrorsLogic); + + useEffect(() => { + fetchIndexInferenceErrorLogs({ indexName }); + }, [indexName]); + + const errorsColumns: Array> = [ + { + dataType: 'date', + field: 'timestamp', + name: i18n.translate( + 'xpack.enterpriseSearch.content.indices.pipelines.tabs.pipelineLogs.tableColumn.timestamp', + { defaultMessage: 'Timestamp' } + ), + }, + { + dataType: 'string', + field: 'message', + name: i18n.translate( + 'xpack.enterpriseSearch.content.indices.pipelines.tabs.pipelineLogs.tableColumn.message', + { defaultMessage: 'Inference error' } + ), + textOnly: true, + }, + { + dataType: 'number', + field: 'doc_count', + name: i18n.translate( + 'xpack.enterpriseSearch.content.indices.pipelines.tabs.pipelineLogs.tableColumn.docCount', + { defaultMessage: 'Approx. document count' } + ), + }, + ]; + + return ( + <> + + + {i18n.translate( + 'xpack.enterpriseSearch.content.indices.pipelines.tabs.pipelineLogs.title', + { defaultMessage: 'Ingestion logs' } + )} + + } + subtitle={i18n.translate( + 'xpack.enterpriseSearch.content.indices.pipelines.tabs.pipelineLogs.subtitle', + { defaultMessage: 'Errors and dropped data failures' } + )} + > + {isLoading ? ( + + ) : ( + + )} + + + ); +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/inference_errors_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/inference_errors_logic.test.ts new file mode 100644 index 0000000000000..a9d07657b94ab --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/inference_errors_logic.test.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 { LogicMounter, mockFlashMessageHelpers } from '../../../../__mocks__/kea_logic'; + +import { Status } from '../../../../../../common/types/api'; +import { FetchMlInferenceErrorsApiLogic } from '../../../api/pipelines/fetch_ml_inference_pipeline_errors'; + +import { InferenceErrorsLogic } from './inference_errors_logic'; + +const DEFAULT_VALUES = { + fetchIndexInferenceHistoryStatus: Status.IDLE, + indexName: '', + inferenceErrors: [], + inferenceErrorsData: undefined, + isLoading: true, +}; + +describe('InferenceErrorsLogic', () => { + const { mount } = new LogicMounter(InferenceErrorsLogic); + const { mount: mountFetchInferenceErrorsApiLogic } = new LogicMounter( + FetchMlInferenceErrorsApiLogic + ); + const { clearFlashMessages, flashAPIErrors } = mockFlashMessageHelpers; + beforeEach(() => { + jest.clearAllMocks(); + mountFetchInferenceErrorsApiLogic(); + mount(); + }); + + it('has expected default values', () => { + expect(InferenceErrorsLogic.values).toEqual(DEFAULT_VALUES); + }); + + describe('actions', () => { + it('should clear flash errors when fetching data', () => { + FetchMlInferenceErrorsApiLogic.actions.makeRequest({ indexName: 'test' }); + expect(clearFlashMessages).toHaveBeenCalledTimes(1); + }); + it('should flash errors fetching errors', () => { + FetchMlInferenceErrorsApiLogic.actions.apiError('error' as any); + expect(flashAPIErrors).toHaveBeenCalledWith('error'); + }); + it('should load fetched errors', () => { + const inferenceErrorsData = { + errors: [ + { + doc_count: 10, + message: 'I am a stick!', + timestamp: '1999-12-31T23:59:59.999Z', + }, + ], + }; + FetchMlInferenceErrorsApiLogic.actions.apiSuccess(inferenceErrorsData); + expect(InferenceErrorsLogic.values).toEqual({ + ...DEFAULT_VALUES, + fetchIndexInferenceHistoryStatus: Status.SUCCESS, + inferenceErrors: inferenceErrorsData.errors, + inferenceErrorsData, + isLoading: false, + }); + }); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/inference_errors_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/inference_errors_logic.ts new file mode 100644 index 0000000000000..520af1bbd6c39 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/inference_errors_logic.ts @@ -0,0 +1,76 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { kea, MakeLogicType } from 'kea'; + +import { Status } from '../../../../../../common/types/api'; +import { MlInferenceError } from '../../../../../../common/types/pipelines'; +import { Actions } from '../../../../shared/api_logic/create_api_logic'; +import { clearFlashMessages, flashAPIErrors } from '../../../../shared/flash_messages'; +import { + FetchMlInferenceErrorsApiLogicArgs, + FetchMlInferenceErrorsApiLogicResponse, + FetchMlInferenceErrorsApiLogic, +} from '../../../api/pipelines/fetch_ml_inference_pipeline_errors'; +import { IndexNameLogic } from '../index_name_logic'; + +interface InferenceErrorsActions { + fetchIndexInferenceErrorLogs: Actions< + FetchMlInferenceErrorsApiLogicArgs, + FetchMlInferenceErrorsApiLogicResponse + >['makeRequest']; + fetchIndexInferenceErrorLogsError: Actions< + FetchMlInferenceErrorsApiLogicArgs, + FetchMlInferenceErrorsApiLogicResponse + >['apiError']; +} + +interface InferenceErrorsValues { + fetchIndexInferenceHistoryStatus: Status; + indexName: string; + inferenceErrors: MlInferenceError[]; + inferenceErrorsData: FetchMlInferenceErrorsApiLogicResponse | undefined; + isLoading: boolean; +} + +export const InferenceErrorsLogic = kea< + MakeLogicType +>({ + connect: { + actions: [ + FetchMlInferenceErrorsApiLogic, + [ + 'makeRequest as fetchIndexInferenceErrorLogs', + 'apiError as fetchIndexInferenceErrorLogsError', + ], + ], + values: [ + IndexNameLogic, + ['indexName'], + FetchMlInferenceErrorsApiLogic, + ['data as inferenceErrorsData', 'status as fetchIndexInferenceHistoryStatus'], + ], + }, + listeners: () => ({ + fetchIndexInferenceErrorLogs: () => clearFlashMessages(), + fetchIndexInferenceErrorLogsError: (error) => flashAPIErrors(error), + }), + path: ['enterprise_search', 'content', 'pipelines_inference_errors'], + selectors: ({ selectors }) => ({ + inferenceErrors: [ + () => [selectors.inferenceErrorsData], + (inferenceErrorsData: FetchMlInferenceErrorsApiLogicResponse | undefined) => + inferenceErrorsData?.errors ?? [], + ], + isLoading: [ + () => [selectors.fetchIndexInferenceHistoryStatus], + (fetchIndexInferenceHistoryStatus: Status) => + fetchIndexInferenceHistoryStatus !== Status.SUCCESS && + fetchIndexInferenceHistoryStatus !== Status.ERROR, + ], + }), +}); 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 27dc055564bd8..79f344e5119e4 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 @@ -11,7 +11,7 @@ import React from 'react'; import { shallow } from 'enzyme'; -import { EuiBadge, EuiPanel, EuiTitle } from '@elastic/eui'; +import { EuiBadge, EuiButtonIcon, EuiPanel, EuiTextColor, EuiTitle } from '@elastic/eui'; import { InferencePipeline, TrainedModelState } from '../../../../../../common/types/pipelines'; @@ -21,7 +21,7 @@ import { TrainedModelHealth } from './ml_model_health'; export const DEFAULT_VALUES: InferencePipeline = { modelState: TrainedModelState.Started, pipelineName: 'Sample Processor', - types: ['pytorch'], + types: ['pytorch', 'ner'], }; const mockValues = { ...DEFAULT_VALUES }; @@ -34,8 +34,52 @@ describe('InferencePipelineCard', () => { it('renders the item', () => { const wrapper = shallow(); expect(wrapper.find(EuiPanel)).toHaveLength(1); + expect(wrapper.find(TrainedModelHealth)).toHaveLength(1); + }); + it('renders model type as title', () => { + const wrapper = shallow(); expect(wrapper.find(EuiTitle)).toHaveLength(1); + const title = wrapper.find(EuiTitle).dive(); + expect(title.text()).toBe('Named Entity Recognition'); + }); + it('renders pipeline as title with unknown model type', () => { + const values = { + ...DEFAULT_VALUES, + types: ['pytorch'], + }; + const wrapper = shallow(); + expect(wrapper.find(EuiTitle)).toHaveLength(1); + // does not render subtitle + expect(wrapper.find(EuiTextColor)).toHaveLength(0); + const title = wrapper.find(EuiTitle).dive(); + expect(title.text()).toBe(DEFAULT_VALUES.pipelineName); + }); + it('renders pipeline as subtitle', () => { + const wrapper = shallow(); + expect(wrapper.find(EuiTextColor)).toHaveLength(1); + const subtitle = wrapper.find(EuiTextColor).dive(); + expect(subtitle.text()).toBe(DEFAULT_VALUES.pipelineName); + }); + it('renders model type as badge', () => { + const wrapper = shallow(); expect(wrapper.find(EuiBadge)).toHaveLength(1); - expect(wrapper.find(TrainedModelHealth)).toHaveLength(1); + const badge = wrapper.find(EuiBadge).render(); + expect(badge.text()).toBe('ner'); + }); + it('renders fix button when model not deployed', () => { + const values = { + ...DEFAULT_VALUES, + modelState: TrainedModelState.NotDeployed, + }; + const wrapper = shallow(); + expect(wrapper.find(EuiButtonIcon)).toHaveLength(1); + + const fixButton = wrapper.find(EuiButtonIcon); + expect(fixButton.prop('iconType')).toBe('wrench'); + expect(fixButton.prop('href')).toBe('/app/ml/trained_models'); + }); + it('does not render fix button when model deployed', () => { + const wrapper = shallow(); + expect(wrapper.find(EuiButtonIcon)).toHaveLength(0); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/inference_pipeline_card.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/inference_pipeline_card.tsx index e8017ff15a198..ab81e206daf57 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/inference_pipeline_card.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/inference_pipeline_card.tsx @@ -20,6 +20,7 @@ import { EuiPopover, EuiPopoverTitle, EuiText, + EuiTextColor, EuiTitle, EuiToolTip, } from '@elastic/eui'; @@ -30,14 +31,18 @@ import { InferencePipeline, TrainedModelState } from '../../../../../../common/t import { CANCEL_BUTTON_LABEL, DELETE_BUTTON_LABEL } from '../../../../shared/constants'; import { HttpLogic } from '../../../../shared/http'; import { ML_MANAGE_TRAINED_MODELS_PATH } from '../../../routes'; +import { getMLType, getModelDisplayTitle } from '../../shared/ml_inference/utils'; import { IndexNameLogic } from '../index_name_logic'; +import { IndexViewLogic } from '../index_view_logic'; + import { TrainedModelHealth } from './ml_model_health'; import { PipelinesLogic } from './pipelines_logic'; export const InferencePipelineCard: React.FC = (pipeline) => { const { http } = useValues(HttpLogic); const { indexName } = useValues(IndexNameLogic); + const { ingestionMethod } = useValues(IndexViewLogic); const [isPopOverOpen, setIsPopOverOpen] = useState(false); const [showConfirmDelete, setShowConfirmDelete] = useState(false); const { deleteMlPipeline } = useActions(PipelinesLogic); @@ -45,8 +50,9 @@ export const InferencePipelineCard: React.FC = (pipeline) => setShowConfirmDelete(true); setIsPopOverOpen(false); }; - const { pipelineName, types } = pipeline; - + const { pipelineName, types: modelTypes } = pipeline; + const modelType = getMLType(modelTypes); + const modelTitle = getModelDisplayTitle(modelType); const actionButton = ( = (pipeline) => -

{pipelineName}

+

{modelTitle ?? pipelineName}

@@ -85,6 +91,7 @@ export const InferencePipelineCard: React.FC = (pipeline) =>
= (pipeline) =>
= (pipeline) => + {modelTitle && ( + + {pipelineName} + + )} @@ -138,6 +151,7 @@ export const InferencePipelineCard: React.FC = (pipeline) => )} > = (pipeline) => )} - {types.map((type) => ( + {(modelType.length > 0 ? [modelType] : modelTypes).map((type) => ( 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_pipeline_modal.tsx index a245c5db97882..34cb59e734d70 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_pipeline_modal.tsx @@ -40,6 +40,7 @@ interface IngestPipelineModalProps { createCustomPipelines: () => void; displayOnly: boolean; indexName: string; + ingestionMethod: string; isGated: boolean; isLoading: boolean; pipeline: IngestPipelineParams; @@ -53,6 +54,7 @@ export const IngestPipelineModal: React.FC = ({ createCustomPipelines, displayOnly, indexName, + ingestionMethod, isGated, isLoading, pipeline, @@ -160,7 +162,11 @@ export const IngestPipelineModal: React.FC = ({ - + @@ -174,7 +180,7 @@ export const IngestPipelineModal: React.FC = ({ {i18n.translate( 'xpack.enterpriseSearch.content.index.pipelines.ingestModal.curlHeader', { - defaultMessage: 'Sample cURL request', + defaultMessage: 'Sample cURL request to ingest a document', } )} @@ -206,6 +212,7 @@ export const IngestPipelineModal: React.FC = ({ { - const { indexName } = useValues(IndexViewLogic); + const { indexName, ingestionMethod } = useValues(IndexViewLogic); const { canSetPipeline, index, pipelineName, pipelineState, showModal } = useValues(PipelinesLogic); @@ -60,6 +60,7 @@ export const IngestPipelinesCard: React.FC = () => { createCustomPipelines={() => createCustomPipeline({ indexName })} displayOnly={!canSetPipeline} indexName={indexName} + ingestionMethod={ingestionMethod} isGated={isGated} isLoading={false} pipeline={{ ...pipelineState, name: pipelineName }} @@ -72,6 +73,7 @@ export const IngestPipelinesCard: React.FC = () => { @@ -89,7 +91,10 @@ export const IngestPipelinesCard: React.FC = () => { - + {i18n.translate( 'xpack.enterpriseSearch.content.indices.pipelines.ingestPipelinesCard.settings.label', { defaultMessage: 'Settings' } @@ -103,9 +108,10 @@ export const IngestPipelinesCard: React.FC = () => { {isApiIndex(index) && ( diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/add_ml_inference_button.test.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/add_ml_inference_button.test.tsx new file mode 100644 index 0000000000000..1c9b978cdf456 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/add_ml_inference_button.test.tsx @@ -0,0 +1,66 @@ +/* + * 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 { setMockValues } from '../../../../../__mocks__/kea_logic'; + +import React from 'react'; + +import { mount } from 'enzyme'; + +import { EuiButton, EuiToolTip } from '@elastic/eui'; + +import { AddMLInferencePipelineButton } from './add_ml_inference_button'; + +const DEFAULT_VALUES = { + canUseMlInferencePipeline: true, + capabilities: { + ml: { + canAccessML: true, + }, + }, + hasIndexIngestionPipeline: true, + ingestionMethod: 'crawler', +}; + +describe('add inference pipeline button', () => { + const onClick = jest.fn(); + beforeEach(() => { + jest.clearAllMocks(); + setMockValues({ ...DEFAULT_VALUES }); + }); + it('renders button', () => { + const wrapper = mount(); + expect(wrapper.find(EuiButton)).toHaveLength(1); + expect(wrapper.find(EuiToolTip)).toHaveLength(0); + const button = wrapper.find(EuiButton); + expect(button.text()).toBe('Add Inference Pipeline'); + }); + it('renders permission tooltip with no ml access', () => { + setMockValues({ ...DEFAULT_VALUES, capabilities: {} }); + const wrapper = mount(); + expect(wrapper.find(EuiButton)).toHaveLength(1); + expect(wrapper.find(EuiToolTip)).toHaveLength(1); + const tooltip = wrapper.find(EuiToolTip); + expect(tooltip.prop('content')).toContain('permission'); + }); + it('renders copy & customize tooltip with index pipeline', () => { + setMockValues({ ...DEFAULT_VALUES, hasIndexIngestionPipeline: false }); + const wrapper = mount(); + expect(wrapper.find(EuiButton)).toHaveLength(1); + expect(wrapper.find(EuiToolTip)).toHaveLength(1); + const tooltip = wrapper.find(EuiToolTip); + expect(tooltip.prop('content')).toContain('copy and customize'); + }); + it('renders disabled tooltip ml is not enabled', () => { + setMockValues({ ...DEFAULT_VALUES, canUseMlInferencePipeline: false }); + const wrapper = mount(); + expect(wrapper.find(EuiButton)).toHaveLength(1); + expect(wrapper.find(EuiToolTip)).toHaveLength(1); + const tooltip = wrapper.find(EuiToolTip); + expect(tooltip.prop('content')).toContain('enable ML Inference Pipelines'); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/add_ml_inference_button.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/add_ml_inference_button.tsx index 2bc65e041cc86..7c46fc3b58040 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/add_ml_inference_button.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/add_ml_inference_button.tsx @@ -13,6 +13,7 @@ import { EuiButton, EuiToolTip } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { KibanaLogic } from '../../../../../shared/kibana/kibana_logic'; +import { IndexViewLogic } from '../../index_view_logic'; import { PipelinesLogic } from '../pipelines_logic'; export interface AddMLInferencePipelineButtonProps { @@ -22,6 +23,7 @@ export const AddMLInferencePipelineButton: React.FC { const { capabilities } = useValues(KibanaLogic); + const { ingestionMethod } = useValues(IndexViewLogic); const { canUseMlInferencePipeline, hasIndexIngestionPipeline } = useValues(PipelinesLogic); const hasMLPermissions = capabilities?.ml?.canAccessML ?? false; if (!hasMLPermissions) { @@ -32,7 +34,7 @@ export const AddMLInferencePipelineButton: React.FC - + ); } @@ -47,7 +49,7 @@ export const AddMLInferencePipelineButton: React.FC - + ); } @@ -62,20 +64,27 @@ export const AddMLInferencePipelineButton: React.FC - + ); } - return ; + return ; }; -const AddButton: React.FC<{ disabled?: boolean; onClick?: () => void }> = ({ - disabled, - onClick, -}) => ( - +const AddButton: React.FC<{ + disabled?: boolean; + ingestionMethod: string; + onClick?: () => void; +}> = ({ disabled, ingestionMethod, onClick }) => ( + {i18n.translate('xpack.enterpriseSearch.content.indices.pipelines.mlInference.addButtonLabel', { - defaultMessage: 'Add inference pipeline', + defaultMessage: 'Add Inference Pipeline', })} ); 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 916a295df0050..99faa4920108c 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 @@ -35,6 +35,8 @@ import { } from '../../../../../shared/constants'; import { IndexNameLogic } from '../../index_name_logic'; +import { IndexViewLogic } from '../../index_view_logic'; + import { ConfigurePipeline } from './configure_pipeline'; import { AddInferencePipelineSteps, MLInferenceLogic } from './ml_inference_logic'; import { NoModelsPanel } from './no_models'; @@ -74,6 +76,7 @@ export const AddMLInferencePipelineModal: React.FC = ({ onClose }) => { + const { ingestionMethod } = useValues(IndexViewLogic); const { createErrors, supportedMLModels, @@ -115,7 +118,7 @@ const AddProcessorContent: React.FC = ({ onClo {step === AddInferencePipelineSteps.Test && } {step === AddInferencePipelineSteps.Review && } - + ); }; @@ -172,7 +175,10 @@ const ModalSteps: React.FC = () => { return ; }; -const ModalFooter: React.FC = ({ onClose }) => { +const ModalFooter: React.FC = ({ + ingestionMethod, + onClose, +}) => { const { addInferencePipelineModal: modal, isPipelineDataValid } = useValues(MLInferenceLogic); const { createPipeline, setAddInferencePipelineStep } = useActions(MLInferenceLogic); @@ -206,11 +212,17 @@ const ModalFooter: React.FC = ({ onClose }) => - {CANCEL_BUTTON_LABEL} + + {CANCEL_BUTTON_LABEL} + {nextStep !== undefined ? ( setAddInferencePipelineStep(nextStep as AddInferencePipelineSteps)} @@ -219,7 +231,12 @@ const ModalFooter: React.FC = ({ onClose }) => {CONTINUE_BUTTON_LABEL} ) : ( - + {i18n.translate( 'xpack.enterpriseSearch.content.indices.transforms.addInferencePipelineModal.footer.create', { diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/configure_pipeline.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/configure_pipeline.tsx index 99be659cbac36..fed9f8e6c5376 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/configure_pipeline.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/configure_pipeline.tsx @@ -26,6 +26,8 @@ import { FormattedMessage } from '@kbn/i18n-react'; import { docLinks } from '../../../../../shared/doc_links'; +import { IndexViewLogic } from '../../index_view_logic'; + import { MLInferenceLogic } from './ml_inference_logic'; const NoSourceFieldsError: React.FC = () => ( @@ -53,6 +55,7 @@ export const ConfigurePipeline: React.FC = () => { sourceFields, } = useValues(MLInferenceLogic); const { setInferencePipelineConfiguration } = useActions(MLInferenceLogic); + const { ingestionMethod } = useValues(IndexViewLogic); const { destinationField, modelID, pipelineName, sourceField } = configuration; const models = supportedMLModels ?? []; @@ -104,6 +107,7 @@ export const ConfigurePipeline: React.FC = () => { isInvalid={nameError} > { fullWidth > { isInvalid={emptySourceFields} > { isInvalid={formErrors.destinationField !== undefined} > 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 cff177f78de5b..082644b12c6ea 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 @@ -28,13 +28,10 @@ import { CreateMlInferencePipelineApiLogic } from '../../../../api/ml_models/cre import { MLModelsApiLogic } from '../../../../api/ml_models/ml_models_logic'; import { isConnectorIndex } from '../../../../utils/indices'; +import { isSupportedMLModel, sortSourceFields } from '../../../shared/ml_inference/utils'; import { AddInferencePipelineFormErrors, InferencePipelineConfiguration } from './types'; -import { - isSupportedMLModel, - sortSourceFields, - validateInferencePipelineConfiguration, -} from './utils'; +import { validateInferencePipelineConfiguration } from './utils'; export const EMPTY_PIPELINE_CONFIGURATION: InferencePipelineConfiguration = { destinationField: '', diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/utils.test.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/utils.test.ts index 4a9c11faa7f73..fc39d2f429a25 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/utils.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/utils.test.ts @@ -5,93 +5,9 @@ * 2.0. */ -import { TrainedModelConfigResponse } from '@kbn/ml-plugin/common/types/trained_models'; - -import { isSupportedMLModel, isValidPipelineName, sortSourceFields } from './utils'; +import { isValidPipelineName } from './utils'; describe('ml inference utils', () => { - describe('isSupportedMLModel', () => { - const makeFakeModel = ( - config: Partial - ): TrainedModelConfigResponse => ({ - inference_config: {}, - input: { - field_names: [], - }, - model_id: 'a-model-001', - model_type: 'pytorch', - tags: [], - version: '1', - ...config, - }); - it('returns true for expected models', () => { - const models: TrainedModelConfigResponse[] = [ - makeFakeModel({ - inference_config: { - ner: {}, - }, - }), - makeFakeModel({ - inference_config: { - text_classification: {}, - }, - }), - makeFakeModel({ - inference_config: { - text_embedding: {}, - }, - }), - makeFakeModel({ - inference_config: { - zero_shot_classification: { - classification_labels: [], - }, - }, - }), - makeFakeModel({ - inference_config: { - question_answering: {}, - }, - }), - makeFakeModel({ - inference_config: { - fill_mask: {}, - }, - }), - ]; - - for (const model of models) { - expect(isSupportedMLModel(model)).toBe(true); - } - }); - - it('returns false for expected models', () => { - const models: TrainedModelConfigResponse[] = [ - makeFakeModel({}), - makeFakeModel({ - inference_config: { - classification: {}, - }, - }), - ]; - - for (const model of models) { - expect(isSupportedMLModel(model)).toBe(false); - } - }); - }); - describe('sortSourceFields', () => { - it('promotes fields', () => { - let fields: string[] = ['id', 'body', 'url']; - expect(fields.sort(sortSourceFields)).toEqual(['body', 'id', 'url']); - fields = ['id', 'body_content', 'url']; - expect(fields.sort(sortSourceFields)).toEqual(['body_content', 'id', 'url']); - fields = ['id', 'title', 'message', 'url']; - expect(fields.sort(sortSourceFields)).toEqual(['title', 'id', 'message', 'url']); - fields = ['id', 'body', 'title', 'message', 'url']; - expect(fields.sort(sortSourceFields)).toEqual(['body', 'title', 'id', 'message', 'url']); - }); - }); describe('isValidPipelineName', () => { it('allows alphanumeric characters, underscores, & hypens', () => { expect(isValidPipelineName('apipelinename123')).toEqual(true); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/utils.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/utils.ts index 8e168586a4819..8db23f5deb7d6 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/utils.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ml_inference/utils.ts @@ -6,36 +6,9 @@ */ import { i18n } from '@kbn/i18n'; -import { TrainedModelConfigResponse } from '@kbn/ml-plugin/common/types/trained_models'; import { AddInferencePipelineFormErrors, InferencePipelineConfiguration } from './types'; -const NLP_CONFIG_KEYS = [ - 'fill_mask', - 'ner', - 'text_classification', - 'text_embedding', - 'question_answering', - 'zero_shot_classification', -]; -export const isSupportedMLModel = (model: TrainedModelConfigResponse): boolean => { - return Object.keys(model.inference_config).some((key) => NLP_CONFIG_KEYS.includes(key)); -}; - -const RECOMMENDED_FIELDS = ['body', 'body_content', 'title']; -export const sortSourceFields = (a: string, b: string): number => { - const promoteA = RECOMMENDED_FIELDS.includes(a); - const promoteB = RECOMMENDED_FIELDS.includes(b); - if (promoteA && promoteB) { - return RECOMMENDED_FIELDS.indexOf(a) > RECOMMENDED_FIELDS.indexOf(b) ? 1 : -1; - } else if (promoteA) { - return -1; - } else if (promoteB) { - return 1; - } - return a.localeCompare(b); -}; - const VALID_PIPELINE_NAME_REGEX = /^[\w\-]+$/; export const isValidPipelineName = (input: string): boolean => { return input.length > 0 && VALID_PIPELINE_NAME_REGEX.test(input); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/pipeline_settings_form.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/pipeline_settings_form.tsx index c01ca3d11a45a..bd3dc0856e36a 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/pipeline_settings_form.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/pipeline_settings_form.tsx @@ -14,11 +14,13 @@ import { IngestPipelineParams } from '../../../../../../common/types/connectors' import { SettingsCheckableCard } from '../../shared/settings_checkable_card/settings_checkable_card'; interface PipelineSettingsFormProps { + ingestionMethod: string; pipeline: IngestPipelineParams; setPipeline: (pipeline: IngestPipelineParams) => void; } export const PipelineSettingsForm: React.FC = ({ + ingestionMethod, setPipeline, pipeline, }) => { @@ -31,6 +33,7 @@ export const PipelineSettingsForm: React.FC = ({ = ({ = ({ { {i18n.translate( 'xpack.enterpriseSearch.content.indices.pipelines.mlInferencePipelines.docLink', { - defaultMessage: 'Learn more about deploying ML models in Elastic', + defaultMessage: 'Learn more about deploying Machine Learning models in Elastic', } )} @@ -129,7 +130,7 @@ export const SearchIndexPipelines: React.FC = () => { {i18n.translate( 'xpack.enterpriseSearch.content.indices.pipelines.mlInferencePipelines.title', { - defaultMessage: 'ML Inference pipelines', + defaultMessage: 'Machine Learning Inference Pipelines', } )} @@ -172,6 +173,7 @@ export const SearchIndexPipelines: React.FC = () => { + {showAddMlInferencePipelineModal && ( )} diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/pipelines_json_configurations.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/pipelines_json_configurations.tsx index 3cba142347fc3..eade81733a9eb 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/pipelines_json_configurations.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/pipelines_json_configurations.tsx @@ -28,11 +28,14 @@ import { docLinks } from '../../../../shared/doc_links'; import { HttpLogic } from '../../../../shared/http'; import { isManagedPipeline } from '../../../../shared/pipelines/is_managed'; +import { IndexViewLogic } from '../index_view_logic'; + import { PipelineJSONBadges } from './pipeline_json_badges'; import { IndexPipelinesConfigurationsLogic } from './pipelines_json_configurations_logic'; export const PipelinesJSONConfigurations: React.FC = () => { const { http } = useValues(HttpLogic); + const { ingestionMethod } = useValues(IndexViewLogic); const { pipelineNames, selectedPipeline, selectedPipelineId, selectedPipelineJSON } = useValues( IndexPipelinesConfigurationsLogic ); @@ -79,6 +82,7 @@ export const PipelinesJSONConfigurations: React.FC = () => { )} > ({ text: name, value: name }))} value={selectedPipelineId} @@ -95,6 +99,7 @@ export const PipelinesJSONConfigurations: React.FC = () => { {isManagedPipeline(selectedPipeline) ? ( { ) : ( { const { data: indexData, status: indexApiStatus } = useValues(FetchIndexApiLogic); - const { isCalloutVisible } = useValues(IndexCreatedCalloutLogic); const { tabId = SearchIndexTabId.OVERVIEW } = useParams<{ tabId?: string; }>(); @@ -177,7 +174,6 @@ export const SearchIndex: React.FC = () => { }} > <> - {isCalloutVisible && } {indexName === indexData?.name && ( )} diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/sync_jobs.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/sync_jobs.tsx index 708f8a6a77253..b6ae8bdd40fff 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/sync_jobs.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/sync_jobs.tsx @@ -85,9 +85,9 @@ export const SyncJobs: React.FC = () => { { + onChange={({ page: { index, size } }: { page: { index: number; size: number } }) => { if (connectorId) { - fetchSyncJobs({ connectorId, page: index, size: syncJobsPagination.pageSize }); + fetchSyncJobs({ connectorId, page: index, size }); } }} pagination={{ diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/settings/settings.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/settings/settings.tsx index 94c4c1fdbaad9..a1bbe6c39956f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/settings/settings.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/settings/settings.tsx @@ -72,8 +72,11 @@ export const Settings: React.FC = () => { 'Allow all ingestion mechanisms on your Enterprise Search deployment to extract searchable content from binary files, like PDFs and Word documents. This setting applies to all new Elasticsearch indices created by an Enterprise Search ingestion mechanism.', } )} + label={i18n.translate('xpack.enterpriseSearch.content.settings.contactExtraction.label', { + defaultMessage: 'Content extraction', + })} link={ - + {i18n.translate('xpack.enterpriseSearch.content.settings.contactExtraction.link', { defaultMessage: 'Learn more about content extraction', })} @@ -99,8 +102,11 @@ export const Settings: React.FC = () => { 'Whitespace reduction will strip your full-text content of whitespace by default.', } )} + label={i18n.translate('xpack.enterpriseSearch.content.settings.whitespaceReduction.label', { + defaultMessage: 'Whitespace reduction', + })} link={ - + {i18n.translate('xpack.enterpriseSearch.content.settings.whitespaceReduction.link', { defaultMessage: 'Learn more about whitespace reduction', })} @@ -129,8 +135,11 @@ export const Settings: React.FC = () => { 'ML Inference Pipelines will run as part of your pipelines. You will have to configure processors for each index individually on its pipelines page.', } )} + label={i18n.translate('xpack.enterpriseSearch.content.settings.mlInference.label', { + defaultMessage: 'ML Inference', + })} link={ - + {i18n.translate('xpack.enterpriseSearch.content.settings.mlInference.link', { defaultMessage: 'Learn more about content extraction', })} diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/settings/settings_panel.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/settings/settings_panel.tsx index 154da2649f9ae..fc0f3cca3e06c 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/settings/settings_panel.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/settings/settings_panel.tsx @@ -20,6 +20,7 @@ import { i18n } from '@kbn/i18n'; interface SettingsPanelProps { description: string; + label: string; link: React.ReactNode; onChange: (event: EuiSwitchEvent) => void; title: string; @@ -28,6 +29,7 @@ interface SettingsPanelProps { export const SettingsPanel: React.FC = ({ description, + label, link, onChange, title, @@ -57,13 +59,7 @@ export const SettingsPanel: React.FC = ({ - + {link} diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/shared/ml_inference/utils.test.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/shared/ml_inference/utils.test.ts new file mode 100644 index 0000000000000..cc4a158f41ef6 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/shared/ml_inference/utils.test.ts @@ -0,0 +1,123 @@ +/* + * 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 { TrainedModelConfigResponse } from '@kbn/ml-plugin/common/types/trained_models'; + +import { + getMLType, + getModelDisplayTitle, + isSupportedMLModel, + sortSourceFields, + NLP_CONFIG_KEYS, +} from './utils'; + +describe('ml inference utils', () => { + describe('isSupportedMLModel', () => { + const makeFakeModel = ( + config: Partial + ): TrainedModelConfigResponse => ({ + inference_config: {}, + input: { + field_names: [], + }, + model_id: 'a-model-001', + model_type: 'pytorch', + tags: [], + version: '1', + ...config, + }); + it('returns true for expected models', () => { + const models: TrainedModelConfigResponse[] = [ + makeFakeModel({ + inference_config: { + ner: {}, + }, + }), + makeFakeModel({ + inference_config: { + text_classification: {}, + }, + }), + makeFakeModel({ + inference_config: { + text_embedding: {}, + }, + }), + makeFakeModel({ + inference_config: { + zero_shot_classification: { + classification_labels: [], + }, + }, + }), + makeFakeModel({ + inference_config: { + question_answering: {}, + }, + }), + makeFakeModel({ + inference_config: { + fill_mask: {}, + }, + }), + ]; + + for (const model of models) { + expect(isSupportedMLModel(model)).toBe(true); + } + }); + + it('returns false for unexpected models', () => { + const models: TrainedModelConfigResponse[] = [ + makeFakeModel({}), + makeFakeModel({ + inference_config: { + fakething: {}, + }, + }), + ]; + + for (const model of models) { + expect(isSupportedMLModel(model)).toBe(false); + } + }); + }); + describe('sortSourceFields', () => { + it('promotes fields', () => { + let fields: string[] = ['id', 'body', 'url']; + expect(fields.sort(sortSourceFields)).toEqual(['body', 'id', 'url']); + fields = ['id', 'body_content', 'url']; + expect(fields.sort(sortSourceFields)).toEqual(['body_content', 'id', 'url']); + fields = ['id', 'title', 'message', 'url']; + expect(fields.sort(sortSourceFields)).toEqual(['title', 'id', 'message', 'url']); + fields = ['id', 'body', 'title', 'message', 'url']; + expect(fields.sort(sortSourceFields)).toEqual(['body', 'title', 'id', 'message', 'url']); + }); + }); + describe('getMLType', () => { + it('returns nlp type if present', () => { + for (const nlpType of NLP_CONFIG_KEYS) { + expect(getMLType(['pytorch', nlpType, 'foo', 'bar'])).toEqual(nlpType); + } + }); + it('returns first item if nlp config key not found in list', () => { + expect(getMLType(['pytorch', 'foo'])).toEqual('pytorch'); + }); + it('returns empty string when no models given', () => { + expect(getMLType([])).toEqual(''); + }); + }); + describe('model type titles', () => { + test.each(NLP_CONFIG_KEYS)('%s should have a title defined', (type) => + expect(getModelDisplayTitle(type)).not.toBe('') + ); + it('unsupported model type should return empty title', () => { + // This should technically never happen given the above test. + expect(getModelDisplayTitle('foo')).toBe(undefined); + }); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/shared/ml_inference/utils.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/shared/ml_inference/utils.ts new file mode 100644 index 0000000000000..0b2955cb7f30e --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/shared/ml_inference/utils.ts @@ -0,0 +1,77 @@ +/* + * 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 { i18n } from '@kbn/i18n'; +import { TrainedModelConfigResponse } from '@kbn/ml-plugin/common/types/trained_models'; + +export const NLP_CONFIG_KEYS = [ + 'fill_mask', + 'ner', + 'text_classification', + 'text_embedding', + 'question_answering', + 'zero_shot_classification', +]; +export const RECOMMENDED_FIELDS = ['body', 'body_content', 'title']; + +export const NLP_DISPLAY_TITLES: Record = { + fill_mask: i18n.translate('xpack.enterpriseSearch.content.ml_inference.fill_mask', { + defaultMessage: 'Fill Mask', + }), + ner: i18n.translate('xpack.enterpriseSearch.content.ml_inference.ner', { + defaultMessage: 'Named Entity Recognition', + }), + question_answering: i18n.translate( + 'xpack.enterpriseSearch.content.ml_inference.question_answering', + { + defaultMessage: 'Named Entity Recognition', + } + ), + text_classification: i18n.translate( + 'xpack.enterpriseSearch.content.ml_inference.text_classification', + { + defaultMessage: 'Text Classification', + } + ), + text_embedding: i18n.translate('xpack.enterpriseSearch.content.ml_inference.text_embedding', { + defaultMessage: 'Dense Vector Text Embedding', + }), + zero_shot_classification: i18n.translate( + 'xpack.enterpriseSearch.content.ml_inference.zero_shot_classification', + { + defaultMessage: 'Zero-Shot Text Classification', + } + ), +}; + +export const isSupportedMLModel = (model: TrainedModelConfigResponse): boolean => { + return Object.keys(model.inference_config).some((key) => NLP_CONFIG_KEYS.includes(key)); +}; + +export const sortSourceFields = (a: string, b: string): number => { + const promoteA = RECOMMENDED_FIELDS.includes(a); + const promoteB = RECOMMENDED_FIELDS.includes(b); + if (promoteA && promoteB) { + return RECOMMENDED_FIELDS.indexOf(a) > RECOMMENDED_FIELDS.indexOf(b) ? 1 : -1; + } else if (promoteA) { + return -1; + } else if (promoteB) { + return 1; + } + return a.localeCompare(b); +}; + +export const getMLType = (modelTypes: string[]): string => { + for (const type of modelTypes) { + if (NLP_CONFIG_KEYS.includes(type)) { + return type; + } + } + return modelTypes?.[0] ?? ''; +}; + +export const getModelDisplayTitle = (type: string): string | undefined => NLP_DISPLAY_TITLES[type]; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/types.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/types.ts index 9120a3b055b61..12cb87c98b434 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/types.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/types.ts @@ -12,9 +12,9 @@ export interface Crawler { } export const enum IngestionMethod { - CONNECTOR, - CRAWLER, - API, + CONNECTOR = 'connector', + CRAWLER = 'crawler', + API = 'api', } export const enum IngestionStatus { diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/doc_links/doc_links.ts b/x-pack/plugins/enterprise_search/public/applications/shared/doc_links/doc_links.ts index 975e7981829f2..34e781731988c 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/doc_links/doc_links.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/doc_links/doc_links.ts @@ -61,7 +61,6 @@ class DocLinks { public connectorsMongoDB: string; public connectorsMySQL: string; public connectorsWorkplaceSearch: string; - public contentExtraction: string; public crawlerGettingStarted: string; public crawlerManaging: string; public crawlerOverview: string; @@ -175,7 +174,6 @@ class DocLinks { this.connectorsMongoDB = ''; this.connectorsMySQL = ''; this.connectorsWorkplaceSearch = ''; - this.contentExtraction = ''; this.crawlerGettingStarted = ''; this.crawlerManaging = ''; this.crawlerOverview = ''; @@ -291,7 +289,6 @@ class DocLinks { this.connectorsMongoDB = docLinks.links.enterpriseSearch.connectorsMongoDB; this.connectorsMySQL = docLinks.links.enterpriseSearch.connectorsMySQL; this.connectorsWorkplaceSearch = docLinks.links.enterpriseSearch.connectorsWorkplaceSearch; - this.contentExtraction = docLinks.links.enterpriseSearch.contentExtraction; this.crawlerGettingStarted = docLinks.links.enterpriseSearch.crawlerGettingStarted; this.crawlerManaging = docLinks.links.enterpriseSearch.crawlerManaging; this.crawlerOverview = docLinks.links.enterpriseSearch.crawlerOverview; diff --git a/x-pack/plugins/enterprise_search/server/lib/ml_inference_pipeline/get_inference_errors.ts b/x-pack/plugins/enterprise_search/server/lib/ml_inference_pipeline/get_inference_errors.ts index 1ced837f42f22..09adc656d576f 100644 --- a/x-pack/plugins/enterprise_search/server/lib/ml_inference_pipeline/get_inference_errors.ts +++ b/x-pack/plugins/enterprise_search/server/lib/ml_inference_pipeline/get_inference_errors.ts @@ -12,11 +12,7 @@ import { import { ElasticsearchClient } from '@kbn/core/server'; -export interface MlInferenceError { - message: string; - doc_count: number; - timestamp: string | undefined; // Date string -} +import { MlInferenceError } from '../../../common/types/pipelines'; export interface ErrorAggregationBucket extends AggregationsStringRareTermsBucketKeys { max_error_timestamp: { diff --git a/x-pack/plugins/event_log/generated/mappings.json b/x-pack/plugins/event_log/generated/mappings.json index 4756b4f2e5534..1db28528efd57 100644 --- a/x-pack/plugins/event_log/generated/mappings.json +++ b/x-pack/plugins/event_log/generated/mappings.json @@ -267,6 +267,10 @@ "status": { "type": "keyword", "ignore_above": 1024 + }, + "outcome": { + "type": "keyword", + "ignore_above": 1024 } } }, diff --git a/x-pack/plugins/event_log/generated/schemas.ts b/x-pack/plugins/event_log/generated/schemas.ts index 523ad683eabf2..e40be778755af 100644 --- a/x-pack/plugins/event_log/generated/schemas.ts +++ b/x-pack/plugins/event_log/generated/schemas.ts @@ -115,6 +115,7 @@ export const EventSchema = schema.maybe( action_group_id: ecsString(), action_subgroup: ecsString(), status: ecsString(), + outcome: ecsString(), }) ), alert: schema.maybe( diff --git a/x-pack/plugins/event_log/scripts/mappings.js b/x-pack/plugins/event_log/scripts/mappings.js index 65c9220fb5355..d47ef4be6cac2 100644 --- a/x-pack/plugins/event_log/scripts/mappings.js +++ b/x-pack/plugins/event_log/scripts/mappings.js @@ -50,6 +50,10 @@ exports.EcsCustomPropertyMappings = { type: 'keyword', ignore_above: 1024, }, + outcome: { + type: 'keyword', + ignore_above: 1024, + }, }, }, alert: { diff --git a/x-pack/plugins/files/public/files_client/files_client.ts b/x-pack/plugins/files/public/files_client/files_client.ts index 8db201dbbc891..a17929a4a100b 100644 --- a/x-pack/plugins/files/public/files_client/files_client.ts +++ b/x-pack/plugins/files/public/files_client/files_client.ts @@ -102,9 +102,11 @@ export function createFilesClient({ getById: ({ kind, ...args }) => { return http.get(apiRoutes.getByIdRoute(scopedFileKind ?? kind, args.id)); }, - list({ kind, page, perPage } = { kind: '' }) { - return http.get(apiRoutes.getListRoute(scopedFileKind ?? kind), { + list: ({ kind, page, perPage, ...body } = { kind: '' }) => { + return http.post(apiRoutes.getListRoute(scopedFileKind ?? kind), { + headers: commonBodyHeaders, query: { page, perPage }, + body: JSON.stringify(body), }); }, update: ({ kind, id, ...body }) => { diff --git a/x-pack/plugins/files/server/file_client/file_client.ts b/x-pack/plugins/files/server/file_client/file_client.ts index ca806b6644f42..6954ac9c635d7 100644 --- a/x-pack/plugins/files/server/file_client/file_client.ts +++ b/x-pack/plugins/files/server/file_client/file_client.ts @@ -154,12 +154,16 @@ export class FileClientImpl implements FileClient { await this.internalUpdate(id, payload); } - public async find(arg: P1): Promise>> { - return this.metadataClient - .find(arg) - .then((r) => - r.map(({ id, metadata }) => this.instantiateFile(id, metadata as FileMetadata)) - ); + public async find( + arg: P1 + ): Promise<{ files: File[]; total: number }> { + const result = await this.metadataClient.find(arg); + return { + total: result.total, + files: result.files.map(({ id, metadata }) => + this.instantiateFile(id, metadata as FileMetadata) + ), + }; } public async delete({ id, hasContent = true }: DeleteArgs) { @@ -192,12 +196,6 @@ export class FileClientImpl implements FileClient { return this.blobStorageClient.delete(arg); }; - public async list(arg?: P1): Promise { - return this.metadataClient - .list(arg) - .then((r) => r.map(({ id, metadata }) => this.instantiateFile(id, metadata))); - } - /** * Upload a blob * @param id - The ID of the file content is associated with diff --git a/x-pack/plugins/files/server/file_client/file_metadata_client/adapters/es_index.ts b/x-pack/plugins/files/server/file_client/file_metadata_client/adapters/es_index.ts index 5b41dca5e158e..dcfe39e112075 100644 --- a/x-pack/plugins/files/server/file_client/file_metadata_client/adapters/es_index.ts +++ b/x-pack/plugins/files/server/file_client/file_metadata_client/adapters/es_index.ts @@ -10,7 +10,7 @@ import { pipe } from 'lodash/fp'; import { Logger } from '@kbn/core/server'; import { toElasticsearchQuery } from '@kbn/es-query'; import { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; -import { MappingProperty } from '@elastic/elasticsearch/lib/api/types'; +import { MappingProperty, SearchTotalHits } from '@elastic/elasticsearch/lib/api/types'; import type { FilesMetrics, FileMetadata, Pagination } from '../../../../common'; import type { FindFileArgs } from '../../../file_service'; import type { @@ -19,10 +19,9 @@ import type { FileMetadataClient, GetArg, GetUsageMetricsArgs, - ListArg, UpdateArgs, } from '../file_metadata_client'; -import { filterArgsToKuery, filterDeletedFiles } from './query_filters'; +import { filterArgsToKuery } from './query_filters'; import { fileObjectType } from '../../../saved_objects/file'; const filterArgsToESQuery = pipe(filterArgsToKuery, toElasticsearchQuery); @@ -114,25 +113,12 @@ export class EsIndexFilesMetadataClient implements FileMetadataClie private attrPrefix: keyof FileDocument = 'file'; - async list({ page, perPage }: ListArg = {}): Promise>> { - const result = await this.esClient.search>({ - index: this.index, - expand_wildcards: 'hidden', - query: toElasticsearchQuery(filterDeletedFiles({ attrPrefix: this.attrPrefix })), - ...this.paginationToES({ page, perPage }), - sort: 'file.created', - }); - - return result.hits.hits.map((hit) => { - return { - id: hit._id, - metadata: hit._source?.file!, - }; - }); - } - - async find({ page, perPage, ...filterArgs }: FindFileArgs): Promise>> { + async find({ page, perPage, ...filterArgs }: FindFileArgs = {}): Promise<{ + total: number; + files: Array>; + }> { const result = await this.esClient.search>({ + track_total_hits: true, index: this.index, expand_wildcards: 'hidden', query: filterArgsToESQuery({ ...filterArgs, attrPrefix: this.attrPrefix }), @@ -140,7 +126,10 @@ export class EsIndexFilesMetadataClient implements FileMetadataClie sort: 'file.created', }); - return result.hits.hits.map((r) => ({ id: r._id, metadata: r._source?.file! })); + return { + total: (result.hits.total as SearchTotalHits).value, + files: result.hits.hits.map((r) => ({ id: r._id, metadata: r._source?.file! })), + }; } async getUsageMetrics(arg: GetUsageMetricsArgs): Promise { diff --git a/x-pack/plugins/files/server/file_client/file_metadata_client/adapters/query_filters.ts b/x-pack/plugins/files/server/file_client/file_metadata_client/adapters/query_filters.ts index 4b33c60f320a4..e5c49b8f12b9d 100644 --- a/x-pack/plugins/files/server/file_client/file_metadata_client/adapters/query_filters.ts +++ b/x-pack/plugins/files/server/file_client/file_metadata_client/adapters/query_filters.ts @@ -12,12 +12,10 @@ import { getFlattenedObject } from '@kbn/std'; import { FileMetadata, FileStatus } from '../../../../common/types'; import { FindFileArgs } from '../../../file_service'; -const { buildNode } = nodeTypes.function; - const deletedStatus: FileStatus = 'DELETED'; export function filterDeletedFiles({ attrPrefix }: { attrPrefix: string }): KueryNode { - return buildNode('not', nodeBuilder.is(`${attrPrefix}.Status`, deletedStatus)); + return nodeTypes.function.buildNode('not', nodeBuilder.is(`${attrPrefix}.Status`, deletedStatus)); } export function filterArgsToKuery({ @@ -30,16 +28,25 @@ export function filterArgsToKuery({ }: Omit & { attrPrefix?: string }): KueryNode { const kueryExpressions: KueryNode[] = [filterDeletedFiles({ attrPrefix })]; - const addFilters = (fieldName: keyof FileMetadata, values: string[] = []): void => { + const addFilters = ( + fieldName: keyof FileMetadata, + values: string[] = [], + isWildcard = false + ): void => { if (values.length) { const orExpressions = values .filter(Boolean) - .map((value) => nodeBuilder.is(`${attrPrefix}.${fieldName}`, escapeKuery(value))); + .map((value) => + nodeBuilder.is( + `${attrPrefix}.${fieldName}`, + isWildcard ? nodeTypes.wildcard.buildNode(value) : escapeKuery(value) + ) + ); kueryExpressions.push(nodeBuilder.or(orExpressions)); } }; - addFilters('name', name); + addFilters('name', name, true); addFilters('FileKind', kind); addFilters('Status', status); addFilters('extension', extension); @@ -51,7 +58,8 @@ export function filterArgsToKuery({ forEach(([fieldName, value]) => { addFilters( `Meta.${fieldName}` as keyof FileMetadata, - Array.isArray(value) ? value : [value] + Array.isArray(value) ? value : [value], + true ); }) ); diff --git a/x-pack/plugins/files/server/file_client/file_metadata_client/adapters/saved_objects.ts b/x-pack/plugins/files/server/file_client/file_metadata_client/adapters/saved_objects.ts index 9afd12689acbf..b1a43a05bfb7b 100644 --- a/x-pack/plugins/files/server/file_client/file_metadata_client/adapters/saved_objects.ts +++ b/x-pack/plugins/files/server/file_client/file_metadata_client/adapters/saved_objects.ts @@ -13,11 +13,10 @@ import type { SavedObjectsOpenPointInTimeResponse, } from '@kbn/core-saved-objects-api-server'; import { AggregationsSumAggregate } from '@elastic/elasticsearch/lib/api/types'; -import { escapeKuery } from '@kbn/es-query'; import { FindFileArgs } from '../../../file_service/file_action_types'; import { ES_FIXED_SIZE_INDEX_BLOB_STORE } from '../../../../common/constants'; -import type { FileMetadata, FilesMetrics, FileStatus, Pagination } from '../../../../common/types'; +import type { FileMetadata, FilesMetrics, FileStatus } from '../../../../common/types'; import type { FileMetadataClient, UpdateArgs, @@ -61,26 +60,11 @@ export class SavedObjectsFileMetadataClient implements FileMetadataClient { metadata: result.attributes as FileDescriptor['metadata'], }; } - async list({ fileKind, page, perPage }: { fileKind?: string } & Pagination = {}): Promise< - FileDescriptor[] - > { - let filter = `NOT ${this.soType}.attributes.Status: DELETED`; - if (fileKind) { - filter = `${this.soType}.attributes.FileKind: ${escapeKuery(fileKind)} AND ${filter}`; - } - const result = await this.soClient.find({ - type: this.soType, - filter, - page, - perPage, - }); - return result.saved_objects.map((file) => ({ - id: file.id, - metadata: file.attributes as FileDescriptor['metadata'], - })); - } - async find({ page, perPage, ...filterArgs }: FindFileArgs): Promise { + async find({ page, perPage, ...filterArgs }: FindFileArgs = {}): Promise<{ + total: number; + files: Array>; + }> { const result = await this.soClient.find({ type: this.soType, filter: filterArgsToKuery({ ...filterArgs, attrPrefix: `${this.soType}.attributes` }), @@ -89,10 +73,13 @@ export class SavedObjectsFileMetadataClient implements FileMetadataClient { sortOrder: 'desc', sortField: 'created', }); - return result.saved_objects.map((so) => ({ - id: so.id, - metadata: so.attributes as FileMetadata, - })); + return { + files: result.saved_objects.map((so) => ({ + id: so.id, + metadata: so.attributes as FileMetadata, + })), + total: result.total, + }; } async delete({ id }: { id: string }): Promise { diff --git a/x-pack/plugins/files/server/file_client/file_metadata_client/file_metadata_client.ts b/x-pack/plugins/files/server/file_client/file_metadata_client/file_metadata_client.ts index 5934ac1f422b8..5136fc9744d51 100644 --- a/x-pack/plugins/files/server/file_client/file_metadata_client/file_metadata_client.ts +++ b/x-pack/plugins/files/server/file_client/file_metadata_client/file_metadata_client.ts @@ -72,13 +72,6 @@ export interface DeleteArg { id: string; } -export interface ListArg extends Pagination { - /** - * The file kind to scope this query to - */ - fileKind?: string; -} - export interface FindArg extends Pagination { /** * The file kind to scope this query to @@ -116,18 +109,12 @@ export interface FileMetadataClient { * @param arg - Arguments to delete file metadata */ delete(arg: DeleteArg): Promise; - /** - * List all instances of metadata for a file kind. - * - * @param arg - Arguments to list file metadata - */ - list(arg?: ListArg): Promise; /** * Search for a set of file kind instances that match the filters. * * @param arg - Filters and other settings to match against */ - find(arg: FindFileArgs): Promise; + find(arg?: FindFileArgs): Promise<{ total: number; files: FileDescriptor[] }>; /** * Prepare a set of metrics based on the file metadata. * diff --git a/x-pack/plugins/files/server/file_client/file_metadata_client/index.ts b/x-pack/plugins/files/server/file_client/file_metadata_client/index.ts index e4b84a1c6cb04..690a6b472b00f 100644 --- a/x-pack/plugins/files/server/file_client/file_metadata_client/index.ts +++ b/x-pack/plugins/files/server/file_client/file_metadata_client/index.ts @@ -12,7 +12,6 @@ export type { FindArg as FindMetadataArg, GetArg as GetMetadataArg, GetUsageMetricsArgs, - ListArg as ListMetadataArg, UpdateArgs as UpdateMetadataArg, } from './file_metadata_client'; export { SavedObjectsFileMetadataClient, EsIndexFilesMetadataClient } from './adapters'; diff --git a/x-pack/plugins/files/server/file_client/index.ts b/x-pack/plugins/files/server/file_client/index.ts index cb9c2187bc996..46eec400b77bc 100644 --- a/x-pack/plugins/files/server/file_client/index.ts +++ b/x-pack/plugins/files/server/file_client/index.ts @@ -13,7 +13,6 @@ export type { FindMetadataArg, GetMetadataArg, GetUsageMetricsArgs, - ListMetadataArg, UpdateMetadataArg, } from './file_metadata_client'; export { FileClientImpl } from './file_client'; diff --git a/x-pack/plugins/files/server/file_client/integration_tests/es_file_client.test.ts b/x-pack/plugins/files/server/file_client/integration_tests/es_file_client.test.ts index 58bf5cec29c41..0ae1b9c7d29f8 100644 --- a/x-pack/plugins/files/server/file_client/integration_tests/es_file_client.test.ts +++ b/x-pack/plugins/files/server/file_client/integration_tests/es_file_client.test.ts @@ -106,7 +106,7 @@ describe('ES-index-backed file client', () => { await file3.uploadContent(Readable.from(['test'])); { - const results = await fileClient.find({ + const { files: results } = await fileClient.find({ status: ['READY'], meta: { test: '3' }, }); @@ -121,7 +121,7 @@ describe('ES-index-backed file client', () => { } { - const results = await fileClient.find({ + const { files: results } = await fileClient.find({ status: ['READY', 'AWAITING_UPLOAD'], }); @@ -178,10 +178,10 @@ describe('ES-index-backed file client', () => { }, }); - const list = await fileClient.list(); + const { files } = await fileClient.find(); - expect(list).toHaveLength(1); - expect(list[0].toJSON()).toEqual( + expect(files).toHaveLength(1); + expect(files[0].toJSON()).toEqual( expect.objectContaining({ id: '123', fileKind: 'none', diff --git a/x-pack/plugins/files/server/file_client/types.ts b/x-pack/plugins/files/server/file_client/types.ts index bbab0066cf3f0..19a50f7249fa2 100644 --- a/x-pack/plugins/files/server/file_client/types.ts +++ b/x-pack/plugins/files/server/file_client/types.ts @@ -93,19 +93,12 @@ export interface FileClient { */ delete(arg: DeleteArgs): Promise; - /** - * See {@link FileMetadataClient.list} - * - * @param arg - Argument to list files - */ - list(arg?: P1): Promise; - /** * See {@link FileMetadataClient.find}. * * @param arg - Argument to find files */ - find: (arg: P1) => Promise; + find: (arg?: P1) => Promise<{ files: File[]; total: number }>; /** * Create a file share instance for this file. diff --git a/x-pack/plugins/files/server/file_service/file_action_types.ts b/x-pack/plugins/files/server/file_service/file_action_types.ts index c3d3a67ec6c66..f0242cb523d40 100644 --- a/x-pack/plugins/files/server/file_service/file_action_types.ts +++ b/x-pack/plugins/files/server/file_service/file_action_types.ts @@ -65,16 +65,6 @@ export interface DeleteFileArgs { fileKind: string; } -/** - * Arguments list files. - */ -export interface ListFilesArgs extends Pagination { - /** - * File kind, must correspond to a registered {@link FileKind}. - */ - fileKind: string; -} - /** * Arguments to get a file by ID. */ diff --git a/x-pack/plugins/files/server/file_service/file_service.ts b/x-pack/plugins/files/server/file_service/file_service.ts index f8d8534b7a635..e48b0a6ea38ca 100644 --- a/x-pack/plugins/files/server/file_service/file_service.ts +++ b/x-pack/plugins/files/server/file_service/file_service.ts @@ -5,14 +5,13 @@ * 2.0. */ -import type { FileJSON, FilesMetrics, File } from '../../common'; +import type { FilesMetrics, File, FileJSON } from '../../common'; import type { FileShareServiceStart } from '../file_share_service/types'; import type { CreateFileArgs, UpdateFileArgs, DeleteFileArgs, GetByIdArgs, - ListFilesArgs, FindFileArgs, } from './file_action_types'; @@ -55,14 +54,7 @@ export interface FileServiceStart { * * @param args - find files args */ - find(args: FindFileArgs): Promise>>; - - /** - * List all files of specific file kind. - * - * @param args - list files args - */ - list(args: ListFilesArgs): Promise>>; + find(args: FindFileArgs): Promise<{ files: Array>; total: number }>; /** * Get an instance of a share object diff --git a/x-pack/plugins/files/server/file_service/file_service_factory.ts b/x-pack/plugins/files/server/file_service/file_service_factory.ts index cff416e184356..393777c9a9abf 100644 --- a/x-pack/plugins/files/server/file_service/file_service_factory.ts +++ b/x-pack/plugins/files/server/file_service/file_service_factory.ts @@ -19,13 +19,7 @@ import { fileObjectType, fileShareObjectType, hiddenTypes } from '../saved_objec import { BlobStorageService } from '../blob_storage_service'; import { FileClientImpl } from '../file_client/file_client'; import { InternalFileShareService } from '../file_share_service'; -import { - CreateFileArgs, - FindFileArgs, - GetByIdArgs, - ListFilesArgs, - UpdateFileArgs, -} from './file_action_types'; +import { CreateFileArgs, FindFileArgs, GetByIdArgs, UpdateFileArgs } from './file_action_types'; import { InternalFileService } from './internal_file_service'; import { FileServiceStart } from './file_service'; import { FileKindsRegistry } from '../../common/file_kinds_registry'; @@ -105,10 +99,10 @@ export class FileServiceFactoryImpl implements FileServiceFactory { return internalFileService.getById(args) as Promise>; }, async find(args: FindFileArgs) { - return internalFileService.findFilesJSON(args) as Promise>>; - }, - async list(args: ListFilesArgs) { - return internalFileService.list(args) as Promise>>; + return internalFileService.findFilesJSON(args) as Promise<{ + files: Array>; + total: number; + }>; }, async getUsageMetrics() { return internalFileService.getUsageMetrics(); diff --git a/x-pack/plugins/files/server/file_service/index.ts b/x-pack/plugins/files/server/file_service/index.ts index c094c9f2d056b..457e5f3d4dfb8 100644 --- a/x-pack/plugins/files/server/file_service/index.ts +++ b/x-pack/plugins/files/server/file_service/index.ts @@ -11,7 +11,6 @@ export type { DeleteFileArgs, FindFileArgs, GetByIdArgs, - ListFilesArgs, UpdateFileArgs, } from './file_action_types'; export type { FileServiceStart } from './file_service'; diff --git a/x-pack/plugins/files/server/file_service/internal_file_service.ts b/x-pack/plugins/files/server/file_service/internal_file_service.ts index 4e676fbc26653..7768237e9fd50 100644 --- a/x-pack/plugins/files/server/file_service/internal_file_service.ts +++ b/x-pack/plugins/files/server/file_service/internal_file_service.ts @@ -21,7 +21,6 @@ import type { DeleteFileArgs, FindFileArgs, GetByIdArgs, - ListFilesArgs, } from './file_action_types'; import { createFileClient, FileClientImpl } from '../file_client/file_client'; /** @@ -88,28 +87,16 @@ export class InternalFileService { return file; } - public async list({ - fileKind: fileKindId, - page = 1, - perPage = 100, - }: ListFilesArgs): Promise { - const fileKind = this.getFileKind(fileKindId); - const result = await this.metadataClient.list({ - fileKind: fileKind.id, - page, - perPage, - }); - const fileClient = this.createFileClient(fileKind.id); - return result.map((file) => this.toFile(file.id, file.metadata, fileKind.id, fileClient)); - } - public getFileKind(id: string): FileKind { return this.fileKindRegistry.get(id); } - public async findFilesJSON(args: FindFileArgs): Promise { - const result = await this.metadataClient.find(args); - return result.map((r) => toJSON(r.id, r.metadata)); + public async findFilesJSON(args: FindFileArgs): Promise<{ files: FileJSON[]; total: number }> { + const { total, files } = await this.metadataClient.find(args); + return { + total, + files: files.map(({ id, metadata }) => toJSON(id, metadata)), + }; } public async getUsageMetrics(): Promise { diff --git a/x-pack/plugins/files/server/index.ts b/x-pack/plugins/files/server/index.ts index 7b1ecc5ac89ce..fe2bd3e69eec0 100755 --- a/x-pack/plugins/files/server/index.ts +++ b/x-pack/plugins/files/server/index.ts @@ -13,7 +13,6 @@ export type { FileDescriptor, GetMetadataArg, FindMetadataArg, - ListMetadataArg, UpdateMetadataArg, DeleteMetedataArg, FileMetadataClient, @@ -35,7 +34,6 @@ export type { export type { GetByIdArgs, FindFileArgs, - ListFilesArgs, CreateFileArgs, DeleteFileArgs, UpdateFileArgs, diff --git a/x-pack/plugins/files/server/integration_tests/file_service.test.ts b/x-pack/plugins/files/server/integration_tests/file_service.test.ts index 6277be74e1409..9ea208ca29855 100644 --- a/x-pack/plugins/files/server/integration_tests/file_service.test.ts +++ b/x-pack/plugins/files/server/integration_tests/file_service.test.ts @@ -99,8 +99,8 @@ describe('FileService', () => { } afterEach(async () => { await Promise.all(disposables.map((file) => file.delete())); - const results = await fileService.list({ fileKind }); - expect(results.length).toBe(0); + const { files } = await fileService.find({ kind: [fileKind] }); + expect(files.length).toBe(0); disposables = []; }); @@ -146,16 +146,46 @@ describe('FileService', () => { createDisposableFile({ fileKind, name: 'test-3' }), createDisposableFile({ fileKind, name: 'test-3' /* Also test file with same name */ }), ]); - const result = await fileService.list({ fileKind }); - expect(result.length).toBe(4); + const result = await fileService.find({ kind: [fileKind] }); + expect(result.files.length).toBe(4); + }); + + it('lists files and filters', async () => { + await Promise.all([ + createDisposableFile({ fileKind, name: 'foo-1' }), + createDisposableFile({ fileKind, name: 'foo-2' }), + createDisposableFile({ fileKind, name: 'foo-3' }), + createDisposableFile({ fileKind, name: 'test-3' }), + ]); + { + const { files, total } = await fileService.find({ + kind: [fileKind], + name: ['foo*'], + perPage: 2, + page: 1, + }); + expect(files.length).toBe(2); + expect(total).toBe(3); + } + + { + const { files, total } = await fileService.find({ + kind: [fileKind], + name: ['foo*'], + perPage: 2, + page: 2, + }); + expect(files.length).toBe(1); + expect(total).toBe(3); + } }); it('deletes files', async () => { const file = await fileService.create({ fileKind, name: 'test' }); - const files = await fileService.list({ fileKind }); - expect(files.length).toBe(1); + const result = await fileService.find({ kind: [fileKind] }); + expect(result.files.length).toBe(1); await file.delete(); - expect(await fileService.list({ fileKind })).toEqual([]); + expect(await fileService.find({ kind: [fileKind] })).toEqual({ files: [], total: 0 }); }); interface CustomMeta { diff --git a/x-pack/plugins/files/server/mocks.ts b/x-pack/plugins/files/server/mocks.ts index c5b5afa5d842e..033e94c3bfd7f 100644 --- a/x-pack/plugins/files/server/mocks.ts +++ b/x-pack/plugins/files/server/mocks.ts @@ -17,7 +17,6 @@ export const createFileServiceMock = (): DeeplyMockedKeys => ( getByToken: jest.fn(), getShareObject: jest.fn(), getUsageMetrics: jest.fn(), - list: jest.fn(), listShareObjects: jest.fn(), update: jest.fn(), updateShareObject: jest.fn(), diff --git a/x-pack/plugins/files/server/routes/file_kind/integration_tests/file_kind_http.test.ts b/x-pack/plugins/files/server/routes/file_kind/integration_tests/file_kind_http.test.ts index e4d4bbdf0b297..6acd1e3317344 100644 --- a/x-pack/plugins/files/server/routes/file_kind/integration_tests/file_kind_http.test.ts +++ b/x-pack/plugins/files/server/routes/file_kind/integration_tests/file_kind_http.test.ts @@ -110,14 +110,17 @@ describe('File kind HTTP API', () => { const { body: { files }, - } = await request.get(root, `/api/files/files/${fileKind}/list`).expect(200); + } = await request.post(root, `/api/files/files/${fileKind}/list`).send({}).expect(200); expect(files).toHaveLength(nrOfFiles); expect(files[0]).toEqual(expect.objectContaining({ name: 'test' })); const { body: { files: files2 }, - } = await request.get(root, `/api/files/files/${fileKind}/list?page=1&perPage=5`).expect(200); + } = await request + .post(root, `/api/files/files/${fileKind}/list?page=1&perPage=5`) + .send({}) + .expect(200); expect(files2).toHaveLength(5); }); diff --git a/x-pack/plugins/files/server/routes/file_kind/list.ts b/x-pack/plugins/files/server/routes/file_kind/list.ts index b6a869117b37f..b9b389f41b7a9 100644 --- a/x-pack/plugins/files/server/routes/file_kind/list.ts +++ b/x-pack/plugins/files/server/routes/file_kind/list.ts @@ -8,27 +8,47 @@ import { schema } from '@kbn/config-schema'; import type { FileJSON, FileKind } from '../../../common/types'; import { CreateRouteDefinition, FILES_API_ROUTES } from '../api_routes'; import type { CreateHandler, FileKindRouter } from './types'; +import { + stringOrArrayOfStrings, + nameStringOrArrayOfNameStrings, + toArrayOrUndefined, +} from '../find'; -export const method = 'get' as const; +export const method = 'post' as const; const rt = { + body: schema.object({ + status: schema.maybe(stringOrArrayOfStrings), + extension: schema.maybe(stringOrArrayOfStrings), + name: schema.maybe(nameStringOrArrayOfNameStrings), + meta: schema.maybe(schema.object({}, { unknowns: 'allow' })), + }), query: schema.object({ - page: schema.maybe(schema.number({ defaultValue: 1 })), + page: schema.maybe(schema.number()), perPage: schema.maybe(schema.number({ defaultValue: 100 })), }), }; -export type Endpoint = CreateRouteDefinition> }>; +export type Endpoint = CreateRouteDefinition< + typeof rt, + { files: Array>; total: number } +>; export const handler: CreateHandler = async ({ files, fileKind }, req, res) => { const { + body: { name, status, extension, meta }, query: { page, perPage }, } = req; const { fileService } = await files; - const response = await fileService.asCurrentUser().list({ fileKind, page, perPage }); - const body: Endpoint['output'] = { - files: response.map((result) => result.toJSON()), - }; + const body: Endpoint['output'] = await fileService.asCurrentUser().find({ + kind: [fileKind], + name: toArrayOrUndefined(name), + status: toArrayOrUndefined(status), + extension: toArrayOrUndefined(extension), + page, + perPage, + meta, + }); return res.ok({ body }); }; diff --git a/x-pack/plugins/files/server/routes/find.ts b/x-pack/plugins/files/server/routes/find.ts index 43348491b77b5..4f5a6da46b455 100644 --- a/x-pack/plugins/files/server/routes/find.ts +++ b/x-pack/plugins/files/server/routes/find.ts @@ -14,8 +14,13 @@ const method = 'post' as const; const string64 = schema.string({ maxLength: 64 }); const string256 = schema.string({ maxLength: 256 }); -const stringOrArrayOfStrings = schema.oneOf([string64, schema.arrayOf(string64)]); -const nameStringOrArrayOfNameStrings = schema.oneOf([string256, schema.arrayOf(string256)]); +export const stringOrArrayOfStrings = schema.oneOf([string64, schema.arrayOf(string64)]); +export const nameStringOrArrayOfNameStrings = schema.oneOf([string256, schema.arrayOf(string256)]); + +export function toArrayOrUndefined(val?: string | string[]): undefined | string[] { + if (val == null) return undefined; + return Array.isArray(val) ? val : [val]; +} const rt = { body: schema.object({ @@ -31,11 +36,7 @@ const rt = { }), }; -export type Endpoint = CreateRouteDefinition; - -function toArray(val: string | string[]) { - return Array.isArray(val) ? val : [val]; -} +export type Endpoint = CreateRouteDefinition; const handler: CreateHandler = async ({ files }, req, res) => { const { fileService } = await files; @@ -44,15 +45,18 @@ const handler: CreateHandler = async ({ files }, req, res) => { query, } = req; + const { files: results, total } = await fileService.asCurrentUser().find({ + kind: toArrayOrUndefined(kind), + name: toArrayOrUndefined(name), + status: toArrayOrUndefined(status), + extension: toArrayOrUndefined(extension), + meta, + ...query, + }); + const body: Endpoint['output'] = { - files: await fileService.asCurrentUser().find({ - kind: kind ? toArray(kind) : undefined, - name: name ? toArray(name) : undefined, - status: status ? toArray(status) : undefined, - extension: extension ? toArray(extension) : undefined, - meta, - ...query, - }), + total, + files: results, }; return res.ok({ body, diff --git a/x-pack/plugins/fleet/common/openapi/README.md b/x-pack/plugins/fleet/common/openapi/README.md index 5e7a3d05cf996..954af7eb76b00 100644 --- a/x-pack/plugins/fleet/common/openapi/README.md +++ b/x-pack/plugins/fleet/common/openapi/README.md @@ -1,14 +1,13 @@ # OpenAPI (Experimental) -The current self-contained spec file is [as JSON](https://raw.githubusercontent.com/elastic/kibana/master/x-pack/plugins/fleet/common/openapi/bundled.json) or [as YAML](https://raw.githubusercontent.com/elastic/kibana/master/x-pack/plugins/fleet/common/openapi/bundled.yaml) and can be used for online tools like those found at https://openapi.tools/. This spec is experimental and may be incomplete or change later. +> **_NOTE:_** This spec is experimental and may be incomplete or change later. -For example, online viewers for the specification like these: +The current self-contained spec file, available [as JSON](https://raw.githubusercontent.com/elastic/kibana/master/x-pack/plugins/fleet/common/openapi/bundled.json) or [as YAML](https://raw.githubusercontent.com/elastic/kibana/master/x-pack/plugins/fleet/common/openapi/bundled.yaml), can be used for online tools like those found at https://openapi.tools/. -| View spec using MrinDoc | View spec using Swagger UI | -|----|----| -| Screen Shot 2021-03-09 at 10 14 52 AM | Screen Shot 2021-03-09 at 10 14 04 AM | +For example, [click here to view the specification in the Swagger UI](https://petstore.swagger.io/?url=https://raw.githubusercontent.com/elastic/kibana/master/x-pack/plugins/fleet/common/openapi/bundled.json). A guide about the openApi specification can be found at [https://swagger.io/docs/specification/about/](https://swagger.io/docs/specification/about/). + ## The `openapi` folder * `entrypoint.yaml` is the overview file which links to the various files on disk. @@ -18,15 +17,15 @@ A guide about the openApi specification can be found at [https://swagger.io/docs [`responses`](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#responseObject) [`parameters`](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#parameterObject) - ## Tools +## Tools It is possible to validate the docs before bundling them with the following command: ``` - npx swagger-cli validate x-pack/plugins/fleet/common/openapi/entrypoint.yaml + npx swagger-cli validate x-pack/plugins/fleet/common/openapi/entrypoint.yaml ``` Then generate the `bundled` files with the following: - ``` - npx @redocly/openapi-cli bundle --ext yaml --output bundled.yaml entrypoint.yaml - npx @redocly/openapi-cli bundle --ext json --output bundled.json entrypoint.yaml - ``` + ``` + npx @redocly/openapi-cli bundle --ext yaml --output bundled.yaml entrypoint.yaml + npx @redocly/openapi-cli bundle --ext json --output bundled.json entrypoint.yaml + ``` diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/components/package_policy_input_stream.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/components/package_policy_input_stream.tsx index 5d6d6f5153360..9b94537a73c27 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/components/package_policy_input_stream.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/components/package_policy_input_stream.tsx @@ -47,7 +47,7 @@ const ScrollAnchor = styled.div` scroll-margin-top: ${(props) => parseFloat(props.theme.eui.euiHeaderHeightCompensation) * 2}px; `; -export const PackagePolicyInputStreamConfig: React.FunctionComponent<{ +interface Props { packagePolicy: NewPackagePolicy; packageInputStream: RegistryStream & { data_stream: { dataset: string; type: string } }; packageInfo: PackageInfo; @@ -56,7 +56,9 @@ export const PackagePolicyInputStreamConfig: React.FunctionComponent<{ updatePackagePolicyInputStream: (updatedStream: Partial) => void; inputStreamValidationResults: PackagePolicyConfigValidationResults; forceShowErrors?: boolean; -}> = memo( +} + +export const PackagePolicyInputStreamConfig = memo( ({ packagePolicy, packageInputStream, @@ -193,161 +195,174 @@ export const PackagePolicyInputStreamConfig: React.FunctionComponent<{ ); })} - {/* Advanced section */} - {(isPackagePolicyEdit || !!advancedVars.length) && ( - - - + {/* Advanced section - always shown since we display experimental indexing settings here */} + + + + + setIsShowingAdvanced(!isShowingAdvanced)} + flush="left" + > + + + + {!isShowingAdvanced && hasErrors && advancedVarsWithErrorsCount ? ( - setIsShowingAdvanced(!isShowingAdvanced)} - flush="left" - > + - + - {!isShowingAdvanced && hasErrors && advancedVarsWithErrorsCount ? ( + ) : null} + + + {isShowingAdvanced ? ( + <> + {advancedVars.map((varDef) => { + if (!packagePolicyInputStream.vars) return null; + const { name: varName, type: varType } = varDef; + const value = packagePolicyInputStream.vars?.[varName]?.value; + + return ( + + { + updatePackagePolicyInputStream({ + vars: { + ...packagePolicyInputStream.vars, + [varName]: { + type: varType, + value: newValue, + }, + }, + }); + }} + errors={inputStreamValidationResults?.vars![varName]} + forceShowErrors={forceShowErrors} + /> + + ); + })} + {/* Only show datastream pipelines and mappings on edit */} + {isPackagePolicyEdit && ( + <> + + + + + + + + )} + {/* Experimental index/datastream settings e.g. synthetic source */} + + - + +
+ +
+
+
+ + + + + ), + }} /> - ) : null} -
-
- {isShowingAdvanced ? ( - <> - {advancedVars.map((varDef) => { - if (!packagePolicyInputStream.vars) return null; - const { name: varName, type: varType } = varDef; - const value = packagePolicyInputStream.vars?.[varName]?.value; - - return ( - - { - updatePackagePolicyInputStream({ - vars: { - ...packagePolicyInputStream.vars, - [varName]: { - type: varType, - value: newValue, - }, - }, - }); - }} - errors={inputStreamValidationResults?.vars![varName]} - forceShowErrors={forceShowErrors} - /> - - ); - })} - {/* Only show datastream pipelines and mappings on edit */} - {isPackagePolicyEdit && ( - <> - - - - - - - - )} - {/* Experimental index/datastream settings e.g. synthetic source */} - - - - -
- -
-
-
- - + + + + dataStream === + getRegistryDataStreamAssetBaseName( + packagePolicyInputStream.data_stream + ) && features.synthetic_source + ) ?? false + } + label={ - - - ), - }} + id="xpack.fleet.createPackagePolicy.experimentalFeatures.syntheticSourceLabel" + defaultMessage="Synthetic source" /> - - - - - - dataStream === - getRegistryDataStreamAssetBaseName( - packagePolicyInputStream.data_stream - ) && features.synthetic_source - ) ?? false - } - label={ - + } + onChange={(e) => { + if (!packagePolicy.package) { + return; } - onChange={(e) => { - if (!packagePolicy.package) { - return; - } - updatePackagePolicy({ - package: { - ...packagePolicy.package, - experimental_data_stream_features: [ - { - data_stream: getRegistryDataStreamAssetBaseName( - packagePolicyInputStream.data_stream - ), - features: { - synthetic_source: e.target.checked, - }, - }, - ], + const newExperimentalDataStreamFeatures = [ + ...(packagePolicy.package.experimental_data_stream_features ?? []), + ]; + + const dataStream = getRegistryDataStreamAssetBaseName( + packagePolicyInputStream.data_stream + ); + + const existingSettingRecord = newExperimentalDataStreamFeatures.find( + (x) => x.data_stream === dataStream + ); + + if (existingSettingRecord) { + existingSettingRecord.features.synthetic_source = e.target.checked; + } else { + newExperimentalDataStreamFeatures.push({ + data_stream: dataStream, + features: { + synthetic_source: e.target.checked, }, }); - }} - /> - -
-
- - ) : null} -
- )} + } + + updatePackagePolicy({ + package: { + ...packagePolicy.package, + experimental_data_stream_features: + newExperimentalDataStreamFeatures, + }, + }); + }} + /> +
+
+
+ + ) : null} +
diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/multi_page_layout/components/add_first_integration_splash.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/multi_page_layout/components/add_first_integration_splash.tsx index 1e0aeb3236492..e1e53efa16985 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/multi_page_layout/components/add_first_integration_splash.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/multi_page_layout/components/add_first_integration_splash.tsx @@ -230,7 +230,7 @@ export const AddFirstIntegrationSplashScreen: React.FC<{ error?: RequestError | null; packageInfo?: PackageInfo; isLoading: boolean; - cancelClickHandler: React.ReactEventHandler; + cancelClickHandler?: React.ReactEventHandler; cancelUrl: string; onNext: () => void; }> = ({ @@ -276,6 +276,12 @@ export const AddFirstIntegrationSplashScreen: React.FC<{ + } cancelClickHandler={cancelClickHandler} isLoading={isLoading} onNext={onNext} diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/multi_page_layout/components/bottom_bar.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/multi_page_layout/components/bottom_bar.tsx index 228a89fa4e495..61875a063207d 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/multi_page_layout/components/bottom_bar.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/multi_page_layout/components/bottom_bar.tsx @@ -29,8 +29,9 @@ export const NotObscuredByBottomBar = styled('div')` export const CreatePackagePolicyBottomBar: React.FC<{ isLoading?: boolean; isDisabled?: boolean; - cancelClickHandler: React.ReactEventHandler; + cancelClickHandler?: React.ReactEventHandler; cancelUrl?: string; + cancelMessage?: React.ReactElement; actionMessage: React.ReactElement; onNext: () => void; noAnimation?: boolean; @@ -42,6 +43,7 @@ export const CreatePackagePolicyBottomBar: React.FC<{ cancelClickHandler, cancelUrl, actionMessage, + cancelMessage, isDisabled = false, noAnimation = false, }) => { @@ -53,10 +55,12 @@ export const CreatePackagePolicyBottomBar: React.FC<{ {/* eslint-disable-next-line @elastic/eui/href-or-on-click */} - + {cancelMessage || ( + + )} @@ -85,7 +89,7 @@ export const CreatePackagePolicyBottomBar: React.FC<{ }; export const AgentStandaloneBottomBar: React.FC<{ - cancelClickHandler: React.ReactEventHandler; + cancelClickHandler?: React.ReactEventHandler; cancelUrl?: string; onNext: () => void; noAnimation?: boolean; diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/multi_page_layout/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/multi_page_layout/index.tsx index c14d4bcd67752..6ce311b36aa6a 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/multi_page_layout/index.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/multi_page_layout/index.tsx @@ -10,10 +10,9 @@ import { i18n } from '@kbn/i18n'; import { splitPkgKey } from '../../../../../../../common/services'; -import { useGetPackageInfoByKey, useGetSettings } from '../../../../hooks'; +import { useGetPackageInfoByKey, useGetSettings, useLink } from '../../../../hooks'; import type { AddToPolicyParams, CreatePackagePolicyParams } from '../types'; -import { useCancelAddPackagePolicy } from '../hooks'; import { useGetAgentPolicyOrDefault } from './hooks'; @@ -55,11 +54,12 @@ export const CreatePackagePolicyMultiPage: CreatePackagePolicyParams = ({ queryParamsPolicyId, }) => { const { params } = useRouteMatch(); - - const { pkgName, pkgVersion } = splitPkgKey(params.pkgkey); + const { pkgkey, policyId, integration } = params; + const { pkgName, pkgVersion } = splitPkgKey(pkgkey); const [onSplash, setOnSplash] = useState(true); const [currentStep, setCurrentStep] = useState(0); const [isManaged, setIsManaged] = useState(true); + const { getHref } = useLink(); const [enrolledAgentIds, setEnrolledAgentIds] = useState([]); const toggleIsManaged = (newIsManaged: boolean) => { setIsManaged(newIsManaged); @@ -85,19 +85,21 @@ export const CreatePackagePolicyMultiPage: CreatePackagePolicyParams = ({ const settings = useMemo(() => settingsData?.item, [settingsData]); const integrationInfo = useMemo(() => { - if (!params.integration) return; + if (!integration) return; return packageInfo?.policy_templates?.find( - (policyTemplate) => policyTemplate.name === params.integration + (policyTemplate) => policyTemplate.name === integration ); - }, [packageInfo?.policy_templates, params]); + }, [packageInfo?.policy_templates, integration]); const splashScreenNext = () => { setOnSplash(false); }; - const { cancelClickHandler, cancelUrl } = useCancelAddPackagePolicy({ - from, - pkgkey: params.pkgkey, + const cancelUrl = getHref('add_integration_to_policy', { + pkgkey, + useMultiPageLayout: false, + ...(integration ? { integration } : {}), + ...(policyId ? { agentPolicyId: policyId } : {}), }); if (onSplash || !packageInfo) { @@ -108,7 +110,6 @@ export const CreatePackagePolicyMultiPage: CreatePackagePolicyParams = ({ integrationInfo={integrationInfo} packageInfo={packageInfo} cancelUrl={cancelUrl} - cancelClickHandler={cancelClickHandler} onNext={splashScreenNext} /> ); @@ -125,7 +126,6 @@ export const CreatePackagePolicyMultiPage: CreatePackagePolicyParams = ({ const stepsBack = () => { if (currentStep === 0) { - cancelClickHandler(null); return; } @@ -142,7 +142,6 @@ export const CreatePackagePolicyMultiPage: CreatePackagePolicyParams = ({ packageInfo={packageInfo} integrationInfo={integrationInfo} cancelUrl={cancelUrl} - cancelClickHandler={cancelClickHandler} onNext={stepsNext} onBack={stepsBack} isManaged={isManaged} diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/multi_page_layout/types.ts b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/multi_page_layout/types.ts index 327be01e0b3e9..d3a195e0513d4 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/multi_page_layout/types.ts +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/multi_page_layout/types.ts @@ -27,7 +27,7 @@ export interface MultiPageStepLayoutProps { enrollmentAPIKey?: EnrollmentAPIKey; packageInfo: PackageInfo; integrationInfo?: RegistryPolicyTemplate; - cancelClickHandler: React.ReactEventHandler; + cancelClickHandler?: React.ReactEventHandler; onBack: React.ReactEventHandler; cancelUrl: string; steps: MultiPageStep[]; diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/components/post_install_add_agent_modal.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/components/post_install_add_agent_modal.tsx index e82d51440e067..b6d568971140a 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/components/post_install_add_agent_modal.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/components/post_install_add_agent_modal.tsx @@ -6,9 +6,20 @@ */ import React from 'react'; -import { EuiConfirmModal } from '@elastic/eui'; +import { + EuiButton, + EuiButtonEmpty, + EuiModal, + EuiModalBody, + EuiModalFooter, + EuiModalHeader, + EuiModalHeaderTitle, + EuiText, +} from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; +import { WithGuidedOnboardingTour } from '../../../../../../../components'; +import { useIsGuidedOnboardingActive } from '../../../../../../../hooks'; import type { AgentPolicy, PackageInfo } from '../../../../../types'; const toTitleCase = (str: string) => str.charAt(0).toUpperCase() + str.substr(1); @@ -19,41 +30,64 @@ export const PostInstallAddAgentModal: React.FunctionComponent<{ packageInfo: PackageInfo; agentPolicy: AgentPolicy; }> = ({ onConfirm, onCancel, packageInfo, agentPolicy }) => { + const isGuidedOnboardingActive = useIsGuidedOnboardingActive(packageInfo.name); + return ( - - } - onCancel={onCancel} - onConfirm={onConfirm} - cancelButtonText={ - - } - confirmButtonText={ - - } - buttonColor="primary" - data-test-subj="postInstallAddAgentModal" - > - Elastic Agent, - }} - /> - + + + + + + + + + +

+ Elastic Agent, + }} + /> +

+
+
+ + + + + + + + + + + + +
); }; diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/devtools_request.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/devtools_request.tsx index 55e91154060b7..ca8c24b9a748d 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/devtools_request.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/devtools_request.tsx @@ -54,7 +54,7 @@ export function useDevToolsRequest({ 'xpack.fleet.createPackagePolicy.devtoolsRequestWithAgentPolicyDescription', { defaultMessage: - 'These Kibana requests creates a new agent policy and a new package policy.', + 'These Kibana requests create a new agent policy and a new package policy.', } ), ]; diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/components/package_list_grid.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/components/package_list_grid.tsx index a3495d599870d..74922314a8c48 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/components/package_list_grid.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/components/package_list_grid.tsx @@ -34,6 +34,8 @@ import type { IntegrationCardItem } from '../../../../../../common/types/models' import type { ExtendedIntegrationCategory, CategoryFacet } from '../screens/home/category_facets'; +import { promoteFeaturedIntegrations } from './utils'; + import { PackageCard } from './package_card'; export interface Props { @@ -41,7 +43,6 @@ export interface Props { controls?: ReactNode | ReactNode[]; title?: string; list: IntegrationCardItem[]; - featuredList?: JSX.Element | null; initialSearch?: string; selectedCategory: ExtendedIntegrationCategory; setSelectedCategory: (category: string) => void; @@ -63,7 +64,6 @@ export const PackageListGrid: FunctionComponent = ({ setSelectedCategory, categories, showMissingIntegrationMessage = false, - featuredList = null, callout, showCardLabels = true, }) => { @@ -99,16 +99,18 @@ export const PackageListGrid: FunctionComponent = ({ ? categories.find((category) => category.id === selectedCategory)?.title : undefined; - const filteredList = useMemo(() => { + const filteredPromotedList = useMemo(() => { if (isLoading) return []; - return searchTerm + const filteredList = searchTerm ? list.filter((item) => (localSearchRef.current!.search(searchTerm) as IntegrationCardItem[]) .map((match) => match[searchIdField]) .includes(item[searchIdField]) ) : list; - }, [isLoading, list, localSearchRef, searchTerm]); + + return promoteFeaturedIntegrations(filteredList, selectedCategory); + }, [isLoading, list, localSearchRef, searchTerm, selectedCategory]); const controlsContent = ; let gridContent: JSX.Element; @@ -118,7 +120,7 @@ export const PackageListGrid: FunctionComponent = ({ } else { gridContent = ( @@ -127,7 +129,6 @@ export const PackageListGrid: FunctionComponent = ({ return ( <> - {featuredList}
+ ({ + id: `epr:${name}`, + description: 'description', + icons: [], + title: name, + url: `/app/integrations/detail/${name}-1.0.0/overview`, + integration: '', + name, + version: '1.0.0', + release: 'ga', + categories: [], + isUnverified: false, + } as IntegrationCardItem); + +const intA = mockCard('A'); +const intB = mockCard('B'); +const intC = mockCard('C'); +const intD = mockCard('D'); + +describe('_promoteFeaturedIntegrations', () => { + it('should return list unaltered if no featured integrations for category', () => { + const list = [intA, intB]; + const selectedCategory = 'security'; + const featuredIntegrationsByCategory = {}; + expect( + _promoteFeaturedIntegrations(featuredIntegrationsByCategory, list, selectedCategory) + ).toEqual(list); + }); + it('should promote single integration to front of list if it matches the selected category', () => { + const list = [intA, intB]; + const selectedCategory = 'security'; + const featuredIntegrationsByCategory = { + security: ['B'], + }; + expect( + _promoteFeaturedIntegrations(featuredIntegrationsByCategory, list, selectedCategory) + ).toEqual([intB, intA]); + }); + it('should promote single integration to front of list if the selected category is empty string', () => { + const list = [intA, intB]; + const selectedCategory = ''; + const featuredIntegrationsByCategory = { + '': ['B'], + }; + expect( + _promoteFeaturedIntegrations(featuredIntegrationsByCategory, list, selectedCategory) + ).toEqual([intB, intA]); + }); + it('should respect the order of the featured integrations list', () => { + const list = [intA, intB, intC, intD]; + const selectedCategory = 'security'; + const featuredIntegrationsByCategory = { + security: ['C', 'B'], + }; + expect( + _promoteFeaturedIntegrations(featuredIntegrationsByCategory, list, selectedCategory) + ).toEqual([intC, intB, intA, intD]); + }); +}); diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/components/utils/promote_featured_integrations.ts b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/components/utils/promote_featured_integrations.ts new file mode 100644 index 0000000000000..93eac87a6aca1 --- /dev/null +++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/components/utils/promote_featured_integrations.ts @@ -0,0 +1,40 @@ +/* + * 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 partition from 'lodash/partition'; + +import { FEATURED_INTEGRATIONS_BY_CATEGORY } from '@kbn/custom-integrations-plugin/common'; + +import type { Props as PackageListGridProps } from '../package_list_grid'; + +type Category = PackageListGridProps['selectedCategory']; + +// exported for testing +export function _promoteFeaturedIntegrations( + featuredIntegrationsByCategory: Partial>, + packageList: PackageListGridProps['list'], + selectedCategory: Category +) { + const featuredIntegrationNames = featuredIntegrationsByCategory[selectedCategory]; + + if (!featuredIntegrationNames) return packageList; + + const [featuredIntegrations, otherIntegrations] = partition(packageList, (card) => + featuredIntegrationNames.includes(card.name) + ); + + // now return the integrations in the order they are defined in + const orderedFeaturedIntegrations = featuredIntegrationNames + .map((integrationName) => featuredIntegrations.find(({ name }) => name === integrationName)) + .filter((v) => v) as PackageListGridProps['list']; + + return [...orderedFeaturedIntegrations, ...otherIntegrations]; +} + +export const promoteFeaturedIntegrations = _promoteFeaturedIntegrations.bind( + null, + FEATURED_INTEGRATIONS_BY_CATEGORY +); diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/index.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/index.tsx index caefad75ad7a1..d649bede3db44 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/index.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/index.tsx @@ -48,12 +48,15 @@ import { import { pkgKeyFromPackageInfo } from '../../../../services'; import type { DetailViewPanelName, PackageInfo } from '../../../../types'; import { InstallStatus } from '../../../../types'; -import { Error, Loading, HeaderReleaseBadge } from '../../../../components'; +import { + Error, + Loading, + HeaderReleaseBadge, + WithGuidedOnboardingTour, +} from '../../../../components'; import type { WithHeaderLayoutProps } from '../../../../layouts'; import { WithHeaderLayout } from '../../../../layouts'; -import { WithGuidedOnboardingTour } from './components/with_guided_onboarding_tour'; - import { useIsFirstTimeAgentUser } from './hooks'; import { getInstallPkgRouteOptions } from './utils'; import { @@ -121,6 +124,7 @@ export function Detail() { const { createPackagePolicyMultiPageLayout: isExperimentalAddIntegrationPageEnabled } = ExperimentalFeaturesService.get(); const agentPolicyIdFromContext = getAgentPolicyId(); + const isOverviewPage = panel === 'overview'; // Package info state const [packageInfo, setPackageInfo] = useState(null); @@ -362,7 +366,8 @@ export function Detail() { - - - - } - href={addBasePath( - '/app/enterprise_search/content/search_indices/new_index?method=crawler' - )} - title={i18n.translate('xpack.fleet.featuredSearchTitle', { - defaultMessage: 'Web crawler', - })} - description={i18n.translate('xpack.fleet.featuredSearchDesc', { - defaultMessage: - 'Add search to your website with the Enterprise Search web crawler.', - })} - /> - - - - - } - /> - - - - - } - href={addBasePath('/app/integrations/detail/endpoint/')} - title={i18n.translate('xpack.fleet.featuredSecurityTitle', { - defaultMessage: 'Elastic Defend', - })} - description={i18n.translate('xpack.fleet.featuredSecurityDesc', { - defaultMessage: - 'Protect your hosts and cloud workloads with threat prevention, detection, and deep security data visibility.', - })} - /> - - - - - - ); - let noEprCallout; if (eprPackageLoadingError || eprCategoryLoadingError) { const error = eprPackageLoadingError || eprCategoryLoadingError; @@ -406,8 +336,7 @@ export const AvailablePackages: React.FC<{ return ( !!c), diff --git a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/confirm_incoming_data.tsx b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/confirm_incoming_data.tsx index 145811126691a..9e87a30034fd4 100644 --- a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/confirm_incoming_data.tsx +++ b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/confirm_incoming_data.tsx @@ -10,6 +10,8 @@ import { EuiCallOut, EuiText, EuiSpacer, EuiButton, EuiLink } from '@elastic/eui import { FormattedMessage } from '@kbn/i18n-react'; import { i18n } from '@kbn/i18n'; +import { useIsGuidedOnboardingActive, useStartServices } from '../../hooks'; + import type { InstalledIntegrationPolicy } from './use_get_agent_incoming_data'; import { useGetAgentIncomingData, usePollingIncomingData } from './use_get_agent_incoming_data'; @@ -29,6 +31,8 @@ export const ConfirmIncomingData: React.FunctionComponent = ({ troubleshootLink, }) => { const { incomingData, isLoading } = usePollingIncomingData(agentIds); + const isGuidedOnboardingActive = useIsGuidedOnboardingActive(installedPolicy?.name); + const { guidedOnboarding } = useStartServices(); const { enrolledAgents, numAgentsWithData, linkButton, message } = useGetAgentIncomingData( incomingData, @@ -37,6 +41,11 @@ export const ConfirmIncomingData: React.FunctionComponent = ({ if (!isLoading && enrolledAgents > 0 && numAgentsWithData > 0) { setAgentDataConfirmed(true); + if (installedPolicy?.name && isGuidedOnboardingActive) { + guidedOnboarding.guidedOnboardingApi?.completeGuidedOnboardingForIntegration( + installedPolicy!.name + ); + } } if (!agentDataConfirmed) { diff --git a/x-pack/plugins/fleet/public/components/index.ts b/x-pack/plugins/fleet/public/components/index.ts index 7eb22e4c459bb..24d53e8e9eb4e 100644 --- a/x-pack/plugins/fleet/public/components/index.ts +++ b/x-pack/plugins/fleet/public/components/index.ts @@ -27,3 +27,4 @@ export * from './platform_selector'; export { ConfirmForceInstallModal } from './confirm_force_install_modal'; export { DevtoolsRequestFlyoutButton } from './devtools_request_flyout'; export { HeaderReleaseBadge, InlineReleaseBadge } from './release_badge'; +export { WithGuidedOnboardingTour } from './with_guided_onboarding_tour'; diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/components/with_guided_onboarding_tour.tsx b/x-pack/plugins/fleet/public/components/with_guided_onboarding_tour.tsx similarity index 55% rename from x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/components/with_guided_onboarding_tour.tsx rename to x-pack/plugins/fleet/public/components/with_guided_onboarding_tour.tsx index 2ea4a6775d6e6..5ed0256e7f881 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/components/with_guided_onboarding_tour.tsx +++ b/x-pack/plugins/fleet/public/components/with_guided_onboarding_tour.tsx @@ -7,10 +7,11 @@ import React, { useEffect, useState } from 'react'; import type { FunctionComponent, ReactElement } from 'react'; +import type { EuiTourStepProps } from '@elastic/eui'; import { EuiButton, EuiText, EuiTourStep } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -type TourType = 'addIntegrationButton' | 'integrationsList'; +type TourType = 'addIntegrationButton' | 'integrationsList' | 'agentModalButton'; const getTourConfig = (packageKey: string, tourType: TourType) => { if (packageKey.startsWith('endpoint') && tourType === 'addIntegrationButton') { return { @@ -23,19 +24,52 @@ const getTourConfig = (packageKey: string, tourType: TourType) => { }), }; } + + if (packageKey.startsWith('kubernetes') && tourType === 'addIntegrationButton') { + return { + title: i18n.translate('xpack.fleet.guidedOnboardingTour.kubernetesButton.tourTitle', { + defaultMessage: 'Add Kubernetes', + }), + description: i18n.translate( + 'xpack.fleet.guidedOnboardingTour.kubernetesButton.tourDescription', + { + defaultMessage: + 'In just a few steps, configure your data with our recommended defaults. You can change this later.', + } + ), + }; + } + + if (packageKey.startsWith('kubernetes') && tourType === 'agentModalButton') { + return { + title: i18n.translate('xpack.fleet.guidedOnboardingTour.agentModalButton.tourTitle', { + defaultMessage: 'Add Elastic Agent', + }), + description: i18n.translate( + 'xpack.fleet.guidedOnboardingTour.agentModalButton.tourDescription', + { + defaultMessage: + 'In order to proceed with your setup, add Elastic Agent to your hosts now.', + } + ), + }; + } + return null; }; export const WithGuidedOnboardingTour: FunctionComponent<{ packageKey: string; - isGuidedOnboardingActive: boolean; + isTourVisible: boolean; tourType: TourType; + tourPosition?: EuiTourStepProps['anchorPosition']; children: ReactElement; -}> = ({ packageKey, isGuidedOnboardingActive, tourType, children }) => { + tourOffset?: EuiTourStepProps['offset']; +}> = ({ packageKey, isTourVisible, tourType, children, tourPosition, tourOffset }) => { const [isGuidedOnboardingTourOpen, setIsGuidedOnboardingTourOpen] = - useState(isGuidedOnboardingActive); + useState(isTourVisible); useEffect(() => { - setIsGuidedOnboardingTourOpen(isGuidedOnboardingActive); - }, [isGuidedOnboardingActive]); + setIsGuidedOnboardingTourOpen(isTourVisible); + }, [isTourVisible]); const config = getTourConfig(packageKey, tourType); return config ? ( @@ -46,8 +80,9 @@ export const WithGuidedOnboardingTour: FunctionComponent<{ onFinish={() => setIsGuidedOnboardingTourOpen(false)} step={1} stepsTotal={1} + offset={tourOffset} title={config.title} - anchorPosition="rightUp" + anchorPosition={tourPosition ? tourPosition : 'rightUp'} footerAction={ setIsGuidedOnboardingTourOpen(false)} size="s" color="success"> {i18n.translate('xpack.fleet.guidedOnboardingTour.nextButtonLabel', { diff --git a/x-pack/plugins/fleet/server/collectors/register.ts b/x-pack/plugins/fleet/server/collectors/register.ts index a0a373d0f435f..f19682a5a243a 100644 --- a/x-pack/plugins/fleet/server/collectors/register.ts +++ b/x-pack/plugins/fleet/server/collectors/register.ts @@ -19,13 +19,24 @@ import type { PackageUsage } from './package_collectors'; import { getFleetServerUsage } from './fleet_server_collector'; import type { FleetServerUsage } from './fleet_server_collector'; -interface Usage { +export interface Usage { agents_enabled: boolean; agents: AgentUsage; packages: PackageUsage[]; fleet_server: FleetServerUsage; } +export const fetchUsage = async (core: CoreSetup, config: FleetConfigType) => { + const [soClient, esClient] = await getInternalClients(core); + const usage = { + agents_enabled: getIsAgentsEnabled(config), + agents: await getAgentUsage(config, soClient, esClient), + fleet_server: await getFleetServerUsage(soClient, esClient), + packages: await getPackageUsage(soClient), + }; + return usage; +}; + export function registerFleetUsageCollector( core: CoreSetup, config: FleetConfigType, @@ -41,15 +52,7 @@ export function registerFleetUsageCollector( const fleetCollector = usageCollection.makeUsageCollector({ type: 'fleet', isReady: () => true, - fetch: async () => { - const [soClient, esClient] = await getInternalClients(core); - return { - agents_enabled: getIsAgentsEnabled(config), - agents: await getAgentUsage(config, soClient, esClient), - fleet_server: await getFleetServerUsage(soClient, esClient), - packages: await getPackageUsage(soClient), - }; - }, + fetch: async () => fetchUsage(core, config), schema: { agents_enabled: { type: 'boolean' }, agents: { diff --git a/x-pack/plugins/fleet/server/integration_tests/validate_bundled_packages.test.ts b/x-pack/plugins/fleet/server/integration_tests/validate_bundled_packages.test.ts index 79388d7d5b914..f43b1699eab10 100644 --- a/x-pack/plugins/fleet/server/integration_tests/validate_bundled_packages.test.ts +++ b/x-pack/plugins/fleet/server/integration_tests/validate_bundled_packages.test.ts @@ -50,7 +50,7 @@ describe('validate bundled packages', () => { bundledPackages .filter((pkg) => !EXCLUDED_PACKAGES.includes(pkg.name)) .map(async (bundledPackage) => { - const registryPackage = await Registry.getRegistryPackage( + const registryPackage = await Registry.getPackage( bundledPackage.name, bundledPackage.version ); diff --git a/x-pack/plugins/fleet/server/plugin.ts b/x-pack/plugins/fleet/server/plugin.ts index 9e02ad3f96407..7d00f944fbf81 100644 --- a/x-pack/plugins/fleet/server/plugin.ts +++ b/x-pack/plugins/fleet/server/plugin.ts @@ -91,6 +91,7 @@ import type { AgentPolicyServiceInterface, PackageService, } from './services'; +import { FleetUsageSender } from './services'; import { appContextService, licenseService, @@ -100,7 +101,7 @@ import { AgentServiceImpl, PackageServiceImpl, } from './services'; -import { registerFleetUsageCollector } from './collectors/register'; +import { registerFleetUsageCollector, fetchUsage } from './collectors/register'; import { getAuthzFromRequest, makeRouterWithFleetAuthz } from './routes/security'; import { FleetArtifactsClient } from './services/artifacts'; import type { FleetRouter } from './types/request_context'; @@ -217,6 +218,7 @@ export class FleetPlugin private readonly telemetryEventsSender: TelemetryEventsSender; private readonly fleetStatus$: BehaviorSubject; private bulkActionsResolver?: BulkActionsResolver; + private fleetUsageSender?: FleetUsageSender; private agentService?: AgentService; private packageService?: PackageService; @@ -378,6 +380,14 @@ export class FleetPlugin // Register usage collection registerFleetUsageCollector(core, config, deps.usageCollection); + const fetch = async () => fetchUsage(core, config); + this.fleetUsageSender = new FleetUsageSender( + deps.taskManager, + core, + fetch, + this.kibanaVersion, + this.isProductionMode + ); const router: FleetRouter = core.http.createRouter(); // Allow read-only users access to endpoints necessary for Integrations UI @@ -444,6 +454,7 @@ export class FleetPlugin this.telemetryEventsSender.start(plugins.telemetry, core); this.bulkActionsResolver?.start(plugins.taskManager); + this.fleetUsageSender?.start(plugins.taskManager); const logger = appContextService.getLogger(); diff --git a/x-pack/plugins/fleet/server/routes/data_streams/handlers.ts b/x-pack/plugins/fleet/server/routes/data_streams/handlers.ts index d761f8b5e7f30..274ab22999ff8 100644 --- a/x-pack/plugins/fleet/server/routes/data_streams/handlers.ts +++ b/x-pack/plugins/fleet/server/routes/data_streams/handlers.ts @@ -59,8 +59,16 @@ export const getListHandler: RequestHandler = async (context, request, response) getPackageSavedObjects(savedObjects.client), ]); - const dataStreamsInfoByName = keyBy(dataStreamsInfo, 'name'); - const dataStreamsStatsByName = keyBy(dataStreamStats, 'data_stream'); + const filteredDataStreamsInfo = dataStreamsInfo.filter( + (ds) => ds?._meta?.managed_by === 'fleet' + ); + + const dataStreamsInfoByName = keyBy(filteredDataStreamsInfo, 'name'); + + const filteredDataStreamsStats = dataStreamStats.filter( + (dss) => !!dataStreamsInfoByName[dss.data_stream] + ); + const dataStreamsStatsByName = keyBy(filteredDataStreamsStats, 'data_stream'); // Combine data stream info const dataStreams = merge(dataStreamsInfoByName, dataStreamsStatsByName); diff --git a/x-pack/plugins/fleet/server/services/epm/package_service.mock.ts b/x-pack/plugins/fleet/server/services/epm/package_service.mock.ts index f703399ca6df7..806f295ec2c4e 100644 --- a/x-pack/plugins/fleet/server/services/epm/package_service.mock.ts +++ b/x-pack/plugins/fleet/server/services/epm/package_service.mock.ts @@ -11,7 +11,7 @@ const createClientMock = (): jest.Mocked => ({ getInstallation: jest.fn(), ensureInstalledPackage: jest.fn(), fetchFindLatestPackage: jest.fn(), - getRegistryPackage: jest.fn(), + getPackage: jest.fn(), reinstallEsAssets: jest.fn(), }); diff --git a/x-pack/plugins/fleet/server/services/epm/package_service.test.ts b/x-pack/plugins/fleet/server/services/epm/package_service.test.ts index 4f98776f53d60..f4f853d778923 100644 --- a/x-pack/plugins/fleet/server/services/epm/package_service.test.ts +++ b/x-pack/plugins/fleet/server/services/epm/package_service.test.ts @@ -31,7 +31,7 @@ const testKeys = [ 'getInstallation', 'ensureInstalledPackage', 'fetchFindLatestPackage', - 'getRegistryPackage', + 'getPackage', 'reinstallEsAssets', ]; @@ -99,16 +99,16 @@ function getTest( break; case testKeys[3]: test = { - method: mocks.packageClient.getRegistryPackage.bind(mocks.packageClient), + method: mocks.packageClient.getPackage.bind(mocks.packageClient), args: ['package name', '8.0.0'], - spy: jest.spyOn(epmRegistry, 'getRegistryPackage'), + spy: jest.spyOn(epmRegistry, 'getPackage'), spyArgs: ['package name', '8.0.0', undefined], spyResponse: { - packageInfo: { name: 'getRegistryPackage test' }, + packageInfo: { name: 'getPackage test' }, paths: ['/some/test/path'], }, expectedReturnValue: { - packageInfo: { name: 'getRegistryPackage test' }, + packageInfo: { name: 'getPackage test' }, paths: ['/some/test/path'], }, }; diff --git a/x-pack/plugins/fleet/server/services/epm/package_service.ts b/x-pack/plugins/fleet/server/services/epm/package_service.ts index 71ab87c7d92bd..45fb673771327 100644 --- a/x-pack/plugins/fleet/server/services/epm/package_service.ts +++ b/x-pack/plugins/fleet/server/services/epm/package_service.ts @@ -19,13 +19,14 @@ import type { InstallablePackage, Installation, RegistryPackage, + ArchivePackage, BundledPackage, } from '../../types'; import { checkSuperuser } from '../../routes/security'; import { FleetUnauthorizedError } from '../../errors'; import { installTransforms, isTransform } from './elasticsearch/transform/install'; -import { fetchFindLatestPackageOrThrow, getRegistryPackage } from './registry'; +import { fetchFindLatestPackageOrThrow, getPackage } from './registry'; import { ensureInstalledPackage, getInstallation } from './packages'; export type InstalledAssetType = EsAssetReference; @@ -46,10 +47,10 @@ export interface PackageClient { fetchFindLatestPackage(packageName: string): Promise; - getRegistryPackage( + getPackage( packageName: string, packageVersion: string - ): Promise<{ packageInfo: RegistryPackage; paths: string[] }>; + ): Promise<{ packageInfo: ArchivePackage; paths: string[] }>; reinstallEsAssets( packageInfo: InstallablePackage, @@ -120,13 +121,13 @@ class PackageClientImpl implements PackageClient { return fetchFindLatestPackageOrThrow(packageName); } - public async getRegistryPackage( + public async getPackage( packageName: string, packageVersion: string, - options?: Parameters['2'] + options?: Parameters['2'] ) { await this.#runPreflight(); - return getRegistryPackage(packageName, packageVersion, options); + return getPackage(packageName, packageVersion, options); } public async reinstallEsAssets( diff --git a/x-pack/plugins/fleet/server/services/epm/packages/get.test.ts b/x-pack/plugins/fleet/server/services/epm/packages/get.test.ts index af168a8cc1619..20ed655d97176 100644 --- a/x-pack/plugins/fleet/server/services/epm/packages/get.test.ts +++ b/x-pack/plugins/fleet/server/services/epm/packages/get.test.ts @@ -188,7 +188,11 @@ describe('When using EPM `get` services', () => { name: 'my-package', version: '1.0.0', } as RegistryPackage); - MockRegistry.getRegistryPackage.mockResolvedValue({ + MockRegistry.fetchInfo.mockResolvedValue({ + name: 'my-package', + version: '1.0.0', + } as RegistryPackage); + MockRegistry.getPackage.mockResolvedValue({ paths: [], packageInfo: { name: 'my-package', @@ -366,7 +370,7 @@ describe('When using EPM `get` services', () => { status: 'not_installed', }); - expect(MockRegistry.getRegistryPackage).not.toHaveBeenCalled(); + expect(MockRegistry.getPackage).not.toHaveBeenCalled(); }); // when calling the get package endpoint without a package version we @@ -392,7 +396,7 @@ describe('When using EPM `get` services', () => { status: 'not_installed', }); - expect(MockRegistry.getRegistryPackage).not.toHaveBeenCalled(); + expect(MockRegistry.getPackage).not.toHaveBeenCalled(); }); }); }); diff --git a/x-pack/plugins/fleet/server/services/epm/packages/get.ts b/x-pack/plugins/fleet/server/services/epm/packages/get.ts index b0aaa64a69239..b8b447a8de526 100644 --- a/x-pack/plugins/fleet/server/services/epm/packages/get.ts +++ b/x-pack/plugins/fleet/server/services/epm/packages/get.ts @@ -152,13 +152,12 @@ export async function getPackageInfo({ // If same version is available in registry and skipArchive is true, use the info from the registry (faster), // otherwise build it from the archive let paths: string[]; - let packageInfo: RegistryPackage | ArchivePackage | undefined = skipArchive - ? await Registry.fetchInfo(pkgName, resolvedPkgVersion).catch(() => undefined) - : undefined; - + const registryInfo = await Registry.fetchInfo(pkgName, resolvedPkgVersion).catch(() => undefined); + let packageInfo; // We need to get input only packages from source to get all fields // see https://github.com/elastic/package-registry/issues/864 - if (packageInfo && packageInfo.type !== 'input') { + if (registryInfo && skipArchive && registryInfo.type !== 'input') { + packageInfo = registryInfo; // Fix the paths paths = packageInfo.assets?.map((path) => @@ -170,7 +169,6 @@ export async function getPackageInfo({ pkgVersion: resolvedPkgVersion, savedObjectsClient, installedPkg: savedObject?.attributes, - getPkgInfoFromArchive: packageInfo?.type === 'input', ignoreUnverified, })); } @@ -235,13 +233,12 @@ interface PackageResponse { } type GetPackageResponse = PackageResponse | undefined; -// gets package from install_source if it exists otherwise gets from registry +// gets package from install_source export async function getPackageFromSource(options: { pkgName: string; pkgVersion: string; installedPkg?: Installation; savedObjectsClient: SavedObjectsClientContract; - getPkgInfoFromArchive?: boolean; ignoreUnverified?: boolean; }): Promise { const logger = appContextService.getLogger(); @@ -250,7 +247,6 @@ export async function getPackageFromSource(options: { pkgVersion, installedPkg, savedObjectsClient, - getPkgInfoFromArchive = true, ignoreUnverified = false, } = options; let res: GetPackageResponse; @@ -280,11 +276,12 @@ export async function getPackageFromSource(options: { logger.debug(`retrieved installed package ${pkgName}-${pkgVersion} from ES`); } } - // for packages not in cache or package storage and installed from registry, check registry + // install source is now archive in all cases + // See https://github.com/elastic/kibana/issues/115032 if (!res && pkgInstallSource === 'registry') { try { - res = await Registry.getRegistryPackage(pkgName, pkgVersion); - logger.debug(`retrieved installed package ${pkgName}-${pkgVersion} from registry`); + res = await Registry.getPackage(pkgName, pkgVersion); + logger.debug(`retrieved installed package ${pkgName}-${pkgVersion}`); } catch (error) { if (error instanceof PackageFailedVerificationError) { throw error; @@ -294,12 +291,8 @@ export async function getPackageFromSource(options: { } } } else { - // else package is not installed or installed and missing from cache and storage and installed from registry - res = await Registry.getRegistryPackage(pkgName, pkgVersion, { - getPkgInfoFromArchive, - ignoreUnverified, - }); - logger.debug(`retrieved uninstalled package ${pkgName}-${pkgVersion} from registry`); + res = await Registry.getPackage(pkgName, pkgVersion, { ignoreUnverified }); + logger.debug(`retrieved package ${pkgName}-${pkgVersion} from registry`); } if (!res) { throw new FleetError(`package info for ${pkgName}-${pkgVersion} does not exist`); diff --git a/x-pack/plugins/fleet/server/services/epm/packages/install.test.ts b/x-pack/plugins/fleet/server/services/epm/packages/install.test.ts index c58700716d18a..d8f4f4a70adaa 100644 --- a/x-pack/plugins/fleet/server/services/epm/packages/install.test.ts +++ b/x-pack/plugins/fleet/server/services/epm/packages/install.test.ts @@ -84,7 +84,7 @@ describe('install', () => { .spyOn(Registry, 'fetchFindLatestPackageOrThrow') .mockImplementation(() => Promise.resolve({ version: '1.3.0' } as any)); jest - .spyOn(Registry, 'getRegistryPackage') + .spyOn(Registry, 'getPackage') .mockImplementation(() => Promise.resolve({ packageInfo: { license: 'basic' } } as any)); mockGetBundledPackages.mockReset(); diff --git a/x-pack/plugins/fleet/server/services/epm/packages/install.ts b/x-pack/plugins/fleet/server/services/epm/packages/install.ts index 91e2c7d241fd7..ebd0bde8b09b4 100644 --- a/x-pack/plugins/fleet/server/services/epm/packages/install.ts +++ b/x-pack/plugins/fleet/server/services/epm/packages/install.ts @@ -302,7 +302,7 @@ async function installPackageFromRegistry({ Registry.fetchFindLatestPackageOrThrow(pkgName, { ignoreConstraints, }), - Registry.getRegistryPackage(pkgName, pkgVersion, { + Registry.getPackage(pkgName, pkgVersion, { ignoreUnverified: force && !neverIgnoreVerificationError, }), ]); diff --git a/x-pack/plugins/fleet/server/services/epm/registry/index.ts b/x-pack/plugins/fleet/server/services/epm/registry/index.ts index 2e5fff50af576..4213a50ebf5bf 100644 --- a/x-pack/plugins/fleet/server/services/epm/registry/index.ts +++ b/x-pack/plugins/fleet/server/services/epm/registry/index.ts @@ -246,39 +246,66 @@ export async function getInfo(name: string, version: string) { // input type packages must get their pkg info from the archive if (packageInfo.type === 'integration') setPackageInfo({ name, version, packageInfo }); } + return packageInfo as RegistryPackage; }); } -export async function getRegistryPackage( +// Check that the packageInfo exists in cache +// If not, retrieve it from the archive +async function getPackageInfoFromArchiveOrCache( name: string, version: string, - options?: { ignoreUnverified?: boolean; getPkgInfoFromArchive?: boolean } + archiveBuffer: Buffer, + archivePath: string +): Promise { + const cachedInfo = getPackageInfo({ name, version }); + + if (!cachedInfo) { + const { packageInfo } = await generatePackageInfoFromArchiveBuffer( + archiveBuffer, + ensureContentType(archivePath) + ); + // set the download URL as it isn't contained in the manifest + // this allows us to re-download the archive during package install + setPackageInfo({ packageInfo: { ...packageInfo, download: archivePath }, name, version }); + return packageInfo; + } else { + return cachedInfo; + } +} + +export async function getPackage( + name: string, + version: string, + options?: { ignoreUnverified?: boolean } ): Promise<{ paths: string[]; - packageInfo: RegistryPackage; + packageInfo: ArchivePackage; verificationResult?: PackageVerificationResult; }> { const verifyPackage = appContextService.getExperimentalFeatures().packageVerification; let paths = getArchiveFilelist({ name, version }); let verificationResult = verifyPackage ? getVerificationResult({ name, version }) : undefined; + + const { + archiveBuffer, + archivePath, + verificationResult: latestVerificationResult, + } = await withPackageSpan('Fetch package archive from archive buffer', () => + fetchArchiveBuffer({ + pkgName: name, + pkgVersion: version, + shouldVerify: verifyPackage, + ignoreUnverified: options?.ignoreUnverified, + }) + ); + + if (latestVerificationResult) { + verificationResult = latestVerificationResult; + setVerificationResult({ name, version }, latestVerificationResult); + } if (!paths || paths.length === 0) { - const { - archiveBuffer, - archivePath, - verificationResult: latestVerificationResult, - } = await withPackageSpan('Fetch package archive from registry', () => - fetchArchiveBuffer({ - pkgName: name, - pkgVersion: version, - shouldVerify: verifyPackage, - ignoreUnverified: options?.ignoreUnverified, - }) - ); - if (latestVerificationResult) { - verificationResult = latestVerificationResult; - setVerificationResult({ name, version }, latestVerificationResult); - } paths = await withPackageSpan('Unpack archive', () => unpackBufferToCache({ name, @@ -287,17 +314,14 @@ export async function getRegistryPackage( contentType: ensureContentType(archivePath), }) ); - const cachedInfo = getPackageInfo({ name, version }); - if (options?.getPkgInfoFromArchive && !cachedInfo) { - const { packageInfo } = await generatePackageInfoFromArchiveBuffer( - archiveBuffer, - ensureContentType(archivePath) - ); - setPackageInfo({ packageInfo, name, version }); - } } - const packageInfo = await getInfo(name, version); + const packageInfo = await getPackageInfoFromArchiveOrCache( + name, + version, + archiveBuffer, + archivePath + ); return { paths, packageInfo, verificationResult }; } @@ -325,9 +349,17 @@ export async function fetchArchiveBuffer({ verificationResult?: PackageVerificationResult; }> { const logger = appContextService.getLogger(); - const { download: archivePath } = await getInfo(pkgName, pkgVersion); + let { download: archivePath } = await getInfo(pkgName, pkgVersion); + + // Bundled packages don't have a download path when they're installed, as they're + // ArchivePackage objects - so we fake the download path here instead + if (!archivePath) { + archivePath = `/epr/${pkgName}/${pkgName}-${pkgVersion}.zip`; + } + const archiveUrl = `${getRegistryUrl()}${archivePath}`; const archiveBuffer = await getResponseStream(archiveUrl).then(streamToBuffer); + if (shouldVerify) { const verificationResult = await verifyPackageArchiveSignature({ pkgName, diff --git a/x-pack/plugins/fleet/server/services/fleet_usage_sender.ts b/x-pack/plugins/fleet/server/services/fleet_usage_sender.ts new file mode 100644 index 0000000000000..b7ab806e5f8c1 --- /dev/null +++ b/x-pack/plugins/fleet/server/services/fleet_usage_sender.ts @@ -0,0 +1,198 @@ +/* + * 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. + */ +/* eslint-disable max-classes-per-file */ +import type { + ConcreteTaskInstance, + TaskManagerStartContract, + TaskManagerSetupContract, +} from '@kbn/task-manager-plugin/server'; +import type { CoreSetup } from '@kbn/core/server'; + +import { ElasticV3ServerShipper } from '@kbn/analytics-shippers-elastic-v3-server'; + +import type { Usage } from '../collectors/register'; + +import { appContextService } from './app_context'; + +export class FleetShipper extends ElasticV3ServerShipper { + public static shipperName = 'fleet_shipper'; +} + +export class FleetUsageSender { + private taskManager?: TaskManagerStartContract; + private taskId = 'Fleet-Usage-Sender-Task'; + private taskType = 'Fleet-Usage-Sender'; + + constructor( + taskManager: TaskManagerSetupContract, + core: CoreSetup, + fetchUsage: () => Promise, + kibanaVersion: string, + isProductionMode: boolean + ) { + taskManager.registerTaskDefinitions({ + [this.taskType]: { + title: 'Fleet Usage Sender', + timeout: '1m', + maxAttempts: 1, + createTaskRunner: ({ taskInstance }: { taskInstance: ConcreteTaskInstance }) => { + return { + async run() { + appContextService.getLogger().info('Running Fleet Usage telemetry send task'); + + try { + const usageData = await fetchUsage(); + appContextService.getLogger().debug(JSON.stringify(usageData)); + core.analytics.reportEvent('Fleet Usage', usageData); + } catch (error) { + appContextService + .getLogger() + .error('Error occurred while sending Fleet Usage telemetry: ' + error); + } + }, + + async cancel() {}, + }; + }, + }, + }); + this.registerTelemetryEventType(core); + + core.analytics.registerShipper(FleetShipper, { + channelName: 'fleet-usages', + version: kibanaVersion, + sendTo: isProductionMode ? 'production' : 'staging', + }); + } + + public async start(taskManager: TaskManagerStartContract) { + this.taskManager = taskManager; + + appContextService.getLogger().info(`Task ${this.taskId} scheduled with interval 1h`); + await this.taskManager?.ensureScheduled({ + id: this.taskId, + taskType: this.taskType, + schedule: { + interval: '1h', + }, + scope: ['fleet'], + state: {}, + params: {}, + }); + } + + /** + * took schema from [here](https://github.com/elastic/kibana/blob/main/x-pack/plugins/fleet/server/collectors/register.ts#L53) and adapted to EBT format + */ + private registerTelemetryEventType(core: CoreSetup): void { + core.analytics.registerEventType({ + eventType: 'Fleet Usage', + schema: { + agents_enabled: { type: 'boolean', _meta: { description: 'agents enabled' } }, + agents: { + properties: { + total_enrolled: { + type: 'long', + _meta: { + description: 'The total number of enrolled agents, in any state', + }, + }, + healthy: { + type: 'long', + _meta: { + description: 'The total number of enrolled agents in a healthy state', + }, + }, + unhealthy: { + type: 'long', + _meta: { + description: 'The total number of enrolled agents in an unhealthy state', + }, + }, + updating: { + type: 'long', + _meta: { + description: 'The total number of enrolled agents in an updating state', + }, + }, + offline: { + type: 'long', + _meta: { + description: 'The total number of enrolled agents currently offline', + }, + }, + total_all_statuses: { + type: 'long', + _meta: { + description: 'The total number of agents in any state, both enrolled and inactive', + }, + }, + }, + }, + fleet_server: { + properties: { + total_enrolled: { + type: 'long', + _meta: { + description: 'The total number of enrolled Fleet Server agents, in any state', + }, + }, + total_all_statuses: { + type: 'long', + _meta: { + description: + 'The total number of Fleet Server agents in any state, both enrolled and inactive.', + }, + }, + healthy: { + type: 'long', + _meta: { + description: 'The total number of enrolled Fleet Server agents in a healthy state.', + }, + }, + unhealthy: { + type: 'long', + _meta: { + description: + 'The total number of enrolled Fleet Server agents in an unhealthy state', + }, + }, + updating: { + type: 'long', + _meta: { + description: + 'The total number of enrolled Fleet Server agents in an updating state', + }, + }, + offline: { + type: 'long', + _meta: { + description: 'The total number of enrolled Fleet Server agents currently offline', + }, + }, + num_host_urls: { + type: 'long', + _meta: { + description: 'The number of Fleet Server hosts configured in Fleet settings.', + }, + }, + }, + }, + packages: { + type: 'array', + items: { + properties: { + name: { type: 'keyword' }, + version: { type: 'keyword' }, + enabled: { type: 'boolean' }, + }, + }, + }, + }, + }); + } +} diff --git a/x-pack/plugins/fleet/server/services/index.ts b/x-pack/plugins/fleet/server/services/index.ts index aafbb383cbb0d..6078e2696f3b9 100644 --- a/x-pack/plugins/fleet/server/services/index.ts +++ b/x-pack/plugins/fleet/server/services/index.ts @@ -62,3 +62,5 @@ export type { PackageService, PackageClient } from './epm'; // Fleet server policy config export { migrateSettingsToFleetServerHost } from './fleet_server_host'; + +export { FleetUsageSender } from './fleet_usage_sender'; diff --git a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx index e4d87d26cbecc..d5389e1576753 100644 --- a/x-pack/plugins/global_search_bar/public/components/search_bar.tsx +++ b/x-pack/plugins/global_search_bar/public/components/search_bar.tsx @@ -269,7 +269,7 @@ export const SearchBar: FC = ({ ); const placeholderText = i18n.translate('xpack.globalSearchBar.searchBar.placeholder', { - defaultMessage: 'Find apps, content, and more. Ex: Discover', + defaultMessage: 'Find apps, content, and more.', }); const keyboardShortcutTooltip = `${i18n.translate( 'xpack.globalSearchBar.searchBar.shortcutTooltip.description', diff --git a/x-pack/plugins/infra/public/pages/metrics/hosts/components/hosts_table.tsx b/x-pack/plugins/infra/public/pages/metrics/hosts/components/hosts_table.tsx index e92ac801e8612..143f7fedb1420 100644 --- a/x-pack/plugins/infra/public/pages/metrics/hosts/components/hosts_table.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/hosts/components/hosts_table.tsx @@ -35,7 +35,7 @@ const getLensHostsTable = ( ], state: { datasourceStates: { - indexpattern: { + formBased: { layers: { 'cbe5d8a0-381d-49bf-b8ac-f8f312ec7129': { columns: { diff --git a/x-pack/plugins/infra/server/lib/alerting/common/messages.ts b/x-pack/plugins/infra/server/lib/alerting/common/messages.ts index 3ca8160d2dda8..80dae7ffac959 100644 --- a/x-pack/plugins/infra/server/lib/alerting/common/messages.ts +++ b/x-pack/plugins/infra/server/lib/alerting/common/messages.ts @@ -214,3 +214,45 @@ export const viewInAppUrlActionVariableDescription = i18n.translate( 'Link to the view or feature within Elastic that can be used to investigate the alert and its context further', } ); + +export const cloudActionVariableDescription = i18n.translate( + 'xpack.infra.metrics.alerting.cloudActionVariableDescription', + { + defaultMessage: 'The cloud object defined by ECS if available in the source.', + } +); + +export const hostActionVariableDescription = i18n.translate( + 'xpack.infra.metrics.alerting.hostActionVariableDescription', + { + defaultMessage: 'The host object defined by ECS if available in the source.', + } +); + +export const containerActionVariableDescription = i18n.translate( + 'xpack.infra.metrics.alerting.containerActionVariableDescription', + { + defaultMessage: 'The container object defined by ECS if available in the source.', + } +); + +export const orchestratorActionVariableDescription = i18n.translate( + 'xpack.infra.metrics.alerting.orchestratorActionVariableDescription', + { + defaultMessage: 'The orchestrator object defined by ECS if available in the source.', + } +); + +export const labelsActionVariableDescription = i18n.translate( + 'xpack.infra.metrics.alerting.labelsActionVariableDescription', + { + defaultMessage: 'List of labels associated with the entity where this alert triggered.', + } +); + +export const tagsActionVariableDescription = i18n.translate( + 'xpack.infra.metrics.alerting.tagsActionVariableDescription', + { + defaultMessage: 'List of tags associated with the entity where this alert triggered.', + } +); diff --git a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/evaluate_condition.ts b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/evaluate_condition.ts index 615df9f9c64b7..21ae9388da239 100644 --- a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/evaluate_condition.ts +++ b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/evaluate_condition.ts @@ -22,6 +22,7 @@ export type ConditionResult = InventoryMetricConditions & { currentValue: number; isNoData: boolean; isError: boolean; + context: [x: string]; }; export const evaluateCondition = async ({ @@ -82,6 +83,14 @@ export const evaluateCondition = async ({ isNoData: value === null, isError: value === undefined, currentValue: value.value, + context: { + cloud: value.cloud, + host: value.host, + container: value.container, + orchestrator: value.orchestrator, + labels: value.labels, + tags: value.tags, + }, }; }) as unknown; // Typescript doesn't seem to know what `throw` is doing diff --git a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/inventory_metric_threshold_executor.ts b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/inventory_metric_threshold_executor.ts index 7dd2678d7f7ae..2e51d2e8291b5 100644 --- a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/inventory_metric_threshold_executor.ts +++ b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/inventory_metric_threshold_executor.ts @@ -49,6 +49,7 @@ type InventoryMetricThresholdAlert = Alert< type InventoryMetricThresholdAlertFactory = ( id: string, reason: string, + additionalContext?: [x: string] | null, threshold?: number | undefined, value?: number | undefined ) => InventoryMetricThresholdAlert; @@ -66,12 +67,13 @@ export const createInventoryMetricThresholdExecutor = (libs: InfraBackendLibs) = if (criteria.length === 0) throw new Error('Cannot execute an alert with 0 conditions'); const logger = createScopedLogger(libs.logger, 'inventoryRule', { alertId, executionId }); const { alertWithLifecycle, savedObjectsClient, getAlertStartedDate } = services; - const alertFactory: InventoryMetricThresholdAlertFactory = (id, reason) => + const alertFactory: InventoryMetricThresholdAlertFactory = (id, reason, additionalContext) => alertWithLifecycle({ id, fields: { [ALERT_REASON]: reason, [ALERT_RULE_PARAMETERS]: params as any, // the type assumes the object is already flattened when writing the same way as when reading https://github.com/elastic/kibana/blob/main/x-pack/plugins/rule_registry/common/field_map/runtime_type_from_fieldmap.ts#L60 + ...additionalContext, }, }); @@ -184,7 +186,9 @@ export const createInventoryMetricThresholdExecutor = (libs: InfraBackendLibs) = const actionGroupId = nextState === AlertStates.WARNING ? WARNING_ACTIONS.id : FIRED_ACTIONS.id; - const alert = alertFactory(group, reason); + const additionalContext = results && results.length > 0 ? results[0][group].context : null; + + const alert = alertFactory(group, reason, additionalContext); const indexedStartedDate = getAlertStartedDate(group) ?? startedAt.toISOString(); const viewInAppUrl = getViewInAppUrlInventory( criteria, @@ -193,6 +197,7 @@ export const createInventoryMetricThresholdExecutor = (libs: InfraBackendLibs) = libs.basePath ); scheduledActionsCount++; + const context = { group, alertState: stateToAlertMessage[nextState], @@ -204,6 +209,7 @@ export const createInventoryMetricThresholdExecutor = (libs: InfraBackendLibs) = ), threshold: mapToConditionsLookup(criteria, (c) => c.threshold), metric: mapToConditionsLookup(criteria, (c) => c.metric), + ...additionalContext, }; alert.scheduleActions(actionGroupId, context); } diff --git a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/lib/create_request.ts b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/lib/create_request.ts index 3253d48353ef7..b13638f6c2336 100644 --- a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/lib/create_request.ts +++ b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/lib/create_request.ts @@ -55,6 +55,18 @@ export const createRequest = ( const metricAggregations = createMetricAggregations(timerange, nodeType, metric, customMetric); const bucketSelector = createBucketSelector(metric, condition, customMetric); + const additionalContextAgg = { + additionalContext: { + top_hits: { + size: 1, + _source: { + includes: ['host.*', 'labels.*', 'tags', 'cloud.*', 'orchestrator.*', 'container.*'], + excludes: ['host.cpu.*', 'host.disk.*', 'host.network.*'], + }, + }, + }, + }; + const request: ESSearchRequest = { allow_no_indices: true, ignore_unavailable: true, @@ -65,7 +77,7 @@ export const createRequest = ( aggs: { nodes: { composite, - aggs: { ...metricAggregations, ...bucketSelector }, + aggs: { ...metricAggregations, ...bucketSelector, ...additionalContextAgg }, }, }, }, diff --git a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/lib/get_data.ts b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/lib/get_data.ts index 09ac4b47f2c9a..264e0b365fc9c 100644 --- a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/lib/get_data.ts +++ b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/lib/get_data.ts @@ -5,8 +5,10 @@ * 2.0. */ +import { AggregationsAggregate, SearchResponse } from '@elastic/elasticsearch/lib/api/types'; import { ElasticsearchClient } from '@kbn/core/server'; import type { Logger } from '@kbn/logging'; +import { EcsFieldsResponse } from '@kbn/rule-registry-plugin/common/search_strategy'; import { InventoryMetricConditions } from '../../../../../common/alerting/metrics'; import { InfraTimerangeInput, SnapshotCustomMetricInput } from '../../../../../common/http_api'; import { @@ -20,13 +22,28 @@ import { createRequest } from './create_request'; interface BucketKey { node: string; } -type Response = Record; + +interface AdditionalContext { + [x: string]: any; +} + +type Response = Record< + string, + { + value: number | null; + warn: boolean; + trigger: boolean; + } & AdditionalContext +>; + type Metric = Record; + interface Bucket { key: BucketKey; doc_count: number; shouldWarn: { value: number }; shouldTrigger: { value: number }; + additionalContext: SearchResponse>; } type NodeBucket = Bucket & Metric; interface ResponseAggregations { @@ -56,10 +73,15 @@ export const getData = async ( const nextAfterKey = nodes.after_key; for (const bucket of nodes.buckets) { const metricId = customMetric && customMetric.field ? customMetric.id : metric; + const bucketHits = bucket.additionalContext?.hits?.hits; + const additionalContextSource = + bucketHits && bucketHits.length > 0 ? bucketHits[0]._source : null; + previous[bucket.key.node] = { value: bucket?.[metricId]?.value ?? null, warn: bucket?.shouldWarn.value > 0 ?? false, trigger: bucket?.shouldTrigger.value > 0 ?? false, + ...additionalContextSource, }; } if (nextAfterKey) { diff --git a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/register_inventory_metric_threshold_rule_type.ts b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/register_inventory_metric_threshold_rule_type.ts index 873b54c156551..b3b1f5ba21c65 100644 --- a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/register_inventory_metric_threshold_rule_type.ts +++ b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/register_inventory_metric_threshold_rule_type.ts @@ -25,9 +25,15 @@ import { import { InfraBackendLibs } from '../../infra_types'; import { alertStateActionVariableDescription, + cloudActionVariableDescription, + containerActionVariableDescription, groupActionVariableDescription, + hostActionVariableDescription, + labelsActionVariableDescription, metricActionVariableDescription, + orchestratorActionVariableDescription, reasonActionVariableDescription, + tagsActionVariableDescription, thresholdActionVariableDescription, timestampActionVariableDescription, valueActionVariableDescription, @@ -102,6 +108,12 @@ export async function registerMetricInventoryThresholdRuleType( { name: 'metric', description: metricActionVariableDescription }, { name: 'threshold', description: thresholdActionVariableDescription }, { name: 'viewInAppUrl', description: viewInAppUrlActionVariableDescription }, + { name: 'cloud', description: cloudActionVariableDescription }, + { name: 'host', description: hostActionVariableDescription }, + { name: 'container', description: containerActionVariableDescription }, + { name: 'orchestrator', description: orchestratorActionVariableDescription }, + { name: 'labels', description: labelsActionVariableDescription }, + { name: 'tags', description: tagsActionVariableDescription }, ], }, }); diff --git a/x-pack/plugins/infra/server/lib/alerting/log_threshold/log_threshold_executor.test.ts b/x-pack/plugins/infra/server/lib/alerting/log_threshold/log_threshold_executor.test.ts index 78934d09755be..4e2e6b780dafb 100644 --- a/x-pack/plugins/infra/server/lib/alerting/log_threshold/log_threshold_executor.test.ts +++ b/x-pack/plugins/infra/server/lib/alerting/log_threshold/log_threshold_executor.test.ts @@ -14,6 +14,8 @@ import { getGroupedESQuery, processUngroupedResults, processGroupByResults, + LogThresholdAlertFactory, + LogThresholdAlertLimit, } from './log_threshold_executor'; import { Comparator, @@ -406,9 +408,14 @@ describe('Log threshold executor', () => { }); describe('Results processors', () => { - describe('Can process ungrouped results', () => { - test('It handles the ALERT state correctly', () => { - const alertFactoryMock = jest.fn(); + describe('for ungrouped results', () => { + it('handles the ALERT state correctly', () => { + const alertFactoryMock: jest.MockedFunction = jest.fn(); + const alertLimitMock: jest.Mocked = { + getValue: jest.fn().mockReturnValue(10), + setLimitReached: jest.fn(), + }; + const ruleParams = { ...baseRuleParams, criteria: [positiveCriteria[0]], @@ -421,7 +428,7 @@ describe('Log threshold executor', () => { }, } as UngroupedSearchQueryResponse; - processUngroupedResults(results, ruleParams, alertFactoryMock); + processUngroupedResults(results, ruleParams, alertFactoryMock, alertLimitMock); // first call, fifth argument expect(alertFactoryMock.mock.calls[0][4]).toEqual([ @@ -437,11 +444,91 @@ describe('Log threshold executor', () => { }, ]); }); + + it('reports reaching a low limit when alerting', () => { + const alertFactoryMock: jest.MockedFunction = jest.fn(); + const alertLimitMock: jest.Mocked = { + getValue: jest.fn().mockReturnValue(1), + setLimitReached: jest.fn(), + }; + + const ruleParams = { + ...baseRuleParams, + criteria: [positiveCriteria[0]], + }; + const results = { + hits: { + total: { + value: 10, + }, + }, + } as UngroupedSearchQueryResponse; + + processUngroupedResults(results, ruleParams, alertFactoryMock, alertLimitMock); + + expect(alertFactoryMock).toBeCalledTimes(1); + expect(alertLimitMock.setLimitReached).toHaveBeenCalledWith(true); + }); + + it('reports not reaching a higher limit when alerting', () => { + const alertFactoryMock: jest.MockedFunction = jest.fn(); + const alertLimitMock: jest.Mocked = { + getValue: jest.fn().mockReturnValue(10), + setLimitReached: jest.fn(), + }; + + const ruleParams = { + ...baseRuleParams, + criteria: [positiveCriteria[0]], + }; + const results = { + hits: { + total: { + value: 10, + }, + }, + } as UngroupedSearchQueryResponse; + + processUngroupedResults(results, ruleParams, alertFactoryMock, alertLimitMock); + + expect(alertFactoryMock).toBeCalledTimes(1); + expect(alertLimitMock.setLimitReached).toHaveBeenCalledWith(false); + }); + + it('reports not reaching the limit without any alerts', () => { + const alertFactoryMock: jest.MockedFunction = jest.fn(); + const alertLimitMock: jest.Mocked = { + getValue: jest.fn().mockReturnValue(0), + setLimitReached: jest.fn(), + }; + + const ruleParams = { + ...baseRuleParams, + criteria: [positiveCriteria[0]], + }; + const results = { + hits: { + total: { + value: 0, + }, + }, + } as UngroupedSearchQueryResponse; + + processUngroupedResults(results, ruleParams, alertFactoryMock, alertLimitMock); + + expect(alertFactoryMock).not.toHaveBeenCalled(); + expect(alertLimitMock.setLimitReached).toHaveBeenCalledWith(false); + }); }); - describe('Can process grouped results', () => { - test('It handles the ALERT state correctly', () => { - const alertFactoryMock = jest.fn(); + describe('for grouped results', () => { + it('handles the ALERT state correctly', () => { + const alertFactoryMock: jest.MockedFunction = jest.fn(); + const alertLimitMock: jest.Mocked = { + getValue: jest.fn().mockReturnValue(2), + setLimitReached: jest.fn(), + }; + const ruleParams = { ...baseRuleParams, criteria: [positiveCriteria[0]], @@ -481,7 +568,7 @@ describe('Log threshold executor', () => { }, ] as GroupedSearchQueryResponse['aggregations']['groups']['buckets']; - processGroupByResults(results, ruleParams, alertFactoryMock); + processGroupByResults(results, ruleParams, alertFactoryMock, alertLimitMock); expect(alertFactoryMock.mock.calls.length).toBe(2); // First call, fifth argument @@ -514,6 +601,110 @@ describe('Log threshold executor', () => { }, ]); }); + + it('respects and reports reaching a low limit when alerting', () => { + const alertFactoryMock: jest.MockedFunction = jest.fn(); + const alertLimitMock: jest.Mocked = { + getValue: jest.fn().mockReturnValue(1), + setLimitReached: jest.fn(), + }; + + const ruleParams = { + ...baseRuleParams, + criteria: [positiveCriteria[0]], + groupBy: ['host.name', 'event.dataset'], + }; + // Two groups should fire, one shouldn't + const results = [ + { + key: { + 'host.name': 'i-am-a-host-name-1', + 'event.dataset': 'i-am-a-dataset-1', + }, + doc_count: 100, + filtered_results: { + doc_count: 10, + }, + }, + { + key: { + 'host.name': 'i-am-a-host-name-2', + 'event.dataset': 'i-am-a-dataset-2', + }, + doc_count: 100, + filtered_results: { + doc_count: 2, + }, + }, + { + key: { + 'host.name': 'i-am-a-host-name-3', + 'event.dataset': 'i-am-a-dataset-3', + }, + doc_count: 100, + filtered_results: { + doc_count: 20, + }, + }, + ] as GroupedSearchQueryResponse['aggregations']['groups']['buckets']; + + processGroupByResults(results, ruleParams, alertFactoryMock, alertLimitMock); + + expect(alertFactoryMock).toHaveBeenCalledTimes(1); + expect(alertLimitMock.setLimitReached).toHaveBeenCalledWith(true); + }); + + it('reports not reaching a higher limit when alerting', () => { + const alertFactoryMock: jest.MockedFunction = jest.fn(); + const alertLimitMock: jest.Mocked = { + getValue: jest.fn().mockReturnValue(10), + setLimitReached: jest.fn(), + }; + + const ruleParams = { + ...baseRuleParams, + criteria: [positiveCriteria[0]], + groupBy: ['host.name', 'event.dataset'], + }; + // Two groups should fire, one shouldn't + const results = [ + { + key: { + 'host.name': 'i-am-a-host-name-1', + 'event.dataset': 'i-am-a-dataset-1', + }, + doc_count: 100, + filtered_results: { + doc_count: 10, + }, + }, + { + key: { + 'host.name': 'i-am-a-host-name-2', + 'event.dataset': 'i-am-a-dataset-2', + }, + doc_count: 100, + filtered_results: { + doc_count: 2, + }, + }, + { + key: { + 'host.name': 'i-am-a-host-name-3', + 'event.dataset': 'i-am-a-dataset-3', + }, + doc_count: 100, + filtered_results: { + doc_count: 20, + }, + }, + ] as GroupedSearchQueryResponse['aggregations']['groups']['buckets']; + + processGroupByResults(results, ruleParams, alertFactoryMock, alertLimitMock); + + expect(alertFactoryMock).toHaveBeenCalledTimes(2); + expect(alertLimitMock.setLimitReached).toHaveBeenCalledWith(false); + }); }); }); }); diff --git a/x-pack/plugins/infra/server/lib/alerting/log_threshold/log_threshold_executor.ts b/x-pack/plugins/infra/server/lib/alerting/log_threshold/log_threshold_executor.ts index dab15eb5ca923..a475e6beea011 100644 --- a/x-pack/plugins/infra/server/lib/alerting/log_threshold/log_threshold_executor.ts +++ b/x-pack/plugins/infra/server/lib/alerting/log_threshold/log_threshold_executor.ts @@ -19,6 +19,7 @@ import { Alert, AlertInstanceContext as AlertContext, AlertInstanceState as AlertState, + RuleExecutorServices, RuleTypeState, } from '@kbn/alerting-plugin/server'; @@ -60,18 +61,23 @@ export type LogThresholdRuleTypeState = RuleTypeState; // no specific state used export type LogThresholdAlertState = AlertState; // no specific state used export type LogThresholdAlertContext = AlertContext; // no specific instance context used -type LogThresholdAlert = Alert< +export type LogThresholdAlert = Alert< LogThresholdAlertState, LogThresholdAlertContext, LogThresholdActionGroups >; -type LogThresholdAlertFactory = ( +export type LogThresholdAlertFactory = ( id: string, reason: string, value: number, threshold: number, actions?: Array<{ actionGroup: LogThresholdActionGroups; context: AlertContext }> ) => LogThresholdAlert; +export type LogThresholdAlertLimit = RuleExecutorServices< + LogThresholdAlertState, + LogThresholdAlertContext, + LogThresholdActionGroups +>['alertFactory']['alertLimit']; const COMPOSITE_GROUP_SIZE = 2000; @@ -96,8 +102,13 @@ export const createLogThresholdExecutor = (libs: InfraBackendLibs) => LogThresholdAlertContext, LogThresholdActionGroups >(async ({ services, params, startedAt }) => { - const { alertWithLifecycle, savedObjectsClient, scopedClusterClient, getAlertStartedDate } = - services; + const { + alertFactory: { alertLimit }, + alertWithLifecycle, + savedObjectsClient, + scopedClusterClient, + getAlertStartedDate, + } = services; const { basePath } = libs; const alertFactory: LogThresholdAlertFactory = (id, reason, value, threshold, actions) => { @@ -150,6 +161,7 @@ export const createLogThresholdExecutor = (libs: InfraBackendLibs) => runtimeMappings, scopedClusterClient.asCurrentUser, alertFactory, + alertLimit, startedAt.valueOf() ); } else { @@ -160,6 +172,7 @@ export const createLogThresholdExecutor = (libs: InfraBackendLibs) => runtimeMappings, scopedClusterClient.asCurrentUser, alertFactory, + alertLimit, startedAt.valueOf() ); } @@ -185,6 +198,7 @@ export async function executeAlert( runtimeMappings: estypes.MappingRuntimeFields, esClient: ElasticsearchClient, alertFactory: LogThresholdAlertFactory, + alertLimit: LogThresholdAlertLimit, executionTimestamp: number ) { const query = getESQuery( @@ -200,9 +214,19 @@ export async function executeAlert( } if (hasGroupBy(ruleParams)) { - processGroupByResults(await getGroupedResults(query, esClient), ruleParams, alertFactory); + processGroupByResults( + await getGroupedResults(query, esClient), + ruleParams, + alertFactory, + alertLimit + ); } else { - processUngroupedResults(await getUngroupedResults(query, esClient), ruleParams, alertFactory); + processUngroupedResults( + await getUngroupedResults(query, esClient), + ruleParams, + alertFactory, + alertLimit + ); } } @@ -213,6 +237,7 @@ export async function executeRatioAlert( runtimeMappings: estypes.MappingRuntimeFields, esClient: ElasticsearchClient, alertFactory: LogThresholdAlertFactory, + alertLimit: LogThresholdAlertLimit, executionTimestamp: number ) { // Ratio alert params are separated out into two standard sets of alert params @@ -254,7 +279,8 @@ export async function executeRatioAlert( numeratorGroupedResults, denominatorGroupedResults, ruleParams, - alertFactory + alertFactory, + alertLimit ); } else { const [numeratorUngroupedResults, denominatorUngroupedResults] = await Promise.all([ @@ -265,7 +291,8 @@ export async function executeRatioAlert( numeratorUngroupedResults, denominatorUngroupedResults, ruleParams, - alertFactory + alertFactory, + alertLimit ); } } @@ -297,7 +324,8 @@ const getESQuery = ( export const processUngroupedResults = ( results: UngroupedSearchQueryResponse, params: CountRuleParams, - alertFactory: LogThresholdAlertFactory + alertFactory: LogThresholdAlertFactory, + alertLimit: LogThresholdAlertLimit ) => { const { count, criteria, timeSize, timeUnit } = params; const documentCount = results.hits.total.value; @@ -323,6 +351,9 @@ export const processUngroupedResults = ( }, ]; alertFactory(UNGROUPED_FACTORY_KEY, reasonMessage, documentCount, count.value, actions); + alertLimit.setLimitReached(alertLimit.getValue() <= 1); + } else { + alertLimit.setLimitReached(false); } }; @@ -330,7 +361,8 @@ export const processUngroupedRatioResults = ( numeratorResults: UngroupedSearchQueryResponse, denominatorResults: UngroupedSearchQueryResponse, params: RatioRuleParams, - alertFactory: LogThresholdAlertFactory + alertFactory: LogThresholdAlertFactory, + alertLimit: LogThresholdAlertLimit ) => { const { count, criteria, timeSize, timeUnit } = params; @@ -360,6 +392,9 @@ export const processUngroupedRatioResults = ( }, ]; alertFactory(UNGROUPED_FACTORY_KEY, reasonMessage, ratio, count.value, actions); + alertLimit.setLimitReached(alertLimit.getValue() <= 1); + } else { + alertLimit.setLimitReached(false); } }; @@ -405,16 +440,24 @@ const getReducedGroupByResults = ( export const processGroupByResults = ( results: GroupedSearchQueryResponse['aggregations']['groups']['buckets'], params: CountRuleParams, - alertFactory: LogThresholdAlertFactory + alertFactory: LogThresholdAlertFactory, + alertLimit: LogThresholdAlertLimit ) => { const { count, criteria, timeSize, timeUnit } = params; const groupResults = getReducedGroupByResults(results); - groupResults.forEach((group) => { + let remainingAlertCount = alertLimit.getValue(); + + for (const group of groupResults) { + if (remainingAlertCount <= 0) { + break; + } + const documentCount = group.documentCount; if (checkValueAgainstComparatorMap[count.comparator](documentCount, count.value)) { + remainingAlertCount -= 1; const reasonMessage = getReasonMessageForGroupedCountAlert( documentCount, count.value, @@ -437,21 +480,30 @@ export const processGroupByResults = ( ]; alertFactory(group.name, reasonMessage, documentCount, count.value, actions); } - }); + } + + alertLimit.setLimitReached(remainingAlertCount <= 0); }; export const processGroupByRatioResults = ( numeratorResults: GroupedSearchQueryResponse['aggregations']['groups']['buckets'], denominatorResults: GroupedSearchQueryResponse['aggregations']['groups']['buckets'], params: RatioRuleParams, - alertFactory: LogThresholdAlertFactory + alertFactory: LogThresholdAlertFactory, + alertLimit: LogThresholdAlertLimit ) => { const { count, criteria, timeSize, timeUnit } = params; const numeratorGroupResults = getReducedGroupByResults(numeratorResults); const denominatorGroupResults = getReducedGroupByResults(denominatorResults); - numeratorGroupResults.forEach((numeratorGroup) => { + let remainingAlertCount = alertLimit.getValue(); + + for (const numeratorGroup of numeratorGroupResults) { + if (remainingAlertCount <= 0) { + break; + } + const numeratorDocumentCount = numeratorGroup.documentCount; const denominatorGroup = denominatorGroupResults.find( (_group) => _group.name === numeratorGroup.name @@ -464,6 +516,7 @@ export const processGroupByRatioResults = ( ratio !== undefined && checkValueAgainstComparatorMap[count.comparator](ratio, count.value) ) { + remainingAlertCount -= 1; const reasonMessage = getReasonMessageForGroupedRatioAlert( ratio, count.value, @@ -487,7 +540,9 @@ export const processGroupByRatioResults = ( ]; alertFactory(numeratorGroup.name, reasonMessage, ratio, count.value, actions); } - }); + } + + alertLimit.setLimitReached(remainingAlertCount <= 0); }; export const buildFiltersFromCriteria = ( diff --git a/x-pack/plugins/infra/server/services/rules/rule_data_client.ts b/x-pack/plugins/infra/server/services/rules/rule_data_client.ts index 4fcbaf2084362..1435f4812d16c 100644 --- a/x-pack/plugins/infra/server/services/rules/rule_data_client.ts +++ b/x-pack/plugins/infra/server/services/rules/rule_data_client.ts @@ -10,6 +10,7 @@ import { mappingFromFieldMap } from '@kbn/rule-registry-plugin/common/mapping_fr import { experimentalRuleFieldMap } from '@kbn/rule-registry-plugin/common/assets/field_maps/experimental_rule_field_map'; import { Dataset, RuleRegistryPluginSetupContract } from '@kbn/rule-registry-plugin/server'; +import { ECS_COMPONENT_TEMPLATE_NAME } from '@kbn/rule-registry-plugin/common/assets'; import type { InfraFeatureId } from '../../../common/constants'; import { RuleRegistrationContext, RulesServiceStartDeps } from './types'; @@ -30,7 +31,7 @@ export const createRuleDataClient = ({ feature: ownerFeatureId, registrationContext, dataset: Dataset.alerts, - componentTemplateRefs: [], + componentTemplateRefs: [ECS_COMPONENT_TEMPLATE_NAME], componentTemplates: [ { name: 'mappings', diff --git a/x-pack/plugins/kubernetes_security/common/constants.ts b/x-pack/plugins/kubernetes_security/common/constants.ts index 04c273290eca7..3de3ec6be69e3 100644 --- a/x-pack/plugins/kubernetes_security/common/constants.ts +++ b/x-pack/plugins/kubernetes_security/common/constants.ts @@ -43,6 +43,8 @@ export const COUNT_WIDGET_KEY_PODS = 'CountPodsWidgets'; export const COUNT_WIDGET_KEY_CONTAINER_IMAGES = 'CountContainerImagesWidgets'; export const DEFAULT_QUERY = '{"bool":{"must":[],"filter":[],"should":[],"must_not":[]}}'; +export const DEFAULT_KUBERNETES_FILTER_QUERY = + '{"bool":{"must":[],"filter":[{"bool": {"should": [{"exists": {"field": "orchestrator.cluster.id"}}]}}],"should":[],"must_not":[]}}'; export const DEFAULT_FILTER_QUERY = '{"bool":{"must":[],"filter":[{"bool": {"should": [{"exists": {"field": "process.entry_leader.entity_id"}}]}}],"should":[],"must_not":[]}}'; export const DEFAULT_FILTER = { diff --git a/x-pack/plugins/kubernetes_security/public/components/kubernetes_security_routes/index.tsx b/x-pack/plugins/kubernetes_security/public/components/kubernetes_security_routes/index.tsx index 85fe011bef998..629d200eae348 100644 --- a/x-pack/plugins/kubernetes_security/public/components/kubernetes_security_routes/index.tsx +++ b/x-pack/plugins/kubernetes_security/public/components/kubernetes_security_routes/index.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React, { useCallback } from 'react'; +import React, { useCallback, useMemo } from 'react'; import { Route, Switch } from 'react-router-dom'; import useLocalStorage from 'react-use/lib/useLocalStorage'; import { @@ -35,10 +35,11 @@ import { COUNT_WIDGET_KEY_NAMESPACE, COUNT_WIDGET_KEY_NODES, COUNT_WIDGET_KEY_CONTAINER_IMAGES, + DEFAULT_KUBERNETES_FILTER_QUERY, } from '../../../common/constants'; import { PercentWidget } from '../percent_widget'; import { CountWidget } from '../count_widget'; -import { KubernetesSecurityDeps } from '../../types'; +import { GlobalFilter, KubernetesSecurityDeps } from '../../types'; import { AggregateResult } from '../../../common/types/aggregate'; import { useLastUpdated } from '../../hooks'; import { useStyles } from './styles'; @@ -67,6 +68,16 @@ const KubernetesSecurityRoutesComponent = ({ const styles = useStyles(); const lastUpdated = useLastUpdated(globalFilter); + const globalFilterForKubernetes: GlobalFilter = useMemo(() => { + return { + ...globalFilter, + filterQuery: JSON.stringify({ + ...JSON.parse(globalFilter?.filterQuery ?? ''), + ...JSON.parse(DEFAULT_KUBERNETES_FILTER_QUERY), + }), + }; + }, [globalFilter]); + const onReduceInteractiveAggs = useCallback( (result: AggregateResult): Record => result.buckets.reduce((groupedByKeyValue, aggregate) => { @@ -125,7 +136,7 @@ const KubernetesSecurityRoutesComponent = ({ @@ -134,7 +145,7 @@ const KubernetesSecurityRoutesComponent = ({ @@ -143,7 +154,7 @@ const KubernetesSecurityRoutesComponent = ({ @@ -152,7 +163,7 @@ const KubernetesSecurityRoutesComponent = ({ @@ -161,7 +172,7 @@ const KubernetesSecurityRoutesComponent = ({ @@ -191,7 +202,7 @@ const KubernetesSecurityRoutesComponent = ({ } widgetKey="sessionsPercentage" indexPattern={indexPattern} - globalFilter={globalFilter} + globalFilter={globalFilterForKubernetes} dataValueMap={{ true: { name: i18n.translate( @@ -244,7 +255,7 @@ const KubernetesSecurityRoutesComponent = ({ } widgetKey="rootLoginPercentage" indexPattern={indexPattern} - globalFilter={globalFilter} + globalFilter={globalFilterForKubernetes} dataValueMap={{ '0': { name: i18n.translate('xpack.kubernetesSecurity.entryUserChart.root', { @@ -273,7 +284,7 @@ const KubernetesSecurityRoutesComponent = ({ @@ -282,7 +293,7 @@ const KubernetesSecurityRoutesComponent = ({ )} 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 4176e5f1e51a7..f2b4d2b315148 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 @@ -644,7 +644,7 @@ export const LensTopNavMenu = ({ setIsOnTextBasedMode(true); dispatch( switchAndCleanDatasource({ - newDatasourceId: 'textBasedLanguages', + newDatasourceId: 'textBased', visualizationId: visualization?.activeId, currentIndexPatternId: currentIndexPattern?.id, }) @@ -764,7 +764,7 @@ export const LensTopNavMenu = ({ if (isOnTextBasedMode) { dispatch( switchAndCleanDatasource({ - newDatasourceId: 'indexpattern', + newDatasourceId: 'formBased', visualizationId: visualization?.activeId, currentIndexPatternId: dataView?.id, }) @@ -795,7 +795,7 @@ export const LensTopNavMenu = ({ if (isOnTextBasedMode) { dispatch( switchAndCleanDatasource({ - newDatasourceId: 'indexpattern', + newDatasourceId: 'formBased', visualizationId: visualization?.activeId, currentIndexPatternId: dataView?.id, }) @@ -838,7 +838,7 @@ export const LensTopNavMenu = ({ if (isOnTextBasedMode) { dispatch( switchAndCleanDatasource({ - newDatasourceId: 'indexpattern', + newDatasourceId: 'formBased', visualizationId: visualization?.activeId, currentIndexPatternId: newIndexPatternId, }) diff --git a/x-pack/plugins/lens/public/app_plugin/show_underlying_data.test.ts b/x-pack/plugins/lens/public/app_plugin/show_underlying_data.test.ts index bd6b7a000ecd6..b185697021105 100644 --- a/x-pack/plugins/lens/public/app_plugin/show_underlying_data.test.ts +++ b/x-pack/plugins/lens/public/app_plugin/show_underlying_data.test.ts @@ -93,7 +93,7 @@ describe('getLayerMetaInfo', () => { it('should return error in case of getFilters returning errors', () => { const mockDatasource = createMockDatasource('testDatasource'); const updatedPublicAPI: DatasourcePublicAPI = { - datasourceId: 'indexpattern', + datasourceId: 'formBased', getOperationForColumnId: jest.fn(), getTableSpec: jest.fn(() => [{ columnId: 'col1', fields: ['bytes'] }]), getVisualDefaults: jest.fn(), @@ -166,7 +166,7 @@ describe('getLayerMetaInfo', () => { it('should basically work collecting fields and filters in the visualization', () => { const mockDatasource = createMockDatasource('testDatasource'); const updatedPublicAPI: DatasourcePublicAPI = { - datasourceId: 'indexpattern', + datasourceId: 'formBased', getOperationForColumnId: jest.fn(), getTableSpec: jest.fn(() => [{ columnId: 'col1', fields: ['bytes'] }]), getVisualDefaults: jest.fn(), diff --git a/x-pack/plugins/lens/public/async_services.ts b/x-pack/plugins/lens/public/async_services.ts index c0ccd2a71ce2b..fa6ba8e6c87c1 100644 --- a/x-pack/plugins/lens/public/async_services.ts +++ b/x-pack/plugins/lens/public/async_services.ts @@ -29,12 +29,12 @@ export * from './visualizations/heatmap'; export * from './visualizations/gauge/gauge_visualization'; export * from './visualizations/gauge'; -export * from './indexpattern_datasource/indexpattern'; -export { getTextBasedLanguagesDatasource } from './text_based_languages_datasource/text_based_languages'; -export { createFormulaPublicApi } from './indexpattern_datasource/operations/definitions/formula/formula_public_api'; +export * from './datasources/form_based/form_based'; +export { getTextBasedDatasource } from './datasources/text_based/text_based_languages'; +export { createFormulaPublicApi } from './datasources/form_based/operations/definitions/formula/formula_public_api'; -export * from './text_based_languages_datasource'; -export * from './indexpattern_datasource'; +export * from './datasources/text_based'; +export * from './datasources/form_based'; export * from './lens_ui_telemetry'; export * from './lens_ui_errors'; export * from './editor_frame_service/editor_frame'; @@ -43,3 +43,5 @@ export * from './embeddable'; export * from './app_plugin/mounter'; export * from './lens_attribute_service'; export * from './app_plugin/save_modal_container'; + +export * from './trigger_actions/open_in_discover_helpers'; diff --git a/x-pack/plugins/lens/public/data_views_service/loader.test.ts b/x-pack/plugins/lens/public/data_views_service/loader.test.ts index 340bc675bf3e7..97ded75233cda 100644 --- a/x-pack/plugins/lens/public/data_views_service/loader.test.ts +++ b/x-pack/plugins/lens/public/data_views_service/loader.test.ts @@ -14,7 +14,7 @@ import { syncExistingFields, } from './loader'; import { sampleIndexPatterns, mockDataViewsService } from './mocks'; -import { documentField } from '../indexpattern_datasource/document_field'; +import { documentField } from '../datasources/form_based/document_field'; import { coreMock } from '@kbn/core/public/mocks'; import { dataViewPluginMocks } from '@kbn/data-views-plugin/public/mocks'; import type { DataView } from '@kbn/data-views-plugin/public'; diff --git a/x-pack/plugins/lens/public/data_views_service/loader.ts b/x-pack/plugins/lens/public/data_views_service/loader.ts index 3bb1bdf0612a7..f0184d0a11d0b 100644 --- a/x-pack/plugins/lens/public/data_views_service/loader.ts +++ b/x-pack/plugins/lens/public/data_views_service/loader.ts @@ -12,7 +12,7 @@ import { CoreStart } from '@kbn/core/public'; import { DataPublicPluginStart } from '@kbn/data-plugin/public'; import { loadFieldExisting } from '@kbn/unified-field-list-plugin/public'; import { IndexPattern, IndexPatternField, IndexPatternMap, IndexPatternRef } from '../types'; -import { documentField } from '../indexpattern_datasource/document_field'; +import { documentField } from '../datasources/form_based/document_field'; import { DateRange } from '../../common'; import { DataViewsState } from '../state_management'; diff --git a/x-pack/plugins/lens/public/data_views_service/mocks.ts b/x-pack/plugins/lens/public/data_views_service/mocks.ts index 9b7f5cbc2a91a..ed8d6e86e58a4 100644 --- a/x-pack/plugins/lens/public/data_views_service/mocks.ts +++ b/x-pack/plugins/lens/public/data_views_service/mocks.ts @@ -6,11 +6,11 @@ */ import { DataViewsContract } from '@kbn/data-views-plugin/common'; -import { documentField } from '../indexpattern_datasource/document_field'; +import { documentField } from '../datasources/form_based/document_field'; import { createMockedIndexPattern, createMockedRestrictedIndexPattern, -} from '../indexpattern_datasource/mocks'; +} from '../datasources/form_based/mocks'; import { DataViewsState } from '../state_management'; import { ExistingFieldsMap, IndexPattern } from '../types'; import { getFieldByNameFactory } from './loader'; diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/__mocks__/loader.ts b/x-pack/plugins/lens/public/datasources/form_based/__mocks__/loader.ts similarity index 91% rename from x-pack/plugins/lens/public/indexpattern_datasource/__mocks__/loader.ts rename to x-pack/plugins/lens/public/datasources/form_based/__mocks__/loader.ts index 1273d596576c4..47af8d816b73f 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/__mocks__/loader.ts +++ b/x-pack/plugins/lens/public/datasources/form_based/__mocks__/loader.ts @@ -6,11 +6,11 @@ */ import { createMockedIndexPattern, createMockedRestrictedIndexPattern } from '../mocks'; -import { IndexPatternPrivateState } from '../types'; +import { FormBasedPrivateState } from '../types'; export function loadInitialState() { const indexPattern = createMockedIndexPattern(); - const result: IndexPatternPrivateState = { + const result: FormBasedPrivateState = { currentIndexPatternId: indexPattern.id, layers: {}, }; diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/__snapshots__/utils.test.tsx.snap b/x-pack/plugins/lens/public/datasources/form_based/__snapshots__/utils.test.tsx.snap similarity index 100% rename from x-pack/plugins/lens/public/indexpattern_datasource/__snapshots__/utils.test.tsx.snap rename to x-pack/plugins/lens/public/datasources/form_based/__snapshots__/utils.test.tsx.snap diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.scss b/x-pack/plugins/lens/public/datasources/form_based/datapanel.scss similarity index 100% rename from x-pack/plugins/lens/public/indexpattern_datasource/datapanel.scss rename to x-pack/plugins/lens/public/datasources/form_based/datapanel.scss diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.test.tsx b/x-pack/plugins/lens/public/datasources/form_based/datapanel.test.tsx similarity index 90% rename from x-pack/plugins/lens/public/indexpattern_datasource/datapanel.test.tsx rename to x-pack/plugins/lens/public/datasources/form_based/datapanel.test.tsx index 7ee461aa63369..e7b0cd6d457a9 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.test.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/datapanel.test.tsx @@ -13,13 +13,13 @@ import { dataViewPluginMocks, Start as DataViewPublicStart, } from '@kbn/data-views-plugin/public/mocks'; -import { InnerIndexPatternDataPanel, IndexPatternDataPanel, Props } from './datapanel'; +import { InnerFormBasedDataPanel, FormBasedDataPanel, Props } from './datapanel'; import { FieldList } from './field_list'; import { FieldItem } from './field_item'; import { NoFieldsCallout } from './no_fields_callout'; import { act } from 'react-dom/test-utils'; import { coreMock } from '@kbn/core/public/mocks'; -import { IndexPatternPrivateState } from './types'; +import { FormBasedPrivateState } from './types'; import { mountWithIntl, shallowWithIntl } from '@kbn/test-jest-helpers'; import { EuiProgress, EuiLoadingSpinner } from '@elastic/eui'; import { documentField } from './document_field'; @@ -29,12 +29,12 @@ import { indexPatternFieldEditorPluginMock } from '@kbn/data-view-field-editor-p import { getFieldByNameFactory } from './pure_helpers'; import { uiActionsPluginMock } from '@kbn/ui-actions-plugin/public/mocks'; import { TermsIndexPatternColumn } from './operations'; -import { DOCUMENT_FIELD_NAME } from '../../common'; -import { createIndexPatternServiceMock } from '../mocks/data_views_service_mock'; -import { createMockFramePublicAPI } from '../mocks'; -import { DataViewsState } from '../state_management'; -import { ExistingFieldsMap, FramePublicAPI, IndexPattern } from '../types'; -import { IndexPatternServiceProps } from '../data_views_service/service'; +import { DOCUMENT_FIELD_NAME } from '../../../common'; +import { createIndexPatternServiceMock } from '../../mocks/data_views_service_mock'; +import { createMockFramePublicAPI } from '../../mocks'; +import { DataViewsState } from '../../state_management'; +import { ExistingFieldsMap, FramePublicAPI, IndexPattern } from '../../types'; +import { IndexPatternServiceProps } from '../../data_views_service/service'; import { FieldSpec, DataView } from '@kbn/data-views-plugin/public'; import { UI_SETTINGS } from '@kbn/data-plugin/public'; @@ -174,7 +174,7 @@ function getExistingFields(indexPatterns: Record) { return existingFields; } -const initialState: IndexPatternPrivateState = { +const initialState: FormBasedPrivateState = { currentIndexPatternId: '1', layers: { first: { @@ -285,7 +285,7 @@ const dslQuery = { bool: { must: [], filter: [], should: [], must_not: [] } }; // @ts-expect-error Portal mocks are notoriously difficult to type ReactDOM.createPortal = jest.fn((element) => element); -describe('IndexPattern Data Panel', () => { +describe('FormBased Data Panel', () => { const indexPatterns = { a: { id: 'a', @@ -304,7 +304,7 @@ describe('IndexPattern Data Panel', () => { hasRestrictions: false, }, }; - let defaultProps: Parameters[0] & { + let defaultProps: Parameters[0] & { showNoDataPopover: () => void; }; let core: ReturnType; @@ -340,7 +340,7 @@ describe('IndexPattern Data Panel', () => { it('should render a warning if there are no index patterns', () => { const wrapper = shallowWithIntl( - { columns: {}, }, }, - } as IndexPatternPrivateState, + } as FormBasedPrivateState, }; } async function testExistenceLoading( props: Props, - stateChanges?: Partial, + stateChanges?: Partial, propChanges?: Partial ) { - const inst = mountWithIntl(); + const inst = mountWithIntl(); await act(async () => { inst.update(); @@ -601,7 +601,7 @@ describe('IndexPattern Data Panel', () => { it('shows a loading indicator when loading', async () => { const updateIndexPatterns = jest.fn(); const load = async () => {}; - const inst = mountWithIntl(); + const inst = mountWithIntl(); expect(inst.find(EuiProgress).length).toEqual(1); await act(load); inst.update(); @@ -629,7 +629,7 @@ describe('IndexPattern Data Panel', () => { return result; }); - const inst = mountWithIntl(); + const inst = mountWithIntl(); inst.update(); @@ -676,7 +676,7 @@ describe('IndexPattern Data Panel', () => { }); describe('displaying field list', () => { - let props: Parameters[0]; + let props: Parameters[0]; beforeEach(() => { props = { ...defaultProps, @@ -690,8 +690,33 @@ describe('IndexPattern Data Panel', () => { }), }; }); + + it('should list all selected fields if exist', async () => { + const newProps = { + ...props, + layerFields: ['bytes'], + }; + const wrapper = mountWithIntl(); + expect( + wrapper + .find('[data-test-subj="lnsIndexPatternSelectedFields"]') + .find(FieldItem) + .map((fieldItem) => fieldItem.prop('field').name) + ).toEqual(['bytes']); + }); + + it('should not list the selected fields accordion if no fields given', async () => { + const wrapper = mountWithIntl(); + expect( + wrapper + .find('[data-test-subj="lnsIndexPatternSelectedFields"]') + .find(FieldItem) + .map((fieldItem) => fieldItem.prop('field').name) + ).toEqual([]); + }); + it('should list all supported fields in the pattern sorted alphabetically in groups', async () => { - const wrapper = mountWithIntl(); + const wrapper = mountWithIntl(); expect(wrapper.find(FieldItem).first().prop('field').displayName).toEqual('Records'); expect( wrapper @@ -715,7 +740,7 @@ describe('IndexPattern Data Panel', () => { it('should show meta fields accordion', async () => { const wrapper = mountWithIntl( - { it('should display NoFieldsCallout when all fields are empty', async () => { const wrapper = mountWithIntl( - @@ -780,7 +805,7 @@ describe('IndexPattern Data Panel', () => { it('should display spinner for available fields accordion if existing fields are not loaded yet', async () => { const wrapper = mountWithIntl( - @@ -795,7 +820,7 @@ describe('IndexPattern Data Panel', () => { it('should not allow field details when error', () => { const wrapper = mountWithIntl( - @@ -810,7 +835,7 @@ describe('IndexPattern Data Panel', () => { it('should allow field details when timeout', () => { const wrapper = mountWithIntl( - @@ -824,7 +849,7 @@ describe('IndexPattern Data Panel', () => { }); it('should filter down by name', () => { - const wrapper = mountWithIntl(); + const wrapper = mountWithIntl(); act(() => { wrapper.find('[data-test-subj="lnsIndexPatternFieldSearch"]').simulate('change', { target: { value: 'me' }, @@ -843,7 +868,7 @@ describe('IndexPattern Data Panel', () => { }); it('should announce filter in live region', () => { - const wrapper = mountWithIntl(); + const wrapper = mountWithIntl(); act(() => { wrapper.find('[data-test-subj="lnsIndexPatternFieldSearch"]').simulate('change', { target: { value: 'me' }, @@ -862,7 +887,7 @@ describe('IndexPattern Data Panel', () => { }); it('should filter down by type', () => { - const wrapper = mountWithIntl(); + const wrapper = mountWithIntl(); wrapper.find('[data-test-subj="lnsIndexPatternFiltersToggle"]').first().simulate('click'); @@ -874,7 +899,7 @@ describe('IndexPattern Data Panel', () => { }); it('should display no fields in groups when filtered by type Record', () => { - const wrapper = mountWithIntl(); + const wrapper = mountWithIntl(); wrapper.find('[data-test-subj="lnsIndexPatternFiltersToggle"]').first().simulate('click'); @@ -887,7 +912,7 @@ describe('IndexPattern Data Panel', () => { }); it('should toggle type if clicked again', () => { - const wrapper = mountWithIntl(); + const wrapper = mountWithIntl(); wrapper.find('[data-test-subj="lnsIndexPatternFiltersToggle"]').first().simulate('click'); wrapper.find('[data-test-subj="typeFilter-number"]').first().simulate('click'); @@ -903,7 +928,7 @@ describe('IndexPattern Data Panel', () => { }); it('should filter down by type and by name', () => { - const wrapper = mountWithIntl(); + const wrapper = mountWithIntl(); act(() => { wrapper.find('[data-test-subj="lnsIndexPatternFieldSearch"]').simulate('change', { target: { value: 'me' }, diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.tsx b/x-pack/plugins/lens/public/datasources/form_based/datapanel.tsx similarity index 95% rename from x-pack/plugins/lens/public/indexpattern_datasource/datapanel.tsx rename to x-pack/plugins/lens/public/datasources/form_based/datapanel.tsx index 4107cd0c14fa5..8a7916a01a09a 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/datapanel.tsx @@ -39,18 +39,18 @@ import type { FramePublicAPI, IndexPattern, IndexPatternField, -} from '../types'; -import { ChildDragDropProvider, DragContextState } from '../drag_drop'; -import type { IndexPatternPrivateState } from './types'; -import { Loader } from '../loader'; -import { LensFieldIcon } from '../shared_components/field_picker/lens_field_icon'; +} from '../../types'; +import { ChildDragDropProvider, DragContextState } from '../../drag_drop'; +import type { FormBasedPrivateState } from './types'; +import { Loader } from '../../loader'; +import { LensFieldIcon } from '../../shared_components/field_picker/lens_field_icon'; import { getFieldType } from './pure_utils'; import { FieldGroups, FieldList } from './field_list'; -import { fieldContainsData, fieldExists } from '../shared_components'; -import { IndexPatternServiceAPI } from '../data_views_service/service'; +import { fieldContainsData, fieldExists } from '../../shared_components'; +import { IndexPatternServiceAPI } from '../../data_views_service/service'; export type Props = Omit< - DatasourceDataPanelProps, + DatasourceDataPanelProps, 'core' | 'onChangeIndexPattern' > & { data: DataPublicPluginStart; @@ -62,6 +62,7 @@ export type Props = Omit< frame: FramePublicAPI; indexPatternService: IndexPatternServiceAPI; onIndexPatternRefresh: () => void; + layerFields?: string[]; }; function sortFields(fieldA: IndexPatternField, fieldB: IndexPatternField) { @@ -124,7 +125,7 @@ function buildSafeEsQuery( } } -export function IndexPatternDataPanel({ +export function FormBasedDataPanel({ state, dragDropContext, core, @@ -144,6 +145,7 @@ export function IndexPatternDataPanel({ frame, onIndexPatternRefresh, usedIndexPatterns, + layerFields, }: Props) { const { indexPatterns, indexPatternRefs, existingFields, isFirstExistenceFetch } = frame.dataViews; @@ -234,6 +236,7 @@ export function IndexPatternDataPanel({ indexPatternService={indexPatternService} onIndexPatternRefresh={onIndexPatternRefresh} frame={frame} + layerFields={layerFields} /> )} @@ -264,7 +267,7 @@ const defaultFieldGroups: { const htmlId = htmlIdGenerator('datapanel'); const fieldSearchDescriptionId = htmlId(); -export const InnerIndexPatternDataPanel = function InnerIndexPatternDataPanel({ +export const InnerFormBasedDataPanel = function InnerFormBasedDataPanel({ currentIndexPatternId, query, dateRange, @@ -282,6 +285,7 @@ export const InnerIndexPatternDataPanel = function InnerIndexPatternDataPanel({ indexPatternService, frame, onIndexPatternRefresh, + layerFields, }: Omit< DatasourceDataPanelProps, 'state' | 'setState' | 'showNoDataPopover' | 'core' | 'onChangeIndexPattern' | 'usedIndexPatterns' @@ -296,6 +300,7 @@ export const InnerIndexPatternDataPanel = function InnerIndexPatternDataPanel({ frame: FramePublicAPI; indexPatternFieldEditor: IndexPatternFieldEditorStart; onIndexPatternRefresh: () => void; + layerFields?: string[]; }) { const [localState, setLocalState] = useState({ nameFilter: '', @@ -345,6 +350,7 @@ export const InnerIndexPatternDataPanel = function InnerIndexPatternDataPanel({ const allSupportedTypesFields = allFields.filter((field) => supportedFieldTypes.has(field.type) ); + const usedByLayersFields = allFields.filter((field) => layerFields?.includes(field.name)); const sorted = allSupportedTypesFields.sort(sortFields); const groupedFields = { ...defaultFieldGroups, @@ -372,6 +378,19 @@ export const InnerIndexPatternDataPanel = function InnerIndexPatternDataPanel({ title: '', hideDetails: true, }, + SelectedFields: { + fields: usedByLayersFields, + fieldCount: usedByLayersFields.length, + isInitiallyOpen: true, + showInAccordion: true, + title: i18n.translate('xpack.lens.indexPattern.selectedFieldsLabel', { + defaultMessage: 'Selected fields', + }), + isAffectedByGlobalFilter: !!filters.length, + isAffectedByTimeFilter: true, + hideDetails: false, + hideIfEmpty: true, + }, AvailableFields: { fields: groupedFields.availableFields, fieldCount: groupedFields.availableFields.length, @@ -451,6 +470,7 @@ export const InnerIndexPatternDataPanel = function InnerIndexPatternDataPanel({ existenceFetchTimeout, currentIndexPattern, existingFieldsForIndexPattern, + layerFields, ]); const fieldGroups: FieldGroups = useMemo(() => { @@ -751,4 +771,4 @@ export const InnerIndexPatternDataPanel = function InnerIndexPatternDataPanel({ ); }; -export const MemoizedDataPanel = memo(InnerIndexPatternDataPanel); +export const MemoizedDataPanel = memo(InnerFormBasedDataPanel); diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dedupe_aggs.test.ts b/x-pack/plugins/lens/public/datasources/form_based/dedupe_aggs.test.ts similarity index 100% rename from x-pack/plugins/lens/public/indexpattern_datasource/dedupe_aggs.test.ts rename to x-pack/plugins/lens/public/datasources/form_based/dedupe_aggs.test.ts diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dedupe_aggs.ts b/x-pack/plugins/lens/public/datasources/form_based/dedupe_aggs.ts similarity index 100% rename from x-pack/plugins/lens/public/indexpattern_datasource/dedupe_aggs.ts rename to x-pack/plugins/lens/public/datasources/form_based/dedupe_aggs.ts diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/advanced_options.tsx b/x-pack/plugins/lens/public/datasources/form_based/dimension_panel/advanced_options.tsx similarity index 100% rename from x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/advanced_options.tsx rename to x-pack/plugins/lens/public/datasources/form_based/dimension_panel/advanced_options.tsx diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/bucket_nesting_editor.test.tsx b/x-pack/plugins/lens/public/datasources/form_based/dimension_panel/bucket_nesting_editor.test.tsx similarity index 98% rename from x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/bucket_nesting_editor.test.tsx rename to x-pack/plugins/lens/public/datasources/form_based/dimension_panel/bucket_nesting_editor.test.tsx index 248cc0f78756e..6c09849df04ac 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/bucket_nesting_editor.test.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/dimension_panel/bucket_nesting_editor.test.tsx @@ -8,8 +8,8 @@ import { mount } from 'enzyme'; import React from 'react'; import { BucketNestingEditor } from './bucket_nesting_editor'; -import { GenericIndexPatternColumn } from '../indexpattern'; -import { IndexPatternField } from '../../types'; +import { GenericIndexPatternColumn } from '../form_based'; +import { IndexPatternField } from '../../../types'; const fieldMap: Record = { a: { displayName: 'a' } as IndexPatternField, diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/bucket_nesting_editor.tsx b/x-pack/plugins/lens/public/datasources/form_based/dimension_panel/bucket_nesting_editor.tsx similarity index 96% rename from x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/bucket_nesting_editor.tsx rename to x-pack/plugins/lens/public/datasources/form_based/dimension_panel/bucket_nesting_editor.tsx index 31a4b91706dfa..fb062e4231467 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/bucket_nesting_editor.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/dimension_panel/bucket_nesting_editor.tsx @@ -8,10 +8,10 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; import { EuiFormRow, EuiSwitch, EuiSelect } from '@elastic/eui'; -import { IndexPatternLayer } from '../types'; +import { FormBasedLayer } from '../types'; import { hasField } from '../pure_utils'; import { GenericIndexPatternColumn } from '../operations'; -import { IndexPatternField } from '../../types'; +import { IndexPatternField } from '../../../types'; function nestColumn(columnOrder: string[], outer: string, inner: string) { const result = columnOrder.filter((c) => c !== inner); @@ -38,7 +38,7 @@ export function BucketNestingEditor({ getFieldByName, }: { columnId: string; - layer: IndexPatternLayer; + layer: FormBasedLayer; setColumns: (columns: string[]) => void; getFieldByName: (name: string) => IndexPatternField | undefined; }) { diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_editor.scss b/x-pack/plugins/lens/public/datasources/form_based/dimension_panel/dimension_editor.scss similarity index 100% rename from x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_editor.scss rename to x-pack/plugins/lens/public/datasources/form_based/dimension_panel/dimension_editor.scss diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_editor.tsx b/x-pack/plugins/lens/public/datasources/form_based/dimension_panel/dimension_editor.tsx similarity index 97% rename from x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_editor.tsx rename to x-pack/plugins/lens/public/datasources/form_based/dimension_panel/dimension_editor.tsx index b4cad9aa73697..330d3285b2951 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_editor.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/dimension_panel/dimension_editor.tsx @@ -27,9 +27,9 @@ import { EuiButtonIcon, } from '@elastic/eui'; import ReactDOM from 'react-dom'; -import type { IndexPatternDimensionEditorProps } from './dimension_panel'; +import type { FormBasedDimensionEditorProps } from './dimension_panel'; import type { OperationSupportMatrix } from './operation_support'; -import { deleteColumn, GenericIndexPatternColumn } from '../indexpattern'; +import { deleteColumn, GenericIndexPatternColumn } from '../form_based'; import { operationDefinitionMap, getOperationDisplay, @@ -46,7 +46,7 @@ import { mergeLayer } from '../state_helpers'; import { getReferencedField, hasField } from '../pure_utils'; import { fieldIsInvalid } from '../utils'; import { BucketNestingEditor } from './bucket_nesting_editor'; -import type { IndexPatternLayer } from '../types'; +import type { FormBasedLayer } from '../types'; import { FormatSelector } from './format_selector'; import { ReferenceEditor } from './reference_editor'; import { TimeScaling } from './time_scaling'; @@ -54,8 +54,8 @@ import { Filtering } from './filtering'; import { ReducedTimeRange } from './reduced_time_range'; import { AdvancedOptions } from './advanced_options'; import { TimeShift } from './time_shift'; -import type { LayerType } from '../../../common'; -import { DOCUMENT_FIELD_NAME } from '../../../common'; +import type { LayerType } from '../../../../common'; +import { DOCUMENT_FIELD_NAME } from '../../../../common'; import { quickFunctionsName, staticValueOperationName, @@ -68,15 +68,15 @@ import { } from './dimensions_editor_helpers'; import type { TemporaryState } from './dimensions_editor_helpers'; import { FieldInput } from './field_input'; -import { NameInput } from '../../shared_components'; +import { NameInput } from '../../../shared_components'; import { ParamEditorProps } from '../operations/definitions'; import { WrappingHelpPopover } from '../help_popover'; import { isColumn } from '../operations/definitions/helpers'; import type { FieldChoiceWithOperationType } from './field_select'; -import type { IndexPattern, IndexPatternField } from '../../types'; +import type { IndexPattern, IndexPatternField } from '../../../types'; import { documentField } from '../document_field'; -export interface DimensionEditorProps extends IndexPatternDimensionEditorProps { +export interface DimensionEditorProps extends FormBasedDimensionEditorProps { selectedColumn?: GenericIndexPatternColumn; layerType: LayerType; operationSupportMatrix: OperationSupportMatrix; @@ -142,13 +142,13 @@ export function DimensionEditor(props: DimensionEditorProps) { const setStateWrapper = useCallback( ( setter: - | IndexPatternLayer - | ((prevLayer: IndexPatternLayer) => IndexPatternLayer) + | FormBasedLayer + | ((prevLayer: FormBasedLayer) => FormBasedLayer) | GenericIndexPatternColumn, options: { forceRender?: boolean } = {} ) => { const layer = state.layers[layerId]; - let hypotethicalLayer: IndexPatternLayer; + let hypotethicalLayer: FormBasedLayer; if (isColumn(setter)) { hypotethicalLayer = { ...layer, @@ -164,7 +164,7 @@ export function DimensionEditor(props: DimensionEditorProps) { setState( (prevState) => { - let outputLayer: IndexPatternLayer; + let outputLayer: FormBasedLayer; const prevLayer = prevState.layers[layerId]; if (isColumn(setter)) { outputLayer = { @@ -250,8 +250,8 @@ export function DimensionEditor(props: DimensionEditorProps) { // TODO: revisit this once we get rid of updateDatasourceAsync upstream const moveDefinetelyToStaticValueAndUpdate = ( setter: - | IndexPatternLayer - | ((prevLayer: IndexPatternLayer) => IndexPatternLayer) + | FormBasedLayer + | ((prevLayer: FormBasedLayer) => FormBasedLayer) | GenericIndexPatternColumn ) => { if (temporaryStaticValue) { @@ -501,7 +501,7 @@ export function DimensionEditor(props: DimensionEditorProps) { } else if (!selectedColumn || !compatibleWithCurrentField) { const possibleFields = fieldByOperation[operationType] || new Set(); - let newLayer: IndexPatternLayer; + let newLayer: FormBasedLayer; if (possibleFields.size === 1) { newLayer = insertOrReplaceColumn({ layer: props.state.layers[props.layerId], @@ -585,9 +585,7 @@ export function DimensionEditor(props: DimensionEditorProps) { const paramEditorProps: ParamEditorProps< GenericIndexPatternColumn, - | IndexPatternLayer - | ((prevLayer: IndexPatternLayer) => IndexPatternLayer) - | GenericIndexPatternColumn + FormBasedLayer | ((prevLayer: FormBasedLayer) => FormBasedLayer) | GenericIndexPatternColumn > = { layer: state.layers[layerId], layerId, @@ -769,11 +767,11 @@ export function DimensionEditor(props: DimensionEditorProps) { }} paramEditorUpdater={( setter: - | IndexPatternLayer - | ((prevLayer: IndexPatternLayer) => IndexPatternLayer) + | FormBasedLayer + | ((prevLayer: FormBasedLayer) => FormBasedLayer) | GenericIndexPatternColumn ) => { - let newLayer: IndexPatternLayer; + let newLayer: FormBasedLayer; if (typeof setter === 'function') { newLayer = setter(layer); } else if (isColumn(setter)) { diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.test.tsx b/x-pack/plugins/lens/public/datasources/form_based/dimension_panel/dimension_panel.test.tsx similarity index 89% rename from x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.test.tsx rename to x-pack/plugins/lens/public/datasources/form_based/dimension_panel/dimension_panel.test.tsx index 41dd1df5bcd92..456b1537db97c 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.test.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/dimension_panel/dimension_panel.test.tsx @@ -21,8 +21,8 @@ import { dataViewPluginMocks } from '@kbn/data-views-plugin/public/mocks'; import { DataPublicPluginStart } from '@kbn/data-plugin/public'; import { fieldFormatsServiceMock } from '@kbn/field-formats-plugin/public/mocks'; import { - IndexPatternDimensionEditorComponent, - IndexPatternDimensionEditorProps, + FormBasedDimensionEditorComponent, + FormBasedDimensionEditorProps, } from './dimension_panel'; import { mountWithIntl as mount, shallowWithIntl as shallow } from '@kbn/test-jest-helpers'; import { @@ -32,9 +32,9 @@ import { CoreStart, } from '@kbn/core/public'; import { IStorageWrapper } from '@kbn/kibana-utils-plugin/public'; +import { generateId } from '../../../id_generator'; +import { FormBasedPrivateState } from '../types'; import { LayerTypes } from '@kbn/expression-xy-plugin/public'; -import { generateId } from '../../id_generator'; -import { IndexPatternPrivateState } from '../types'; import { FiltersIndexPatternColumn, GenericIndexPatternColumn, @@ -42,7 +42,7 @@ import { TermsIndexPatternColumn, } from '../operations'; import { documentField } from '../document_field'; -import { OperationMetadata } from '../../types'; +import { OperationMetadata } from '../../../types'; import { DateHistogramIndexPatternColumn } from '../operations/definitions/date_histogram'; import { getFieldByNameFactory } from '../pure_helpers'; import { Filtering, setFilter } from './filtering'; @@ -69,7 +69,7 @@ jest.mock('lodash', () => { debounce: (fn: unknown) => fn, }; }); -jest.mock('../../id_generator'); +jest.mock('../../../id_generator'); // Mock the Monaco Editor component jest.mock('../operations/definitions/formula/editor/formula_editor', () => { return { @@ -148,10 +148,10 @@ const bytesColumn: GenericIndexPatternColumn = { * - Dimension trigger: Not tested here * - Dimension editor component: First half of the tests */ -describe('IndexPatternDimensionEditorPanel', () => { - let state: IndexPatternPrivateState; +describe('FormBasedDimensionEditor', () => { + let state: FormBasedPrivateState; let setState: jest.Mock; - let defaultProps: IndexPatternDimensionEditorProps; + let defaultProps: FormBasedDimensionEditorProps; function getStateWithColumns(columns: Record) { return { @@ -265,14 +265,14 @@ describe('IndexPatternDimensionEditorPanel', () => { const filterOperations = jest.fn().mockReturnValue(true); wrapper = shallow( - + ); expect(filterOperations).toBeCalled(); }); it('should show field select', () => { - wrapper = mount(); + wrapper = mount(); expect( wrapper.find(EuiComboBox).filter('[data-test-subj="indexPattern-dimension-field"]') @@ -281,7 +281,7 @@ describe('IndexPatternDimensionEditorPanel', () => { it('should not show field select on fieldless operation', () => { wrapper = mount( - { it('should not show any choices if the filter returns false', () => { wrapper = mount( - false} @@ -320,7 +320,7 @@ describe('IndexPatternDimensionEditorPanel', () => { }); it('should list all field names and document as a whole in prioritized order', () => { - wrapper = mount(); + wrapper = mount(); const options = wrapper .find(EuiComboBox) @@ -348,7 +348,7 @@ describe('IndexPatternDimensionEditorPanel', () => { }, }, }; - wrapper = mount(); + wrapper = mount(); const options = wrapper .find(EuiComboBox) @@ -360,7 +360,7 @@ describe('IndexPatternDimensionEditorPanel', () => { it('should indicate fields which are incompatible for the operation of the current column', () => { wrapper = mount( - @@ -383,7 +383,7 @@ describe('IndexPatternDimensionEditorPanel', () => { it('should indicate operations which are incompatible for the field of the current column', () => { wrapper = mount( - @@ -407,7 +407,7 @@ describe('IndexPatternDimensionEditorPanel', () => { it('should indicate when a transition is invalid due to filterOperations', () => { wrapper = mount( - { }); it('should not display hidden operation types', () => { - wrapper = mount(); + wrapper = mount(); const items: EuiListGroupItemProps[] = wrapper.find(EuiListGroup).prop('listItems') || []; @@ -442,7 +442,7 @@ describe('IndexPatternDimensionEditorPanel', () => { it('should indicate that reference-based operations are not compatible when they are incomplete', () => { wrapper = mount( - { it('should indicate that reference-based operations are compatible sometimes', () => { wrapper = mount( - { }); it('should keep the operation when switching to another field compatible with this operation', () => { - const initialState: IndexPatternPrivateState = getStateWithColumns({ col1: bytesColumn }); + const initialState: FormBasedPrivateState = getStateWithColumns({ col1: bytesColumn }); - wrapper = mount( - - ); + wrapper = mount(); const comboBox = wrapper .find(EuiComboBox) @@ -562,7 +560,7 @@ describe('IndexPatternDimensionEditorPanel', () => { }); it('should switch operations when selecting a field that requires another operation', () => { - wrapper = mount(); + wrapper = mount(); const comboBox = wrapper .find(EuiComboBox) @@ -597,7 +595,7 @@ describe('IndexPatternDimensionEditorPanel', () => { it('should keep the field when switching to another operation compatible for this field', () => { wrapper = mount( - @@ -628,7 +626,7 @@ describe('IndexPatternDimensionEditorPanel', () => { }); it('should not set the state if selecting the currently active operation', () => { - wrapper = mount(); + wrapper = mount(); act(() => { wrapper @@ -640,7 +638,7 @@ describe('IndexPatternDimensionEditorPanel', () => { }); it('should update label and custom label flag on label input changes', () => { - wrapper = mount(); + wrapper = mount(); act(() => { wrapper @@ -669,7 +667,7 @@ describe('IndexPatternDimensionEditorPanel', () => { it('should not keep the label as long as it is the default label', () => { wrapper = mount( - @@ -698,7 +696,7 @@ describe('IndexPatternDimensionEditorPanel', () => { it('should keep the label on operation change if it is custom', () => { wrapper = mount( - { it('should remove customLabel flag if label is set to default', () => { wrapper = mount( - { describe('transient invalid state', () => { it('should set the state if selecting an operation incompatible with the current field', () => { - wrapper = mount(); + wrapper = mount(); act(() => { wrapper @@ -799,7 +797,7 @@ describe('IndexPatternDimensionEditorPanel', () => { }); it('should show error message in invalid state', () => { - wrapper = mount(); + wrapper = mount(); wrapper .find('button[data-test-subj="lns-indexPatternDimension-terms incompatible"]') @@ -811,7 +809,7 @@ describe('IndexPatternDimensionEditorPanel', () => { }); it('should leave error state if a compatible operation is selected', () => { - wrapper = mount(); + wrapper = mount(); wrapper .find('button[data-test-subj="lns-indexPatternDimension-terms incompatible"]') @@ -825,7 +823,7 @@ describe('IndexPatternDimensionEditorPanel', () => { }); it('should leave error state if the original operation is re-selected', () => { - wrapper = mount(); + wrapper = mount(); wrapper .find('button[data-test-subj="lns-indexPatternDimension-terms incompatible"]') @@ -841,7 +839,7 @@ describe('IndexPatternDimensionEditorPanel', () => { it('should leave error state when switching from incomplete state to fieldless operation', () => { // @ts-expect-error window['__react-beautiful-dnd-disable-dev-warnings'] = true; // issue with enzyme & react-beautiful-dnd throwing errors: https://github.com/atlassian/react-beautiful-dnd/issues/1593 - wrapper = mount(); + wrapper = mount(); wrapper .find('button[data-test-subj="lns-indexPatternDimension-terms incompatible"]') @@ -854,7 +852,7 @@ describe('IndexPatternDimensionEditorPanel', () => { it('should leave error state when re-selecting the original fieldless function', () => { wrapper = mount( - { }); it('should indicate fields compatible with selected operation', () => { - wrapper = mount(); + wrapper = mount(); wrapper .find('button[data-test-subj="lns-indexPatternDimension-terms incompatible"]') @@ -901,7 +899,7 @@ describe('IndexPatternDimensionEditorPanel', () => { }); it('should select compatible operation if field not compatible with selected operation', () => { - wrapper = mount(); + wrapper = mount(); wrapper.find('button[data-test-subj="lns-indexPatternDimension-average"]').simulate('click'); @@ -962,11 +960,7 @@ describe('IndexPatternDimensionEditorPanel', () => { }, }); wrapper = mount( - + ); // Transition to a field operation (incompatible) @@ -991,7 +985,7 @@ describe('IndexPatternDimensionEditorPanel', () => { it('should select the Records field when count is selected on non-existing column', () => { wrapper = mount( - { it('should indicate document and field compatibility with selected document operation', () => { wrapper = mount( - { }); it('should set datasource state if compatible field is selected for operation', () => { - wrapper = mount(); + wrapper = mount(); wrapper .find('button[data-test-subj="lns-indexPatternDimension-terms incompatible"]') @@ -1110,7 +1104,7 @@ describe('IndexPatternDimensionEditorPanel', () => { } it('should default to None if time scaling is not set', () => { - wrapper = mount(); + wrapper = mount(); findTestSubject(wrapper, 'indexPattern-advanced-accordion').simulate('click'); expect(wrapper.find('[data-test-subj="indexPattern-time-scaling-enable"]')).toHaveLength(1); expect( @@ -1122,7 +1116,7 @@ describe('IndexPatternDimensionEditorPanel', () => { }); it('should show current time scaling if set', () => { - wrapper = mount(); + wrapper = mount(); findTestSubject(wrapper, 'indexPattern-advanced-accordion').simulate('click'); expect( wrapper @@ -1134,7 +1128,7 @@ describe('IndexPatternDimensionEditorPanel', () => { it('should allow to set time scaling initially', () => { const props = getProps({}); - wrapper = mount(); + wrapper = mount(); findTestSubject(wrapper, 'indexPattern-advanced-accordion').simulate('click'); wrapper .find('[data-test-subj="indexPattern-time-scaling-unit"]') @@ -1167,7 +1161,7 @@ describe('IndexPatternDimensionEditorPanel', () => { operationType: 'sum', label: 'Sum of bytes per hour', }); - wrapper = mount(); + wrapper = mount(); wrapper.find('button[data-test-subj="lns-indexPatternDimension-count"]').simulate('click'); expect(setState.mock.calls[0]).toEqual([expect.any(Function), { isDimensionComplete: true }]); expect(setState.mock.calls[0][0](props.state)).toEqual({ @@ -1194,7 +1188,7 @@ describe('IndexPatternDimensionEditorPanel', () => { operationType: 'sum', label: 'Sum of bytes per hour', }); - wrapper = mount(); + wrapper = mount(); wrapper.find('button[data-test-subj="lns-indexPatternDimension-average"]').simulate('click'); expect(setState.mock.calls[0]).toEqual([expect.any(Function), { isDimensionComplete: true }]); expect(setState.mock.calls[0][0](props.state)).toEqual({ @@ -1216,7 +1210,7 @@ describe('IndexPatternDimensionEditorPanel', () => { it('should allow to change time scaling', () => { const props = getProps({ timeScale: 's', label: 'Count of records per second' }); - wrapper = mount(); + wrapper = mount(); findTestSubject(wrapper, 'indexPattern-advanced-accordion').simulate('click'); wrapper.find('[data-test-subj="indexPattern-time-scaling-unit"] select').simulate('change', { @@ -1243,7 +1237,7 @@ describe('IndexPatternDimensionEditorPanel', () => { it('should not adjust label if it is custom', () => { const props = getProps({ timeScale: 's', customLabel: true, label: 'My label' }); - wrapper = mount(); + wrapper = mount(); wrapper.find('[data-test-subj="indexPattern-time-scaling-unit"] select').simulate('change', { target: { value: 'h' }, }); @@ -1309,7 +1303,7 @@ describe('IndexPatternDimensionEditorPanel', () => { }), columnId: 'col2', }; - wrapper = mount(); + wrapper = mount(); findTestSubject(wrapper, 'indexPattern-advanced-accordion').simulate('click'); expect( wrapper.find('[data-test-subj="indexPattern-dimension-reducedTimeRange-row"]') @@ -1318,7 +1312,7 @@ describe('IndexPatternDimensionEditorPanel', () => { it('should show current reduced time range if set', () => { wrapper = mount( - + ); expect( wrapper.find(ReducedTimeRange).find(EuiComboBox).prop('selectedOptions')[0].value @@ -1327,7 +1321,7 @@ describe('IndexPatternDimensionEditorPanel', () => { it('should allow to set reduced time range initially', () => { const props = getProps({}); - wrapper = mount(); + wrapper = mount(); findTestSubject(wrapper, 'indexPattern-advanced-accordion').simulate('click'); wrapper.find(ReducedTimeRange).find(EuiComboBox).prop('onChange')!([ { value: '1h', label: '' }, @@ -1355,7 +1349,7 @@ describe('IndexPatternDimensionEditorPanel', () => { operationType: 'sum', label: 'Sum of bytes per hour', }); - wrapper = mount(); + wrapper = mount(); wrapper.find('button[data-test-subj="lns-indexPatternDimension-count"]').simulate('click'); expect((props.setState as jest.Mock).mock.calls[0][0](props.state)).toEqual({ ...props.state, @@ -1377,7 +1371,7 @@ describe('IndexPatternDimensionEditorPanel', () => { const props = getProps({ timeShift: '1d', }); - wrapper = mount(); + wrapper = mount(); wrapper.find(ReducedTimeRange).find(EuiComboBox).prop('onCreateOption')!('7m', []); expect((props.setState as jest.Mock).mock.calls[0][0](props.state)).toEqual({ ...props.state, @@ -1399,7 +1393,7 @@ describe('IndexPatternDimensionEditorPanel', () => { const props = getProps({ reducedTimeRange: '5 months', }); - wrapper = mount(); + wrapper = mount(); expect(wrapper.find(ReducedTimeRange).find(EuiComboBox).prop('isInvalid')).toBeTruthy(); @@ -1457,7 +1451,7 @@ describe('IndexPatternDimensionEditorPanel', () => { columnId: 'col2', }; wrapper = mount( - { }); it('should show custom options if time shift is available', () => { - wrapper = shallow(); + wrapper = shallow(); expect( wrapper .find(DimensionEditor) @@ -1485,7 +1479,7 @@ describe('IndexPatternDimensionEditorPanel', () => { }); it('should show current time shift if set', () => { - wrapper = mount(); + wrapper = mount(); expect(wrapper.find(TimeShift).find(EuiComboBox).prop('selectedOptions')[0].value).toEqual( '1d' ); @@ -1493,7 +1487,7 @@ describe('IndexPatternDimensionEditorPanel', () => { it('should allow to set time shift initially', () => { const props = getProps({}); - wrapper = mount(); + wrapper = mount(); findTestSubject(wrapper, 'indexPattern-advanced-accordion').simulate('click'); wrapper.find(TimeShift).find(EuiComboBox).prop('onChange')!([{ value: '1h', label: '' }]); expect((props.setState as jest.Mock).mock.calls[0][0](props.state)).toEqual({ @@ -1519,7 +1513,7 @@ describe('IndexPatternDimensionEditorPanel', () => { operationType: 'sum', label: 'Sum of bytes per hour', }); - wrapper = mount(); + wrapper = mount(); wrapper.find('button[data-test-subj="lns-indexPatternDimension-count"]').simulate('click'); expect((props.setState as jest.Mock).mock.calls[0][0](props.state)).toEqual({ ...props.state, @@ -1541,7 +1535,7 @@ describe('IndexPatternDimensionEditorPanel', () => { const props = getProps({ timeShift: '1d', }); - wrapper = mount(); + wrapper = mount(); wrapper.find(TimeShift).find(EuiComboBox).prop('onCreateOption')!('1h', []); expect((props.setState as jest.Mock).mock.calls[0][0](props.state)).toEqual({ ...props.state, @@ -1563,7 +1557,7 @@ describe('IndexPatternDimensionEditorPanel', () => { const props = getProps({ timeShift: '5 months', }); - wrapper = mount(); + wrapper = mount(); expect(wrapper.find(TimeShift).find(EuiComboBox).prop('isInvalid')).toBeTruthy(); @@ -1608,7 +1602,7 @@ describe('IndexPatternDimensionEditorPanel', () => { it('should not show custom options if time scaling is not available', () => { wrapper = mount( - { }); it('should show custom options if filtering is available', () => { - wrapper = mount(); + wrapper = mount(); findTestSubject(wrapper, 'indexPattern-advanced-accordion').simulate('click'); expect( wrapper.find('[data-test-subj="indexPattern-filter-by-enable"]').hostNodes() @@ -1635,7 +1629,7 @@ describe('IndexPatternDimensionEditorPanel', () => { it('should show current filter if set', () => { wrapper = mount( - ); @@ -1655,7 +1649,7 @@ describe('IndexPatternDimensionEditorPanel', () => { operationType: 'sum', label: 'Sum of bytes per hour', }); - wrapper = mount(); + wrapper = mount(); wrapper.find('button[data-test-subj="lns-indexPatternDimension-count"]').simulate('click'); expect(setState.mock.calls[0]).toEqual([expect.any(Function), { isDimensionComplete: true }]); expect(setState.mock.calls[0][0](props.state)).toEqual({ @@ -1679,7 +1673,7 @@ describe('IndexPatternDimensionEditorPanel', () => { filter: { language: 'kuery', query: 'a: b' }, }); - wrapper = mount(); + wrapper = mount(); act(() => { const { updateLayer, columnId, layer } = wrapper.find(Filtering).props(); @@ -1707,7 +1701,7 @@ describe('IndexPatternDimensionEditorPanel', () => { it('should render invalid field if field reference is broken', () => { wrapper = mount( - { }); it('should support selecting the operation before the field', () => { - wrapper = mount(); + wrapper = mount(); wrapper.find('button[data-test-subj="lns-indexPatternDimension-average"]').simulate('click'); @@ -1784,7 +1778,7 @@ describe('IndexPatternDimensionEditorPanel', () => { it('should select operation directly if only one field is possible', () => { wrapper = mount( - { }); it('should select operation directly if only document is possible', () => { - wrapper = mount(); + wrapper = mount(); wrapper.find('button[data-test-subj="lns-indexPatternDimension-count"]').simulate('click'); @@ -1845,7 +1839,7 @@ describe('IndexPatternDimensionEditorPanel', () => { }); it('should indicate compatible fields when selecting the operation first', () => { - wrapper = mount(); + wrapper = mount(); act(() => { wrapper.find('button[data-test-subj="lns-indexPatternDimension-average"]').simulate('click'); @@ -1871,7 +1865,7 @@ describe('IndexPatternDimensionEditorPanel', () => { it('should indicate document compatibility when document operation is selected', () => { wrapper = mount( - { }); it('should not update when selecting the current field again', () => { - wrapper = mount(); + wrapper = mount(); const comboBox = wrapper .find(EuiComboBox) @@ -1914,7 +1908,7 @@ describe('IndexPatternDimensionEditorPanel', () => { it('should show all operations that are not filtered out', () => { wrapper = mount( - !op.isBucketed && op.dataType === 'number'} /> @@ -1946,7 +1940,7 @@ describe('IndexPatternDimensionEditorPanel', () => { // Prevents field format from being loaded setState.mockImplementation(() => {}); - wrapper = mount(); + wrapper = mount(); const comboBox = wrapper .find(EuiComboBox) @@ -1981,12 +1975,10 @@ describe('IndexPatternDimensionEditorPanel', () => { }); it('should use helper function when changing the function', () => { - const initialState: IndexPatternPrivateState = getStateWithColumns({ + const initialState: FormBasedPrivateState = getStateWithColumns({ col1: bytesColumn, }); - wrapper = mount( - - ); + wrapper = mount(); act(() => { wrapper .find('button[data-test-subj="lns-indexPatternDimension-min"]') @@ -2004,7 +1996,7 @@ describe('IndexPatternDimensionEditorPanel', () => { }); it('should keep the latest valid dimension when removing the selection in field combobox', () => { - wrapper = mount(); + wrapper = mount(); act(() => { wrapper @@ -2017,7 +2009,7 @@ describe('IndexPatternDimensionEditorPanel', () => { }); it('allows custom format', () => { - const stateWithNumberCol: IndexPatternPrivateState = getStateWithColumns({ + const stateWithNumberCol: FormBasedPrivateState = getStateWithColumns({ col1: { label: 'Average of memory', dataType: 'number', @@ -2029,7 +2021,7 @@ describe('IndexPatternDimensionEditorPanel', () => { }); wrapper = mount( - + ); act(() => { @@ -2059,7 +2051,7 @@ describe('IndexPatternDimensionEditorPanel', () => { }); it('keeps decimal places while switching', () => { - const stateWithNumberCol: IndexPatternPrivateState = getStateWithColumns({ + const stateWithNumberCol: FormBasedPrivateState = getStateWithColumns({ col1: { label: 'Average of memory', dataType: 'number', @@ -2073,7 +2065,7 @@ describe('IndexPatternDimensionEditorPanel', () => { }, }); wrapper = mount( - + ); act(() => { @@ -2099,7 +2091,7 @@ describe('IndexPatternDimensionEditorPanel', () => { }); it('allows custom format with number of decimal places', () => { - const stateWithNumberCol: IndexPatternPrivateState = getStateWithColumns({ + const stateWithNumberCol: FormBasedPrivateState = getStateWithColumns({ col1: { label: 'Average of memory', dataType: 'number', @@ -2114,7 +2106,7 @@ describe('IndexPatternDimensionEditorPanel', () => { }); wrapper = mount( - + ); act(() => { @@ -2145,7 +2137,7 @@ describe('IndexPatternDimensionEditorPanel', () => { it('should hide the top level field selector when switching from non-reference to reference', () => { (generateId as jest.Mock).mockReturnValue(`second`); - wrapper = mount(); + wrapper = mount(); expect(wrapper.find('ReferenceEditor')).toHaveLength(0); @@ -2157,7 +2149,7 @@ describe('IndexPatternDimensionEditorPanel', () => { }); it('should hide the reference editors when switching from reference to non-reference', () => { - const stateWithReferences: IndexPatternPrivateState = getStateWithColumns({ + const stateWithReferences: FormBasedPrivateState = getStateWithColumns({ col1: { label: 'Differences of (incomplete)', dataType: 'number', @@ -2169,7 +2161,7 @@ describe('IndexPatternDimensionEditorPanel', () => { }); wrapper = mount( - + ); expect(wrapper.find('ReferenceEditor')).toHaveLength(1); @@ -2182,7 +2174,7 @@ describe('IndexPatternDimensionEditorPanel', () => { }); it('should show a warning when the current dimension is no longer configurable', () => { - const stateWithInvalidCol: IndexPatternPrivateState = getStateWithColumns({ + const stateWithInvalidCol: FormBasedPrivateState = getStateWithColumns({ col1: { label: 'Invalid differences', dataType: 'number', @@ -2193,7 +2185,7 @@ describe('IndexPatternDimensionEditorPanel', () => { }); wrapper = mount( - + ); expect( @@ -2205,7 +2197,7 @@ describe('IndexPatternDimensionEditorPanel', () => { }); it('should remove options to select references when there are no time fields', () => { - const stateWithoutTime: IndexPatternPrivateState = { + const stateWithoutTime: FormBasedPrivateState = { ...getStateWithColumns({ col1: { label: 'Avg', @@ -2218,7 +2210,7 @@ describe('IndexPatternDimensionEditorPanel', () => { }; wrapper = mount( - { }); it('should not show tabs when formula and static_value operations are not available', () => { - const stateWithInvalidCol: IndexPatternPrivateState = getStateWithColumns({ + const stateWithInvalidCol: FormBasedPrivateState = getStateWithColumns({ col1: { label: 'Average of memory', dataType: 'number', @@ -2279,15 +2271,13 @@ describe('IndexPatternDimensionEditorPanel', () => { }), }; - wrapper = mount( - - ); + wrapper = mount(); expect(wrapper.find('[data-test-subj="lens-dimensionTabs"]').exists()).toBeFalsy(); }); it('should show the formula tab when supported', () => { - const stateWithFormulaColumn: IndexPatternPrivateState = getStateWithColumns({ + const stateWithFormulaColumn: FormBasedPrivateState = getStateWithColumns({ col1: { label: 'Formula', dataType: 'number', @@ -2299,7 +2289,7 @@ describe('IndexPatternDimensionEditorPanel', () => { }); wrapper = mount( - + ); expect( @@ -2308,7 +2298,7 @@ describe('IndexPatternDimensionEditorPanel', () => { }); it('should not show the static_value tab when not supported', () => { - const stateWithFormulaColumn: IndexPatternPrivateState = getStateWithColumns({ + const stateWithFormulaColumn: FormBasedPrivateState = getStateWithColumns({ col1: { label: 'Formula', dataType: 'number', @@ -2320,14 +2310,14 @@ describe('IndexPatternDimensionEditorPanel', () => { }); wrapper = mount( - + ); expect(wrapper.find('[data-test-subj="lens-dimensionTabs-static_value"]').exists()).toBeFalsy(); }); it('should show the static value tab when supported', () => { - const staticWithFormulaColumn: IndexPatternPrivateState = getStateWithColumns({ + const staticWithFormulaColumn: FormBasedPrivateState = getStateWithColumns({ col1: { label: 'Formula', dataType: 'number', @@ -2339,7 +2329,7 @@ describe('IndexPatternDimensionEditorPanel', () => { }); wrapper = mount( - { }); it('should select the quick function tab by default', () => { - const stateWithNoColumn: IndexPatternPrivateState = getStateWithColumns({}); + const stateWithNoColumn: FormBasedPrivateState = getStateWithColumns({}); wrapper = mount( - + ); expect( @@ -2367,10 +2357,10 @@ describe('IndexPatternDimensionEditorPanel', () => { }); it('should select the static value tab when supported by default', () => { - const stateWithNoColumn: IndexPatternPrivateState = getStateWithColumns({}); + const stateWithNoColumn: FormBasedPrivateState = getStateWithColumns({}); wrapper = mount( - { }); it('should not show any tab when formula is in full screen mode', () => { - const stateWithFormulaColumn: IndexPatternPrivateState = getStateWithColumns({ + const stateWithFormulaColumn: FormBasedPrivateState = getStateWithColumns({ col1: { label: 'Formula', dataType: 'number', @@ -2395,7 +2385,7 @@ describe('IndexPatternDimensionEditorPanel', () => { }); wrapper = mount( - & { +export type FormBasedDimensionTriggerProps = + DatasourceDimensionTriggerProps & { uniqueLabel: string; }; -export type IndexPatternDimensionEditorProps = - DatasourceDimensionEditorProps & { +export type FormBasedDimensionEditorProps = + DatasourceDimensionEditorProps & { uiSettings: IUiSettingsClient; storage: IStorageWrapper; savedObjectsClient: SavedObjectsClientContract; @@ -49,8 +49,8 @@ function wrapOnDot(str?: string) { return str ? str.replace(/\./g, '.\u200B') : ''; } -export const IndexPatternDimensionTriggerComponent = function IndexPatternDimensionTrigger( - props: IndexPatternDimensionTriggerProps +export const FormBasedDimensionTriggerComponent = function FormBasedDimensionTrigger( + props: FormBasedDimensionTriggerProps ) { const layerId = props.layerId; const layer = props.state.layers[layerId]; @@ -80,8 +80,8 @@ export const IndexPatternDimensionTriggerComponent = function IndexPatternDimens ); }; -export const IndexPatternDimensionEditorComponent = function IndexPatternDimensionPanel( - props: IndexPatternDimensionEditorProps +export const FormBasedDimensionEditorComponent = function FormBasedDimensionPanel( + props: FormBasedDimensionEditorProps ) { const layerId = props.layerId; const currentIndexPattern = props.indexPatterns[props.state.layers[layerId]?.indexPatternId]; @@ -103,5 +103,5 @@ export const IndexPatternDimensionEditorComponent = function IndexPatternDimensi ); }; -export const IndexPatternDimensionTrigger = memo(IndexPatternDimensionTriggerComponent); -export const IndexPatternDimensionEditor = memo(IndexPatternDimensionEditorComponent); +export const FormBasedDimensionTrigger = memo(FormBasedDimensionTriggerComponent); +export const FormBasedDimensionEditor = memo(FormBasedDimensionEditorComponent); diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimensions_editor_helpers.tsx b/x-pack/plugins/lens/public/datasources/form_based/dimension_panel/dimensions_editor_helpers.tsx similarity index 100% rename from x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimensions_editor_helpers.tsx rename to x-pack/plugins/lens/public/datasources/form_based/dimension_panel/dimensions_editor_helpers.tsx diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/droppable/get_drop_props.test.ts b/x-pack/plugins/lens/public/datasources/form_based/dimension_panel/droppable/get_drop_props.test.ts similarity index 99% rename from x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/droppable/get_drop_props.test.ts rename to x-pack/plugins/lens/public/datasources/form_based/dimension_panel/droppable/get_drop_props.test.ts index 2f4d8a0121aa1..21650cffed54a 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/droppable/get_drop_props.test.ts +++ b/x-pack/plugins/lens/public/datasources/form_based/dimension_panel/droppable/get_drop_props.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { DragDropOperation, OperationMetadata } from '../../../types'; +import { DragDropOperation, OperationMetadata } from '../../../../types'; import { TermsIndexPatternColumn } from '../../operations'; import { getDropProps } from './get_drop_props'; import { @@ -15,7 +15,7 @@ import { mockedDndOperations, mockedColumns, } from './mocks'; -import { generateId } from '../../../id_generator'; +import { generateId } from '../../../../id_generator'; const getDefaultProps = () => ({ indexPatterns: mockDataViews(), @@ -27,7 +27,7 @@ const getDefaultProps = () => ({ source: mockedDndOperations.bucket, }); -describe('IndexPatternDimensionEditorPanel#getDropProps', () => { +describe('FormBasedDimensionEditorPanel#getDropProps', () => { describe('not dragging', () => { it('returns undefined if no drag is happening', () => { expect(getDropProps({ ...getDefaultProps(), source: undefined })).toBe(undefined); diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/droppable/get_drop_props.ts b/x-pack/plugins/lens/public/datasources/form_based/dimension_panel/droppable/get_drop_props.ts similarity index 95% rename from x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/droppable/get_drop_props.ts rename to x-pack/plugins/lens/public/datasources/form_based/dimension_panel/droppable/get_drop_props.ts index a1f16006fd803..a9e81bd6df668 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/droppable/get_drop_props.ts +++ b/x-pack/plugins/lens/public/datasources/form_based/dimension_panel/droppable/get_drop_props.ts @@ -12,22 +12,22 @@ import { IndexPattern, IndexPatternMap, IndexPatternField, -} from '../../../types'; +} from '../../../../types'; import { getCurrentFieldsForOperation, getOperationDisplay, hasOperationSupportForMultipleFields, } from '../../operations'; -import { isDraggedDataViewField, isOperationFromTheSameGroup } from '../../../utils'; +import { isDraggedDataViewField, isOperationFromTheSameGroup } from '../../../../utils'; import { hasField } from '../../pure_utils'; -import { DragContextState } from '../../../drag_drop/providers'; -import { OperationMetadata, DraggedField } from '../../../types'; +import { DragContextState } from '../../../../drag_drop/providers'; +import { OperationMetadata, DraggedField } from '../../../../types'; import { getOperationTypesForField } from '../../operations'; -import { GenericIndexPatternColumn } from '../../indexpattern'; -import { IndexPatternPrivateState, DataViewDragDropOperation } from '../../types'; +import { GenericIndexPatternColumn } from '../../form_based'; +import { FormBasedPrivateState, DataViewDragDropOperation } from '../../types'; interface GetDropPropsArgs { - state: IndexPatternPrivateState; + state: FormBasedPrivateState; source?: DragContextState['dragging']; target: DragDropOperation; indexPatterns: IndexPatternMap; diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/droppable/index.ts b/x-pack/plugins/lens/public/datasources/form_based/dimension_panel/droppable/index.ts similarity index 100% rename from x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/droppable/index.ts rename to x-pack/plugins/lens/public/datasources/form_based/dimension_panel/droppable/index.ts diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/droppable/mocks.ts b/x-pack/plugins/lens/public/datasources/form_based/dimension_panel/droppable/mocks.ts similarity index 97% rename from x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/droppable/mocks.ts rename to x-pack/plugins/lens/public/datasources/form_based/dimension_panel/droppable/mocks.ts index 93b63071d6642..ceb16345f475c 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/droppable/mocks.ts +++ b/x-pack/plugins/lens/public/datasources/form_based/dimension_panel/droppable/mocks.ts @@ -5,9 +5,9 @@ * 2.0. */ -import { IndexPatternLayer } from '../../types'; +import { FormBasedLayer } from '../../types'; import { documentField } from '../../document_field'; -import { IndexPatternMap, OperationMetadata } from '../../../types'; +import { IndexPatternMap, OperationMetadata } from '../../../../types'; import { DateHistogramIndexPatternColumn, GenericIndexPatternColumn, @@ -15,7 +15,7 @@ import { TermsIndexPatternColumn, } from '../../operations'; import { getFieldByNameFactory } from '../../pure_helpers'; -jest.mock('../../../id_generator'); +jest.mock('../../../../id_generator'); export const mockDataViews = (): IndexPatternMap => { const fields = [ @@ -191,7 +191,7 @@ export const mockedColumns: Record = { } as GenericIndexPatternColumn, }; -export const mockedLayers: Record IndexPatternLayer> = { +export const mockedLayers: Record FormBasedLayer> = { singleColumnLayer: (id = 'col1') => ({ indexPatternId: 'first', columnOrder: [id], diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/droppable/on_drop_handler.test.ts b/x-pack/plugins/lens/public/datasources/form_based/dimension_panel/droppable/on_drop_handler.test.ts similarity index 98% rename from x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/droppable/on_drop_handler.test.ts rename to x-pack/plugins/lens/public/datasources/form_based/dimension_panel/droppable/on_drop_handler.test.ts index 3b468181db6df..1bff858194a36 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/droppable/on_drop_handler.test.ts +++ b/x-pack/plugins/lens/public/datasources/form_based/dimension_panel/droppable/on_drop_handler.test.ts @@ -6,10 +6,14 @@ */ import { onDrop } from './on_drop_handler'; -import { IndexPatternPrivateState } from '../../types'; -import { OperationMetadata, DropType, DatasourceDimensionDropHandlerProps } from '../../../types'; +import { FormBasedPrivateState } from '../../types'; +import { + OperationMetadata, + DropType, + DatasourceDimensionDropHandlerProps, +} from '../../../../types'; import { FormulaIndexPatternColumn, MedianIndexPatternColumn } from '../../operations'; -import { generateId } from '../../../id_generator'; +import { generateId } from '../../../../id_generator'; import { mockDataViews, mockedLayers, @@ -18,7 +22,7 @@ import { mockedColumns, } from './mocks'; -jest.mock('../../../id_generator'); +jest.mock('../../../../id_generator'); const dimensionGroups = [ { @@ -47,7 +51,7 @@ const dimensionGroups = [ }, ]; -function getStateWithMultiFieldColumn(state: IndexPatternPrivateState) { +function getStateWithMultiFieldColumn(state: FormBasedPrivateState) { return { ...state, layers: { @@ -62,10 +66,10 @@ function getStateWithMultiFieldColumn(state: IndexPatternPrivateState) { }; } -describe('IndexPatternDimensionEditorPanel: onDrop', () => { - let state: IndexPatternPrivateState; +describe('FormBasedDimensionEditorPanel: onDrop', () => { + let state: FormBasedPrivateState; let setState: jest.Mock; - let defaultProps: DatasourceDimensionDropHandlerProps; + let defaultProps: DatasourceDimensionDropHandlerProps; beforeEach(() => { state = { @@ -347,7 +351,7 @@ describe('IndexPatternDimensionEditorPanel: onDrop', () => { describe('dropping a dimension', () => { it('sets correct order in group for metric and bucket columns when duplicating a column in group', () => { - const testState: IndexPatternPrivateState = { + const testState: FormBasedPrivateState = { ...state, layers: { ...state.layers, @@ -439,7 +443,7 @@ describe('IndexPatternDimensionEditorPanel: onDrop', () => { it('when duplicating fullReference column, the referenced columns get duplicated too', () => { (generateId as jest.Mock).mockReturnValue(`ref1Copy`); - const testState: IndexPatternPrivateState = { + const testState: FormBasedPrivateState = { ...state, layers: { ...state.layers, @@ -501,7 +505,7 @@ describe('IndexPatternDimensionEditorPanel: onDrop', () => { it('when duplicating fullReference column, the multiple referenced columns get duplicated too', () => { (generateId as jest.Mock).mockReturnValueOnce(`ref1Copy`); (generateId as jest.Mock).mockReturnValueOnce(`ref2Copy`); - const testState: IndexPatternPrivateState = { + const testState: FormBasedPrivateState = { ...state, layers: { ...state.layers, @@ -566,7 +570,7 @@ describe('IndexPatternDimensionEditorPanel: onDrop', () => { it('when duplicating fullReference column, the referenced columns get duplicated', () => { (generateId as jest.Mock).mockReturnValueOnce(`ref1Copy`); (generateId as jest.Mock).mockReturnValueOnce(`ref2Copy`); - const testState: IndexPatternPrivateState = { + const testState: FormBasedPrivateState = { ...state, layers: { ...state.layers, @@ -854,7 +858,7 @@ describe('IndexPatternDimensionEditorPanel: onDrop', () => { }); describe('dimension group aware ordering and copying', () => { - let testState: IndexPatternPrivateState; + let testState: FormBasedPrivateState; beforeEach(() => { testState = { ...state }; testState.layers.first = { ...mockedLayers.multipleColumnsLayer() }; @@ -1541,7 +1545,7 @@ describe('IndexPatternDimensionEditorPanel: onDrop', () => { }, ]; describe('simple operations', () => { - let props: DatasourceDimensionDropHandlerProps; + let props: DatasourceDimensionDropHandlerProps; beforeEach(() => { setState = jest.fn(); @@ -2087,7 +2091,7 @@ describe('IndexPatternDimensionEditorPanel: onDrop', () => { }); }); describe('references', () => { - let props: DatasourceDimensionDropHandlerProps; + let props: DatasourceDimensionDropHandlerProps; beforeEach(() => { props = { dimensionGroups: defaultDimensionGroups, diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/droppable/on_drop_handler.ts b/x-pack/plugins/lens/public/datasources/form_based/dimension_panel/droppable/on_drop_handler.ts similarity index 98% rename from x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/droppable/on_drop_handler.ts rename to x-pack/plugins/lens/public/datasources/form_based/dimension_panel/droppable/on_drop_handler.ts index 232c96610f04c..ad575d3c53947 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/droppable/on_drop_handler.ts +++ b/x-pack/plugins/lens/public/datasources/form_based/dimension_panel/droppable/on_drop_handler.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { isDraggedDataViewField } from '../../../utils'; +import { isDraggedDataViewField } from '../../../../utils'; import { DatasourceDimensionDropHandlerProps, DragDropOperation, @@ -14,7 +14,7 @@ import { StateSetter, VisualizationDimensionGroupConfig, DraggedField, -} from '../../../types'; +} from '../../../../types'; import { insertOrReplaceColumn, deleteColumn, @@ -28,12 +28,12 @@ import { } from '../../operations'; import { mergeLayer, mergeLayers } from '../../state_helpers'; import { getNewOperation, getField } from './get_drop_props'; -import { IndexPatternPrivateState, DataViewDragDropOperation } from '../../types'; +import { FormBasedPrivateState, DataViewDragDropOperation } from '../../types'; interface DropHandlerProps { - state: IndexPatternPrivateState; + state: FormBasedPrivateState; setState: StateSetter< - IndexPatternPrivateState, + FormBasedPrivateState, { isDimensionComplete?: boolean; forceRender?: boolean; @@ -46,7 +46,7 @@ interface DropHandlerProps { indexPatterns: IndexPatternMap; } -export function onDrop(props: DatasourceDimensionDropHandlerProps) { +export function onDrop(props: DatasourceDimensionDropHandlerProps) { const { target, source, dropType, state, indexPatterns } = props; if (isDraggedDataViewField(source) && isFieldDropType(dropType)) { diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/field_input.test.tsx b/x-pack/plugins/lens/public/datasources/form_based/dimension_panel/field_input.test.tsx similarity index 98% rename from x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/field_input.test.tsx rename to x-pack/plugins/lens/public/datasources/form_based/dimension_panel/field_input.test.tsx index b7ab501f34d16..877dc18156cdf 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/field_input.test.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/dimension_panel/field_input.test.tsx @@ -21,7 +21,7 @@ import { import { FieldInput, getErrorMessage } from './field_input'; import { createMockedIndexPattern } from '../mocks'; import { getOperationSupportMatrix } from '.'; -import { GenericIndexPatternColumn, IndexPatternLayer, IndexPatternPrivateState } from '../types'; +import { GenericIndexPatternColumn, FormBasedLayer, FormBasedPrivateState } from '../types'; import { ReferenceBasedIndexPatternColumn } from '../operations/definitions/column_types'; jest.mock('../operations/layer_helpers', () => { @@ -30,7 +30,7 @@ jest.mock('../operations/layer_helpers', () => { return { ...original, insertOrReplaceColumn: () => { - return {} as IndexPatternLayer; + return {} as FormBasedLayer; }, }; }); @@ -113,14 +113,14 @@ function getLayer(col1: GenericIndexPatternColumn = getStringBasedOperationColum }; } function getDefaultOperationSupportMatrix( - layer: IndexPatternLayer, + layer: FormBasedLayer, columnId: string, existingFields: Record> ) { return getOperationSupportMatrix({ state: { layers: { layer1: layer }, - } as unknown as IndexPatternPrivateState, + } as unknown as FormBasedPrivateState, layerId: 'layer1', filterOperations: () => true, columnId, diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/field_input.tsx b/x-pack/plugins/lens/public/datasources/form_based/dimension_panel/field_input.tsx similarity index 100% rename from x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/field_input.tsx rename to x-pack/plugins/lens/public/datasources/form_based/dimension_panel/field_input.tsx diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/field_select.scss b/x-pack/plugins/lens/public/datasources/form_based/dimension_panel/field_select.scss similarity index 100% rename from x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/field_select.scss rename to x-pack/plugins/lens/public/datasources/form_based/dimension_panel/field_select.scss diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/field_select.tsx b/x-pack/plugins/lens/public/datasources/form_based/dimension_panel/field_select.tsx similarity index 95% rename from x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/field_select.tsx rename to x-pack/plugins/lens/public/datasources/form_based/dimension_panel/field_select.tsx index af5dc76143b17..52b2c128af595 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/field_select.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/dimension_panel/field_select.tsx @@ -10,11 +10,15 @@ import { partition } from 'lodash'; import React, { useMemo } from 'react'; import { i18n } from '@kbn/i18n'; import { EuiComboBoxOptionOption, EuiComboBoxProps } from '@elastic/eui'; -import type { OperationType } from '../indexpattern'; +import type { OperationType } from '../form_based'; import type { OperationSupportMatrix } from './operation_support'; -import { FieldOption, FieldOptionValue, FieldPicker } from '../../shared_components/field_picker'; -import { fieldContainsData } from '../../shared_components'; -import type { ExistingFieldsMap, IndexPattern } from '../../types'; +import { + FieldOption, + FieldOptionValue, + FieldPicker, +} from '../../../shared_components/field_picker'; +import { fieldContainsData } from '../../../shared_components'; +import type { ExistingFieldsMap, IndexPattern } from '../../../types'; import { getFieldType } from '../pure_utils'; export type FieldChoiceWithOperationType = FieldOptionValue & { diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/filtering.tsx b/x-pack/plugins/lens/public/datasources/form_based/dimension_panel/filtering.tsx similarity index 81% rename from x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/filtering.tsx rename to x-pack/plugins/lens/public/datasources/form_based/dimension_panel/filtering.tsx index 059170d9702d8..13db26af12108 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/filtering.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/dimension_panel/filtering.tsx @@ -8,11 +8,11 @@ import React, { useCallback } from 'react'; import { isEqual } from 'lodash'; import type { Query } from '@kbn/es-query'; import { GenericIndexPatternColumn, operationDefinitionMap } from '../operations'; -import type { IndexPatternLayer } from '../types'; -import { validateQuery, FilterQueryInput } from '../../shared_components'; -import type { IndexPattern } from '../../types'; +import type { FormBasedLayer } from '../types'; +import { validateQuery, FilterQueryInput } from '../../../shared_components'; +import type { IndexPattern } from '../../../types'; -export function setFilter(columnId: string, layer: IndexPatternLayer, query: Query | undefined) { +export function setFilter(columnId: string, layer: FormBasedLayer, query: Query | undefined) { return { ...layer, columns: { @@ -36,8 +36,8 @@ export function Filtering({ selectedColumn: GenericIndexPatternColumn; indexPattern: IndexPattern; columnId: string; - layer: IndexPatternLayer; - updateLayer: (newLayer: IndexPatternLayer) => void; + layer: FormBasedLayer; + updateLayer: (newLayer: FormBasedLayer) => void; helpMessage: string | null; }) { const inputFilter = selectedColumn.filter; diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/format_selector.test.tsx b/x-pack/plugins/lens/public/datasources/form_based/dimension_panel/format_selector.test.tsx similarity index 98% rename from x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/format_selector.test.tsx rename to x-pack/plugins/lens/public/datasources/form_based/dimension_panel/format_selector.test.tsx index d59cb4f136fda..6763d6337880b 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/format_selector.test.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/dimension_panel/format_selector.test.tsx @@ -9,7 +9,7 @@ import React from 'react'; import { mount, shallow } from 'enzyme'; import { FormatSelector } from './format_selector'; import { act } from 'react-dom/test-utils'; -import { GenericIndexPatternColumn } from '../..'; +import { GenericIndexPatternColumn } from '../../..'; jest.mock('lodash', () => { const original = jest.requireActual('lodash'); diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/format_selector.tsx b/x-pack/plugins/lens/public/datasources/form_based/dimension_panel/format_selector.tsx similarity index 97% rename from x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/format_selector.tsx rename to x-pack/plugins/lens/public/datasources/form_based/dimension_panel/format_selector.tsx index 280829c8c1573..62770711a62df 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/format_selector.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/dimension_panel/format_selector.tsx @@ -8,9 +8,9 @@ import React, { useCallback, useMemo, useState } from 'react'; import { i18n } from '@kbn/i18n'; import { EuiFormRow, EuiComboBox, EuiSpacer, EuiRange, EuiFieldText } from '@elastic/eui'; -import { GenericIndexPatternColumn } from '../indexpattern'; +import { GenericIndexPatternColumn } from '../form_based'; import { isColumnFormatted } from '../operations/definitions/helpers'; -import { useDebouncedValue } from '../../shared_components'; +import { useDebouncedValue } from '../../../shared_components'; const supportedFormats: Record = { number: { diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/index.ts b/x-pack/plugins/lens/public/datasources/form_based/dimension_panel/index.ts similarity index 100% rename from x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/index.ts rename to x-pack/plugins/lens/public/datasources/form_based/dimension_panel/index.ts diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/operation_support.ts b/x-pack/plugins/lens/public/datasources/form_based/dimension_panel/operation_support.ts similarity index 91% rename from x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/operation_support.ts rename to x-pack/plugins/lens/public/datasources/form_based/dimension_panel/operation_support.ts index 43d9770deb228..5c08b98023c74 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/operation_support.ts +++ b/x-pack/plugins/lens/public/datasources/form_based/dimension_panel/operation_support.ts @@ -6,10 +6,10 @@ */ import memoizeOne from 'memoize-one'; -import { DatasourceDimensionDropProps, IndexPatternMap, OperationMetadata } from '../../types'; -import { OperationType } from '../indexpattern'; +import { DatasourceDimensionDropProps, IndexPatternMap, OperationMetadata } from '../../../types'; +import { OperationType } from '../form_based'; import { memoizedGetAvailableOperationsByMetadata, OperationFieldTuple } from '../operations'; -import { IndexPatternPrivateState } from '../types'; +import { FormBasedPrivateState } from '../types'; export interface OperationSupportMatrix { operationByField: Partial>>; @@ -18,9 +18,9 @@ export interface OperationSupportMatrix { } type Props = Pick< - DatasourceDimensionDropProps['target'], + DatasourceDimensionDropProps['target'], 'layerId' | 'columnId' | 'filterOperations' -> & { state: IndexPatternPrivateState; indexPatterns: IndexPatternMap }; +> & { state: FormBasedPrivateState; indexPatterns: IndexPatternMap }; function computeOperationMatrix( operationsByMetadata: Array<{ diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/reduced_time_range.tsx b/x-pack/plugins/lens/public/datasources/form_based/dimension_panel/reduced_time_range.tsx similarity index 96% rename from x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/reduced_time_range.tsx rename to x-pack/plugins/lens/public/datasources/form_based/dimension_panel/reduced_time_range.tsx index 4d160f7923e06..6f92b8dc75c17 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/reduced_time_range.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/dimension_panel/reduced_time_range.tsx @@ -17,13 +17,13 @@ import { GenericIndexPatternColumn, operationDefinitionMap, } from '../operations'; -import type { IndexPatternLayer } from '../types'; -import type { IndexPattern } from '../../types'; +import type { FormBasedLayer } from '../types'; +import type { IndexPattern } from '../../../types'; import { reducedTimeRangeOptions } from '../reduced_time_range_utils'; export function setReducedTimeRange( columnId: string, - layer: IndexPatternLayer, + layer: FormBasedLayer, reducedTimeRange: string | undefined, skipLabelUpdate?: boolean ) { @@ -69,8 +69,8 @@ export function ReducedTimeRange({ }: { selectedColumn: GenericIndexPatternColumn; columnId: string; - layer: IndexPatternLayer; - updateLayer: (newLayer: IndexPatternLayer) => void; + layer: FormBasedLayer; + updateLayer: (newLayer: FormBasedLayer) => void; indexPattern: IndexPattern; helpMessage: string | null; skipLabelUpdate?: boolean; diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/reference_editor.test.tsx b/x-pack/plugins/lens/public/datasources/form_based/dimension_panel/reference_editor.test.tsx similarity index 98% rename from x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/reference_editor.test.tsx rename to x-pack/plugins/lens/public/datasources/form_based/dimension_panel/reference_editor.test.tsx index 6e5c157e5b9e8..d46dabf6c12f3 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/reference_editor.test.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/dimension_panel/reference_editor.test.tsx @@ -16,7 +16,7 @@ import { fieldFormatsServiceMock } from '@kbn/field-formats-plugin/public/mocks' import type { IUiSettingsClient, SavedObjectsClientContract, HttpSetup } from '@kbn/core/public'; import { IStorageWrapper } from '@kbn/kibana-utils-plugin/public'; import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; -import { OperationMetadata } from '../../types'; +import { OperationMetadata } from '../../../types'; import { createMockedIndexPattern, createMockedIndexPatternWithoutType } from '../mocks'; import { ReferenceEditor, ReferenceEditorProps } from './reference_editor'; import { @@ -26,7 +26,7 @@ import { TermsIndexPatternColumn, } from '../operations'; import { FieldSelect } from './field_select'; -import { IndexPatternLayer } from '../types'; +import { FormBasedLayer } from '../types'; jest.mock('../operations'); @@ -148,7 +148,7 @@ describe('reference editor', () => { sourceField: 'bytes', }, }, - } as IndexPatternLayer; + } as FormBasedLayer; wrapper = mount( { sourceField: 'dest', }, }, - } as IndexPatternLayer; + } as FormBasedLayer; wrapper = mount( { sourceField: 'bytes', }, }, - } as IndexPatternLayer; + } as FormBasedLayer; wrapper = mount( { sourceField: 'bytes', }, }, - } as IndexPatternLayer; + } as FormBasedLayer; wrapper = mount( { sourceField: 'dest', }, }, - } as IndexPatternLayer; + } as FormBasedLayer; const onChooseFunction = jest.fn(); wrapper = mount( { sourceField: 'bytes', }, }, - } as IndexPatternLayer; + } as FormBasedLayer; wrapper = mount( { incompleteColumns: { ref: { operationType: 'max' }, }, - } as IndexPatternLayer; + } as FormBasedLayer; wrapper = mount( { incompleteColumns: { ref: { sourceField: 'timestamp' }, }, - } as IndexPatternLayer; + } as FormBasedLayer; wrapper = mount( { sourceField: 'missing', }, }, - } as IndexPatternLayer; + } as FormBasedLayer; wrapper = mount( IndexPatternLayer) + | FormBasedLayer + | ((prevLayer: FormBasedLayer) => FormBasedLayer) | GenericIndexPatternColumn ) => void; onChooseField: (choice: FieldChoiceWithOperationType) => void; diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/time_scaling.tsx b/x-pack/plugins/lens/public/datasources/form_based/dimension_panel/time_scaling.tsx similarity index 91% rename from x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/time_scaling.tsx rename to x-pack/plugins/lens/public/datasources/form_based/dimension_panel/time_scaling.tsx index 791d3b5846f24..003407649622e 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/time_scaling.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/dimension_panel/time_scaling.tsx @@ -20,13 +20,13 @@ import { GenericIndexPatternColumn, operationDefinitionMap, } from '../operations'; -import type { TimeScaleUnit } from '../../../common/expressions'; -import { unitSuffixesLong } from '../../../common/suffix_formatter'; -import type { IndexPatternLayer } from '../types'; +import type { TimeScaleUnit } from '../../../../common/expressions'; +import { unitSuffixesLong } from '../../../../common/suffix_formatter'; +import type { FormBasedLayer } from '../types'; export function setTimeScaling( columnId: string, - layer: IndexPatternLayer, + layer: FormBasedLayer, timeScale: TimeScaleUnit | undefined ) { const currentColumn = layer.columns[columnId]; @@ -62,8 +62,8 @@ export function TimeScaling({ }: { selectedColumn: GenericIndexPatternColumn; columnId: string; - layer: IndexPatternLayer; - updateLayer: (newLayer: IndexPatternLayer) => void; + layer: FormBasedLayer; + updateLayer: (newLayer: FormBasedLayer) => void; }) { const selectedOperation = operationDefinitionMap[selectedColumn.operationType]; diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/time_shift.tsx b/x-pack/plugins/lens/public/datasources/form_based/dimension_panel/time_shift.tsx similarity index 94% rename from x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/time_shift.tsx rename to x-pack/plugins/lens/public/datasources/form_based/dimension_panel/time_shift.tsx index 63696a3a2196c..35f278cbbe988 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/time_shift.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/dimension_panel/time_shift.tsx @@ -15,18 +15,18 @@ import { GenericIndexPatternColumn, operationDefinitionMap, } from '../operations'; -import type { IndexPatternLayer } from '../types'; -import type { IndexPatternDimensionEditorProps } from './dimension_panel'; +import type { FormBasedLayer } from '../types'; +import type { FormBasedDimensionEditorProps } from './dimension_panel'; import { getDateHistogramInterval, getLayerTimeShiftChecks, timeShiftOptions, } from '../time_shift_utils'; -import type { IndexPattern } from '../../types'; +import type { IndexPattern } from '../../../types'; export function setTimeShift( columnId: string, - layer: IndexPatternLayer, + layer: FormBasedLayer, timeShift: string | undefined ) { const trimmedTimeShift = timeShift?.trim(); @@ -69,9 +69,9 @@ export function TimeShift({ selectedColumn: GenericIndexPatternColumn; indexPattern: IndexPattern; columnId: string; - layer: IndexPatternLayer; - updateLayer: (newLayer: IndexPatternLayer) => void; - activeData: IndexPatternDimensionEditorProps['activeData']; + layer: FormBasedLayer; + updateLayer: (newLayer: FormBasedLayer) => void; + activeData: FormBasedDimensionEditorProps['activeData']; layerId: string; }) { const [localValue, setLocalValue] = useState(selectedColumn.timeShift); diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/document_field.ts b/x-pack/plugins/lens/public/datasources/form_based/document_field.ts similarity index 86% rename from x-pack/plugins/lens/public/indexpattern_datasource/document_field.ts rename to x-pack/plugins/lens/public/datasources/form_based/document_field.ts index e6ef0fcfdc0bf..557a087d2a6e6 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/document_field.ts +++ b/x-pack/plugins/lens/public/datasources/form_based/document_field.ts @@ -6,8 +6,8 @@ */ import { i18n } from '@kbn/i18n'; -import { DOCUMENT_FIELD_NAME } from '../../common'; -import type { IndexPatternField } from '../types'; +import { DOCUMENT_FIELD_NAME } from '../../../common'; +import type { IndexPatternField } from '../../types'; const customLabel = i18n.translate('xpack.lens.indexPattern.records', { defaultMessage: 'Records', diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/field_item.scss b/x-pack/plugins/lens/public/datasources/form_based/field_item.scss similarity index 97% rename from x-pack/plugins/lens/public/indexpattern_datasource/field_item.scss rename to x-pack/plugins/lens/public/datasources/form_based/field_item.scss index 873f5bdcbdf52..5af939906b25c 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/field_item.scss +++ b/x-pack/plugins/lens/public/datasources/form_based/field_item.scss @@ -1,4 +1,4 @@ -@import '../mixins'; +@import '../../mixins'; .lnsFieldItem { width: 100%; diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/field_item.test.tsx b/x-pack/plugins/lens/public/datasources/form_based/field_item.test.tsx similarity index 99% rename from x-pack/plugins/lens/public/indexpattern_datasource/field_item.test.tsx rename to x-pack/plugins/lens/public/datasources/form_based/field_item.test.tsx index 19b3f9e313267..a0514dafd61b0 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/field_item.test.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/field_item.test.tsx @@ -15,7 +15,7 @@ import { coreMock } from '@kbn/core/public/mocks'; import { mountWithIntl } from '@kbn/test-jest-helpers'; import { findTestSubject } from '@elastic/eui/lib/test'; import { fieldFormatsServiceMock } from '@kbn/field-formats-plugin/public/mocks'; -import { IndexPattern } from '../types'; +import { IndexPattern } from '../../types'; import { chartPluginMock } from '@kbn/charts-plugin/public/mocks'; import { documentField } from './document_field'; import { uiActionsPluginMock } from '@kbn/ui-actions-plugin/public/mocks'; @@ -25,9 +25,9 @@ import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; import { dataViewPluginMocks } from '@kbn/data-views-plugin/public/mocks'; import { DataView, DataViewField } from '@kbn/data-views-plugin/common'; import { loadFieldStats } from '@kbn/unified-field-list-plugin/public/services/field_stats'; +import { DOCUMENT_FIELD_NAME } from '../../../common'; +import { LensFieldIcon } from '../../shared_components'; import { FieldStats, FieldVisualizeButton } from '@kbn/unified-field-list-plugin/public'; -import { DOCUMENT_FIELD_NAME } from '../../common'; -import { LensFieldIcon } from '../shared_components'; jest.mock('@kbn/unified-field-list-plugin/public/services/field_stats', () => ({ loadFieldStats: jest.fn().mockResolvedValue({}), diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/field_item.tsx b/x-pack/plugins/lens/public/datasources/form_based/field_item.tsx similarity index 95% rename from x-pack/plugins/lens/public/indexpattern_datasource/field_item.tsx rename to x-pack/plugins/lens/public/datasources/form_based/field_item.tsx index 17b1ce35f38b0..5ebfecc4cc95a 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/field_item.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/field_item.tsx @@ -26,16 +26,16 @@ import { FieldPopoverVisualize, } from '@kbn/unified-field-list-plugin/public'; import { generateFilters, getEsQueryConfig } from '@kbn/data-plugin/public'; -import { APP_ID } from '../../common/constants'; -import { DragDrop } from '../drag_drop'; -import { DatasourceDataPanelProps, DataType } from '../types'; -import { DOCUMENT_FIELD_NAME } from '../../common'; -import type { IndexPattern, IndexPatternField } from '../types'; -import { LensFieldIcon } from '../shared_components/field_picker/lens_field_icon'; -import type { LensAppServices } from '../app_plugin/types'; -import { debouncedComponent } from '../debounced_component'; +import { DragDrop } from '../../drag_drop'; +import { DatasourceDataPanelProps, DataType } from '../../types'; +import { DOCUMENT_FIELD_NAME } from '../../../common'; +import type { IndexPattern, IndexPatternField } from '../../types'; +import { LensFieldIcon } from '../../shared_components/field_picker/lens_field_icon'; +import type { LensAppServices } from '../../app_plugin/types'; +import { debouncedComponent } from '../../debounced_component'; +import { APP_ID } from '../../../common/constants'; import { getFieldType } from './pure_utils'; -import { combineQueryAndFilters } from '../app_plugin/show_underlying_data'; +import { combineQueryAndFilters } from '../../app_plugin/show_underlying_data'; export interface FieldItemProps { core: DatasourceDataPanelProps['core']; diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/field_list.scss b/x-pack/plugins/lens/public/datasources/form_based/field_list.scss similarity index 100% rename from x-pack/plugins/lens/public/indexpattern_datasource/field_list.scss rename to x-pack/plugins/lens/public/datasources/form_based/field_list.scss diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/field_list.tsx b/x-pack/plugins/lens/public/datasources/form_based/field_list.tsx similarity index 68% rename from x-pack/plugins/lens/public/indexpattern_datasource/field_list.tsx rename to x-pack/plugins/lens/public/datasources/form_based/field_list.tsx index 18da8488db212..3c33770a62560 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/field_list.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/field_list.tsx @@ -13,7 +13,7 @@ import { UiActionsStart } from '@kbn/ui-actions-plugin/public'; import { FieldItem } from './field_item'; import { NoFieldsCallout } from './no_fields_callout'; import { FieldItemSharedProps, FieldsAccordion } from './fields_accordion'; -import type { DatasourceDataPanelProps, IndexPatternField } from '../types'; +import type { DatasourceDataPanelProps, IndexPatternField } from '../../types'; const PAGINATION_SIZE = 50; export type FieldGroups = Record< @@ -29,6 +29,7 @@ export type FieldGroups = Record< isAffectedByTimeFilter: boolean; hideDetails?: boolean; defaultNoFieldsMessage?: string; + hideIfEmpty?: boolean; } >; @@ -161,55 +162,58 @@ export const FieldList = React.memo(function FieldList({ )} - {fieldGroupsToShow.map(([key, fieldGroup], index) => ( - - { - setAccordionState((s) => ({ - ...s, - [key]: open, - })); - const displayedFieldLength = getDisplayedFieldsLength(fieldGroups, { - ...accordionState, - [key]: open, - }); - setPageSize( - Math.max(PAGINATION_SIZE, Math.min(pageSize * 1.5, displayedFieldLength)) - ); - }} - showExistenceFetchError={existenceFetchFailed} - showExistenceFetchTimeout={existenceFetchTimeout} - renderCallout={ - - } - uiActions={uiActions} - /> - - - ))} + {fieldGroupsToShow.map(([key, fieldGroup], index) => { + if (Boolean(fieldGroup.hideIfEmpty) && !fieldGroup.fields.length) return null; + return ( + + { + setAccordionState((s) => ({ + ...s, + [key]: open, + })); + const displayedFieldLength = getDisplayedFieldsLength(fieldGroups, { + ...accordionState, + [key]: open, + }); + setPageSize( + Math.max(PAGINATION_SIZE, Math.min(pageSize * 1.5, displayedFieldLength)) + ); + }} + showExistenceFetchError={existenceFetchFailed} + showExistenceFetchTimeout={existenceFetchTimeout} + renderCallout={ + + } + uiActions={uiActions} + /> + + + ); + })}
); diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/fields_accordion.test.tsx b/x-pack/plugins/lens/public/datasources/form_based/fields_accordion.test.tsx similarity index 98% rename from x-pack/plugins/lens/public/indexpattern_datasource/fields_accordion.test.tsx rename to x-pack/plugins/lens/public/datasources/form_based/fields_accordion.test.tsx index 864ba4ac55af9..a471f8e0fa309 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/fields_accordion.test.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/fields_accordion.test.tsx @@ -10,7 +10,7 @@ import { EuiLoadingSpinner, EuiNotificationBadge } from '@elastic/eui'; import { coreMock } from '@kbn/core/public/mocks'; import { mountWithIntl, shallowWithIntl } from '@kbn/test-jest-helpers'; import { fieldFormatsServiceMock } from '@kbn/field-formats-plugin/public/mocks'; -import { IndexPattern } from '../types'; +import { IndexPattern } from '../../types'; import { FieldItem } from './field_item'; import { FieldsAccordion, FieldsAccordionProps, FieldItemSharedProps } from './fields_accordion'; import { chartPluginMock } from '@kbn/charts-plugin/public/mocks'; diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/fields_accordion.tsx b/x-pack/plugins/lens/public/datasources/form_based/fields_accordion.tsx similarity index 99% rename from x-pack/plugins/lens/public/indexpattern_datasource/fields_accordion.tsx rename to x-pack/plugins/lens/public/datasources/form_based/fields_accordion.tsx index 5db910e6d3eff..105c9583e300d 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/fields_accordion.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/fields_accordion.tsx @@ -23,7 +23,7 @@ import type { Query } from '@kbn/es-query'; import { ChartsPluginSetup } from '@kbn/charts-plugin/public'; import { UiActionsStart } from '@kbn/ui-actions-plugin/public'; import { FieldItem } from './field_item'; -import type { DatasourceDataPanelProps, IndexPattern, IndexPatternField } from '../types'; +import type { DatasourceDataPanelProps, IndexPattern, IndexPatternField } from '../../types'; export interface FieldItemSharedProps { core: DatasourceDataPanelProps['core']; diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.test.ts b/x-pack/plugins/lens/public/datasources/form_based/form_based.test.ts similarity index 93% rename from x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.test.ts rename to x-pack/plugins/lens/public/datasources/form_based/form_based.test.ts index aefb4c7327463..6021cdc1e821e 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.test.ts +++ b/x-pack/plugins/lens/public/datasources/form_based/form_based.test.ts @@ -10,7 +10,7 @@ import { SavedObjectReference } from '@kbn/core/public'; import { isFragment } from 'react-is'; import { coreMock } from '@kbn/core/public/mocks'; import { IStorageWrapper } from '@kbn/kibana-utils-plugin/public'; -import { IndexPatternPersistedState, IndexPatternPrivateState } from './types'; +import { FormBasedPersistedState, FormBasedPrivateState } from './types'; import { unifiedSearchPluginMock } from '@kbn/unified-search-plugin/public/mocks'; import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; import { dataViewPluginMocks } from '@kbn/data-views-plugin/public/mocks'; @@ -20,8 +20,8 @@ import { indexPatternFieldEditorPluginMock } from '@kbn/data-view-field-editor-p import { uiActionsPluginMock } from '@kbn/ui-actions-plugin/public/mocks'; import { fieldFormatsServiceMock } from '@kbn/field-formats-plugin/public/mocks'; import { TinymathAST } from '@kbn/tinymath'; -import { getIndexPatternDatasource, GenericIndexPatternColumn } from './indexpattern'; -import { DatasourcePublicAPI, Datasource, FramePublicAPI, OperationDescriptor } from '../types'; +import { getFormBasedDatasource, GenericIndexPatternColumn } from './form_based'; +import { DatasourcePublicAPI, Datasource, FramePublicAPI, OperationDescriptor } from '../../types'; import { getFieldByNameFactory } from './pure_helpers'; import { operationDefinitionMap, @@ -42,10 +42,10 @@ import { import { createMockedFullReference } from './operations/mocks'; import { cloneDeep } from 'lodash'; import { DatatableColumn } from '@kbn/expressions-plugin/common'; -import { createMockFramePublicAPI } from '../mocks'; +import { createMockFramePublicAPI } from '../../mocks'; jest.mock('./loader'); -jest.mock('../id_generator'); +jest.mock('../../id_generator'); jest.mock('./operations'); jest.mock('./dimension_panel/reference_editor', () => ({ ReferenceEditor: () => null, @@ -178,11 +178,11 @@ const expectedIndexPatterns = { const indexPatterns = expectedIndexPatterns; describe('IndexPattern Data Source', () => { - let baseState: IndexPatternPrivateState; - let indexPatternDatasource: Datasource; + let baseState: FormBasedPrivateState; + let FormBasedDatasource: Datasource; beforeEach(() => { - indexPatternDatasource = getIndexPatternDatasource({ + FormBasedDatasource = getFormBasedDatasource({ unifiedSearch: unifiedSearchPluginMock.createStartContract(), storage: {} as IStorageWrapper, core: coreMock.createStart(), @@ -230,7 +230,7 @@ describe('IndexPattern Data Source', () => { operationType: 'count', sourceField: '___records___', }; - const map = indexPatternDatasource.uniqueLabels({ + const map = FormBasedDatasource.uniqueLabels({ layers: { a: { columnOrder: ['a', 'b'], @@ -252,7 +252,7 @@ describe('IndexPattern Data Source', () => { indexPatternId: 'foo', }, }, - } as unknown as IndexPatternPrivateState); + } as unknown as FormBasedPrivateState); expect(map).toMatchInlineSnapshot(` Object { @@ -267,7 +267,7 @@ describe('IndexPattern Data Source', () => { describe('#getPersistedState', () => { it('should persist from saved state', async () => { - expect(indexPatternDatasource.getPersistableState(baseState)).toEqual({ + expect(FormBasedDatasource.getPersistableState(baseState)).toEqual({ state: { layers: { first: { @@ -298,14 +298,28 @@ describe('IndexPattern Data Source', () => { }); }); + describe('#getSelectedFields', () => { + it('should return the fields used per layer', async () => { + expect(FormBasedDatasource?.getSelectedFields?.(baseState)).toEqual(['op']); + }); + + it('should return empty array for empty layers', async () => { + const state = { + ...baseState, + layers: {}, + }; + expect(FormBasedDatasource?.getSelectedFields?.(state)).toEqual([]); + }); + }); + describe('#toExpression', () => { it('should generate an empty expression when no columns are selected', async () => { - const state = indexPatternDatasource.initialize(); - expect(indexPatternDatasource.toExpression(state, 'first', indexPatterns)).toEqual(null); + const state = FormBasedDatasource.initialize(); + expect(FormBasedDatasource.toExpression(state, 'first', indexPatterns)).toEqual(null); }); it('should create a table when there is a formula without aggs', async () => { - const queryBaseState: IndexPatternPrivateState = { + const queryBaseState: FormBasedPrivateState = { currentIndexPatternId: '1', layers: { first: { @@ -324,7 +338,7 @@ describe('IndexPattern Data Source', () => { }, }, }; - expect(indexPatternDatasource.toExpression(queryBaseState, 'first', indexPatterns)).toEqual({ + expect(FormBasedDatasource.toExpression(queryBaseState, 'first', indexPatterns)).toEqual({ chain: [ { function: 'createTable', @@ -342,7 +356,7 @@ describe('IndexPattern Data Source', () => { }); it('should generate an expression for an aggregated query', async () => { - const queryBaseState: IndexPatternPrivateState = { + const queryBaseState: FormBasedPrivateState = { currentIndexPatternId: '1', layers: { first: { @@ -371,7 +385,7 @@ describe('IndexPattern Data Source', () => { }, }; - expect(indexPatternDatasource.toExpression(queryBaseState, 'first', indexPatterns)) + expect(FormBasedDatasource.toExpression(queryBaseState, 'first', indexPatterns)) .toMatchInlineSnapshot(` Object { "chain": Array [ @@ -496,7 +510,7 @@ describe('IndexPattern Data Source', () => { }); it('should put all time fields used in date_histograms to the esaggs timeFields parameter if not ignoring global time range', async () => { - const queryBaseState: IndexPatternPrivateState = { + const queryBaseState: FormBasedPrivateState = { currentIndexPatternId: '1', layers: { first: { @@ -546,16 +560,12 @@ describe('IndexPattern Data Source', () => { }, }; - const ast = indexPatternDatasource.toExpression( - queryBaseState, - 'first', - indexPatterns - ) as Ast; + const ast = FormBasedDatasource.toExpression(queryBaseState, 'first', indexPatterns) as Ast; expect(ast.chain[1].arguments.timeFields).toEqual(['timestamp', 'another_datefield']); }); it('should pass time shift parameter to metric agg functions', async () => { - const queryBaseState: IndexPatternPrivateState = { + const queryBaseState: FormBasedPrivateState = { currentIndexPatternId: '1', layers: { first: { @@ -585,11 +595,7 @@ describe('IndexPattern Data Source', () => { }, }; - const ast = indexPatternDatasource.toExpression( - queryBaseState, - 'first', - indexPatterns - ) as Ast; + const ast = FormBasedDatasource.toExpression(queryBaseState, 'first', indexPatterns) as Ast; expect((ast.chain[1].arguments.aggs[1] as Ast).chain[0].arguments.timeShift).toEqual(['1d']); }); @@ -609,7 +615,7 @@ describe('IndexPattern Data Source', () => { * The sum has its own shift and does not respected the shift from the moving average * The differences has a filter which is inherited to the median, but not the average as it has its own filter */ - const queryBaseState: IndexPatternPrivateState = { + const queryBaseState: FormBasedPrivateState = { currentIndexPatternId: '1', layers: { first: { @@ -796,11 +802,7 @@ describe('IndexPattern Data Source', () => { }, }; - const ast = indexPatternDatasource.toExpression( - queryBaseState, - 'first', - indexPatterns - ) as Ast; + const ast = FormBasedDatasource.toExpression(queryBaseState, 'first', indexPatterns) as Ast; const count = (ast.chain[1].arguments.aggs[1] as Ast).chain[0]; const sum = (ast.chain[1].arguments.aggs[2] as Ast).chain[0]; const average = (ast.chain[1].arguments.aggs[3] as Ast).chain[0]; @@ -822,7 +824,7 @@ describe('IndexPattern Data Source', () => { }); it('should wrap filtered metrics in filtered metric aggregation', async () => { - const queryBaseState: IndexPatternPrivateState = { + const queryBaseState: FormBasedPrivateState = { currentIndexPatternId: '1', layers: { first: { @@ -864,11 +866,7 @@ describe('IndexPattern Data Source', () => { }, }; - const ast = indexPatternDatasource.toExpression( - queryBaseState, - 'first', - indexPatterns - ) as Ast; + const ast = FormBasedDatasource.toExpression(queryBaseState, 'first', indexPatterns) as Ast; expect(ast.chain[1].arguments.aggs[0]).toMatchInlineSnapshot(` Object { "chain": Array [ @@ -954,7 +952,7 @@ describe('IndexPattern Data Source', () => { }); it('should add time_scale and format function if time scale is set and supported', async () => { - const queryBaseState: IndexPatternPrivateState = { + const queryBaseState: FormBasedPrivateState = { currentIndexPatternId: '1', layers: { first: { @@ -992,11 +990,7 @@ describe('IndexPattern Data Source', () => { }, }; - const ast = indexPatternDatasource.toExpression( - queryBaseState, - 'first', - indexPatterns - ) as Ast; + const ast = FormBasedDatasource.toExpression(queryBaseState, 'first', indexPatterns) as Ast; const timeScaleCalls = ast.chain.filter((fn) => fn.function === 'lens_time_scale'); const formatCalls = ast.chain.filter((fn) => fn.function === 'lens_format_column'); expect(timeScaleCalls).toHaveLength(1); @@ -1040,7 +1034,7 @@ describe('IndexPattern Data Source', () => { }); it('should not add time shift to nested count metric', async () => { - const queryBaseState: IndexPatternPrivateState = { + const queryBaseState: FormBasedPrivateState = { currentIndexPatternId: '1', layers: { first: { @@ -1061,11 +1055,7 @@ describe('IndexPattern Data Source', () => { }, }; - const ast = indexPatternDatasource.toExpression( - queryBaseState, - 'first', - indexPatterns - ) as Ast; + const ast = FormBasedDatasource.toExpression(queryBaseState, 'first', indexPatterns) as Ast; const filteredMetricAgg = (ast.chain[1].arguments.aggs[0] as Ast).chain[0].arguments; const metricAgg = (filteredMetricAgg.customMetric[0] as Ast).chain[0].arguments; const bucketAgg = (filteredMetricAgg.customBucket[0] as Ast).chain[0].arguments; @@ -1076,7 +1066,7 @@ describe('IndexPattern Data Source', () => { }); it('should put column formatters after calculated columns', async () => { - const queryBaseState: IndexPatternPrivateState = { + const queryBaseState: FormBasedPrivateState = { currentIndexPatternId: '1', layers: { first: { @@ -1116,18 +1106,14 @@ describe('IndexPattern Data Source', () => { }, }; - const ast = indexPatternDatasource.toExpression( - queryBaseState, - 'first', - indexPatterns - ) as Ast; + const ast = FormBasedDatasource.toExpression(queryBaseState, 'first', indexPatterns) as Ast; const formatIndex = ast.chain.findIndex((fn) => fn.function === 'lens_format_column'); const calculationIndex = ast.chain.findIndex((fn) => fn.function === 'moving_average'); expect(calculationIndex).toBeLessThan(formatIndex); }); it('should rename the output from esaggs when using flat query', () => { - const queryBaseState: IndexPatternPrivateState = { + const queryBaseState: FormBasedPrivateState = { currentIndexPatternId: '1', layers: { first: { @@ -1168,11 +1154,7 @@ describe('IndexPattern Data Source', () => { }, }; - const ast = indexPatternDatasource.toExpression( - queryBaseState, - 'first', - indexPatterns - ) as Ast; + const ast = FormBasedDatasource.toExpression(queryBaseState, 'first', indexPatterns) as Ast; expect(ast.chain[1].arguments.metricsAtAllLevels).toEqual([false]); expect(JSON.parse(ast.chain[2].arguments.idMap[0] as string)).toEqual({ 'col-0-0': [expect.objectContaining({ id: 'bucket1' })], @@ -1182,7 +1164,7 @@ describe('IndexPattern Data Source', () => { }); it('should not put date fields used outside date_histograms to the esaggs timeFields parameter', async () => { - const queryBaseState: IndexPatternPrivateState = { + const queryBaseState: FormBasedPrivateState = { currentIndexPatternId: '1', layers: { first: { @@ -1211,18 +1193,14 @@ describe('IndexPattern Data Source', () => { }, }; - const ast = indexPatternDatasource.toExpression( - queryBaseState, - 'first', - indexPatterns - ) as Ast; + const ast = FormBasedDatasource.toExpression(queryBaseState, 'first', indexPatterns) as Ast; expect(ast.chain[1].arguments.timeFields).toEqual(['timestamp']); expect(ast.chain[1].arguments.timeFields).not.toContain('timefield'); }); describe('optimizations', () => { it('should call optimizeEsAggs once per operation for which it is available', () => { - const queryBaseState: IndexPatternPrivateState = { + const queryBaseState: FormBasedPrivateState = { currentIndexPatternId: '1', layers: { first: { @@ -1272,7 +1250,7 @@ describe('IndexPattern Data Source', () => { const optimizeMock = jest.spyOn(operationDefinitionMap.percentile, 'optimizeEsAggs'); - indexPatternDatasource.toExpression(queryBaseState, 'first', indexPatterns); + FormBasedDatasource.toExpression(queryBaseState, 'first', indexPatterns); expect(operationDefinitionMap.percentile.optimizeEsAggs).toHaveBeenCalledTimes(1); @@ -1280,7 +1258,7 @@ describe('IndexPattern Data Source', () => { }); it('should update anticipated esAggs column IDs based on the order of the optimized agg expression builders', () => { - const queryBaseState: IndexPatternPrivateState = { + const queryBaseState: FormBasedPrivateState = { currentIndexPatternId: '1', layers: { first: { @@ -1340,11 +1318,7 @@ describe('IndexPattern Data Source', () => { return { aggs: aggs.reverse(), esAggsIdMap }; }); - const ast = indexPatternDatasource.toExpression( - queryBaseState, - 'first', - indexPatterns - ) as Ast; + const ast = FormBasedDatasource.toExpression(queryBaseState, 'first', indexPatterns) as Ast; expect(operationDefinitionMap.percentile.optimizeEsAggs).toHaveBeenCalledTimes(1); @@ -1356,7 +1330,7 @@ describe('IndexPattern Data Source', () => { }); it('should deduplicate aggs for supported operations', () => { - const queryBaseState: IndexPatternPrivateState = { + const queryBaseState: FormBasedPrivateState = { currentIndexPatternId: '1', layers: { first: { @@ -1408,11 +1382,7 @@ describe('IndexPattern Data Source', () => { }, }; - const ast = indexPatternDatasource.toExpression( - queryBaseState, - 'first', - indexPatterns - ) as Ast; + const ast = FormBasedDatasource.toExpression(queryBaseState, 'first', indexPatterns) as Ast; const idMap = JSON.parse(ast.chain[2].arguments.idMap as unknown as string); @@ -1491,7 +1461,7 @@ describe('IndexPattern Data Source', () => { }); it('should collect expression references and append them', async () => { - const queryBaseState: IndexPatternPrivateState = { + const queryBaseState: FormBasedPrivateState = { currentIndexPatternId: '1', layers: { first: { @@ -1517,18 +1487,14 @@ describe('IndexPattern Data Source', () => { }, }; - const ast = indexPatternDatasource.toExpression( - queryBaseState, - 'first', - indexPatterns - ) as Ast; + const ast = FormBasedDatasource.toExpression(queryBaseState, 'first', indexPatterns) as Ast; // @ts-expect-error we can't isolate just the reference type expect(operationDefinitionMap.testReference.toExpression).toHaveBeenCalled(); expect(ast.chain[3]).toEqual('mock'); }); it('should keep correct column mapping keys with reference columns present', async () => { - const queryBaseState: IndexPatternPrivateState = { + const queryBaseState: FormBasedPrivateState = { currentIndexPatternId: '1', layers: { first: { @@ -1554,11 +1520,7 @@ describe('IndexPattern Data Source', () => { }, }; - const ast = indexPatternDatasource.toExpression( - queryBaseState, - 'first', - indexPatterns - ) as Ast; + const ast = FormBasedDatasource.toExpression(queryBaseState, 'first', indexPatterns) as Ast; expect(JSON.parse(ast.chain[2].arguments.idMap[0] as string)).toEqual({ 'col-0-0': [ @@ -1571,7 +1533,7 @@ describe('IndexPattern Data Source', () => { it('should topologically sort references', () => { // This is a real example of count() + count() - const queryBaseState: IndexPatternPrivateState = { + const queryBaseState: FormBasedPrivateState = { currentIndexPatternId: '1', layers: { first: { @@ -1645,11 +1607,7 @@ describe('IndexPattern Data Source', () => { }, }; - const ast = indexPatternDatasource.toExpression( - queryBaseState, - 'first', - indexPatterns - ) as Ast; + const ast = FormBasedDatasource.toExpression(queryBaseState, 'first', indexPatterns) as Ast; const chainLength = ast.chain.length; expect(ast.chain[chainLength - 2].arguments.name).toEqual(['math']); expect(ast.chain[chainLength - 1].arguments.id).toEqual(['formula']); @@ -1674,7 +1632,7 @@ describe('IndexPattern Data Source', () => { }, currentIndexPatternId: '1', }; - expect(indexPatternDatasource.insertLayer(state, 'newLayer')).toEqual({ + expect(FormBasedDatasource.insertLayer(state, 'newLayer')).toEqual({ ...state, layers: { ...state.layers, @@ -1705,7 +1663,7 @@ describe('IndexPattern Data Source', () => { }, currentIndexPatternId: '1', }; - expect(indexPatternDatasource.removeLayer(state, 'first')).toEqual({ + expect(FormBasedDatasource.removeLayer(state, 'first')).toEqual({ ...state, layers: { second: { @@ -1720,7 +1678,7 @@ describe('IndexPattern Data Source', () => { describe('#createEmptyLayer', () => { it('creates state with empty layers', () => { - expect(indexPatternDatasource.createEmptyLayer('index-pattern-id')).toEqual({ + expect(FormBasedDatasource.createEmptyLayer('index-pattern-id')).toEqual({ currentIndexPatternId: 'index-pattern-id', layers: {}, }); @@ -1730,7 +1688,7 @@ describe('IndexPattern Data Source', () => { describe('#getLayers', () => { it('should list the current layers', () => { expect( - indexPatternDatasource.getLayers({ + FormBasedDatasource.getLayers({ layers: { first: { indexPatternId: '1', @@ -1753,7 +1711,7 @@ describe('IndexPattern Data Source', () => { let publicAPI: DatasourcePublicAPI; beforeEach(async () => { - publicAPI = indexPatternDatasource.getPublicAPI({ + publicAPI = FormBasedDatasource.getPublicAPI({ state: baseState, layerId: 'first', indexPatterns, @@ -1770,7 +1728,7 @@ describe('IndexPattern Data Source', () => { }); it('should skip columns that are being referenced', () => { - publicAPI = indexPatternDatasource.getPublicAPI({ + publicAPI = FormBasedDatasource.getPublicAPI({ state: { ...baseState, layers: { @@ -1808,7 +1766,7 @@ describe('IndexPattern Data Source', () => { }); it('should collect all fields (also from referenced columns)', () => { - publicAPI = indexPatternDatasource.getPublicAPI({ + publicAPI = FormBasedDatasource.getPublicAPI({ state: { ...baseState, layers: { @@ -1847,7 +1805,7 @@ describe('IndexPattern Data Source', () => { }); it('should collect and organize fields per visible column', () => { - publicAPI = indexPatternDatasource.getPublicAPI({ + publicAPI = FormBasedDatasource.getPublicAPI({ state: { ...baseState, layers: { @@ -1917,7 +1875,7 @@ describe('IndexPattern Data Source', () => { }); it('should return null for referenced columns', () => { - publicAPI = indexPatternDatasource.getPublicAPI({ + publicAPI = FormBasedDatasource.getPublicAPI({ state: { ...baseState, layers: { @@ -1962,7 +1920,7 @@ describe('IndexPattern Data Source', () => { describe('getFilters', () => { it('should return all filters in metrics, grouped by language', () => { - publicAPI = indexPatternDatasource.getPublicAPI({ + publicAPI = FormBasedDatasource.getPublicAPI({ state: { ...baseState, layers: { @@ -2004,7 +1962,7 @@ describe('IndexPattern Data Source', () => { }); }); it('should ignore empty filtered metrics', () => { - publicAPI = indexPatternDatasource.getPublicAPI({ + publicAPI = FormBasedDatasource.getPublicAPI({ state: { ...baseState, layers: { @@ -2034,7 +1992,7 @@ describe('IndexPattern Data Source', () => { }); }); it('shuold collect top values fields as kuery existence filters if no data is provided', () => { - publicAPI = indexPatternDatasource.getPublicAPI({ + publicAPI = FormBasedDatasource.getPublicAPI({ state: { ...baseState, layers: { @@ -2089,7 +2047,7 @@ describe('IndexPattern Data Source', () => { }); }); it('shuold collect top values fields and terms as kuery filters if data is provided', () => { - publicAPI = indexPatternDatasource.getPublicAPI({ + publicAPI = FormBasedDatasource.getPublicAPI({ state: { ...baseState, layers: { @@ -2160,7 +2118,7 @@ describe('IndexPattern Data Source', () => { }); }); it('shuold collect top values fields and terms and carefully handle empty string values', () => { - publicAPI = indexPatternDatasource.getPublicAPI({ + publicAPI = FormBasedDatasource.getPublicAPI({ state: { ...baseState, layers: { @@ -2231,7 +2189,7 @@ describe('IndexPattern Data Source', () => { }); }); it('should ignore top values fields if other/missing option is enabled', () => { - publicAPI = indexPatternDatasource.getPublicAPI({ + publicAPI = FormBasedDatasource.getPublicAPI({ state: { ...baseState, layers: { @@ -2278,7 +2236,7 @@ describe('IndexPattern Data Source', () => { }); }); it('should collect custom ranges as kuery filters', () => { - publicAPI = indexPatternDatasource.getPublicAPI({ + publicAPI = FormBasedDatasource.getPublicAPI({ state: { ...baseState, layers: { @@ -2333,7 +2291,7 @@ describe('IndexPattern Data Source', () => { }); }); it('should collect custom ranges as kuery filters as partial', () => { - publicAPI = indexPatternDatasource.getPublicAPI({ + publicAPI = FormBasedDatasource.getPublicAPI({ state: { ...baseState, layers: { @@ -2393,7 +2351,7 @@ describe('IndexPattern Data Source', () => { }); }); it('should collect filters within filters operation grouped by language', () => { - publicAPI = indexPatternDatasource.getPublicAPI({ + publicAPI = FormBasedDatasource.getPublicAPI({ state: { ...baseState, layers: { @@ -2464,7 +2422,7 @@ describe('IndexPattern Data Source', () => { }); }); it('should ignore filtered metrics if at least one metric is unfiltered', () => { - publicAPI = indexPatternDatasource.getPublicAPI({ + publicAPI = FormBasedDatasource.getPublicAPI({ state: { ...baseState, layers: { @@ -2502,7 +2460,7 @@ describe('IndexPattern Data Source', () => { }); }); it('should ignore filtered metrics if at least one metric is unfiltered in formula', () => { - publicAPI = indexPatternDatasource.getPublicAPI({ + publicAPI = FormBasedDatasource.getPublicAPI({ state: { ...baseState, layers: { @@ -2575,7 +2533,7 @@ describe('IndexPattern Data Source', () => { }); }); it('should support complete scenarios', () => { - publicAPI = indexPatternDatasource.getPublicAPI({ + publicAPI = FormBasedDatasource.getPublicAPI({ state: { ...baseState, layers: { @@ -2662,7 +2620,7 @@ describe('IndexPattern Data Source', () => { }); it('should avoid duplicate filters when formula has a global filter', () => { - publicAPI = indexPatternDatasource.getPublicAPI({ + publicAPI = FormBasedDatasource.getPublicAPI({ state: { ...baseState, layers: { @@ -2770,7 +2728,7 @@ describe('IndexPattern Data Source', () => { it('should use the results of getErrorMessages directly when single layer', () => { (getErrorMessages as jest.Mock).mockClear(); (getErrorMessages as jest.Mock).mockReturnValueOnce(['error 1', 'error 2']); - const state: IndexPatternPrivateState = { + const state: FormBasedPrivateState = { layers: { first: { indexPatternId: '1', @@ -2780,7 +2738,7 @@ describe('IndexPattern Data Source', () => { }, currentIndexPatternId: '1', }; - expect(indexPatternDatasource.getErrorMessages(state, indexPatterns)).toEqual([ + expect(FormBasedDatasource.getErrorMessages(state, indexPatterns)).toEqual([ { longMessage: 'error 1', shortMessage: '' }, { longMessage: 'error 2', shortMessage: '' }, ]); @@ -2790,7 +2748,7 @@ describe('IndexPattern Data Source', () => { it('should prepend each error with its layer number on multi-layer chart', () => { (getErrorMessages as jest.Mock).mockClear(); (getErrorMessages as jest.Mock).mockReturnValueOnce(['error 1', 'error 2']); - const state: IndexPatternPrivateState = { + const state: FormBasedPrivateState = { layers: { first: { indexPatternId: '1', @@ -2805,7 +2763,7 @@ describe('IndexPattern Data Source', () => { }, currentIndexPatternId: '1', }; - expect(indexPatternDatasource.getErrorMessages(state, indexPatterns)).toEqual([ + expect(FormBasedDatasource.getErrorMessages(state, indexPatterns)).toEqual([ { longMessage: 'Layer 1 error: error 1', shortMessage: '' }, { longMessage: 'Layer 1 error: error 2', shortMessage: '' }, ]); @@ -2814,7 +2772,7 @@ describe('IndexPattern Data Source', () => { }); describe('#getWarningMessages', () => { - let state: IndexPatternPrivateState; + let state: FormBasedPrivateState; let framePublicAPI: FramePublicAPI; beforeEach(() => { @@ -2948,12 +2906,7 @@ describe('IndexPattern Data Source', () => { ); it('should return mismatched time shifts', () => { - const warnings = indexPatternDatasource.getWarningMessages!( - state, - framePublicAPI, - {}, - () => {} - ); + const warnings = FormBasedDatasource.getWarningMessages!(state, framePublicAPI, {}, () => {}); expect(extractTranslationIdsFromWarnings(warnings)).toMatchInlineSnapshot(` Array [ @@ -2966,12 +2919,7 @@ describe('IndexPattern Data Source', () => { it('should show different types of warning messages', () => { framePublicAPI.activeData!.first.columns[1].meta.sourceParams!.hasPrecisionError = true; - const warnings = indexPatternDatasource.getWarningMessages!( - state, - framePublicAPI, - {}, - () => {} - ); + const warnings = FormBasedDatasource.getWarningMessages!(state, framePublicAPI, {}, () => {}); expect(extractTranslationIdsFromWarnings(warnings)).toMatchInlineSnapshot(` Array [ @@ -3002,7 +2950,7 @@ describe('IndexPattern Data Source', () => { currentIndexPatternId: '1', }; - expect(indexPatternDatasource.getErrorMessages(state, indexPatterns)).toEqual([ + expect(FormBasedDatasource.getErrorMessages(state, indexPatterns)).toEqual([ { longMessage: 'Layer 1 error: error 1', shortMessage: '' }, { longMessage: 'Layer 1 error: error 2', shortMessage: '' }, ]); @@ -3013,7 +2961,7 @@ describe('IndexPattern Data Source', () => { describe('#updateStateOnCloseDimension', () => { it('should not update when there are no incomplete columns', () => { expect( - indexPatternDatasource.updateStateOnCloseDimension!({ + FormBasedDatasource.updateStateOnCloseDimension!({ state: { layers: { first: { @@ -3055,7 +3003,7 @@ describe('IndexPattern Data Source', () => { currentIndexPatternId: '1', }; expect( - indexPatternDatasource.updateStateOnCloseDimension!({ + FormBasedDatasource.updateStateOnCloseDimension!({ state, layerId: 'first', columnId: 'col1', @@ -3127,9 +3075,9 @@ describe('IndexPattern Data Source', () => { }, }, }, - } as IndexPatternPrivateState; + } as FormBasedPrivateState; expect( - indexPatternDatasource.isTimeBased(state, { + FormBasedDatasource.isTimeBased(state, { ...indexPatterns, '1': { ...indexPatterns['1'], timeFieldName: undefined }, }) @@ -3189,9 +3137,9 @@ describe('IndexPattern Data Source', () => { }, }, }, - } as IndexPatternPrivateState; + } as FormBasedPrivateState; expect( - indexPatternDatasource.isTimeBased(state, { + FormBasedDatasource.isTimeBased(state, { ...indexPatterns, '1': { ...indexPatterns['1'], timeFieldName: undefined }, }) @@ -3215,9 +3163,9 @@ describe('IndexPattern Data Source', () => { }, }, }, - } as IndexPatternPrivateState; + } as FormBasedPrivateState; expect( - indexPatternDatasource.isTimeBased(state, { + FormBasedDatasource.isTimeBased(state, { ...indexPatterns, '1': { ...indexPatterns['1'], timeFieldName: undefined }, }) @@ -3241,8 +3189,8 @@ describe('IndexPattern Data Source', () => { }, }, }, - } as IndexPatternPrivateState; - expect(indexPatternDatasource.isTimeBased(state, indexPatterns)).toEqual(true); + } as FormBasedPrivateState; + expect(FormBasedDatasource.isTimeBased(state, indexPatterns)).toEqual(true); }); }); @@ -3265,9 +3213,9 @@ describe('IndexPattern Data Source', () => { }, }, }, - } as IndexPatternPrivateState; + } as FormBasedPrivateState; expect( - indexPatternDatasource.initializeDimension!(state, 'first', indexPatterns, { + FormBasedDatasource.initializeDimension!(state, 'first', indexPatterns, { columnId: 'newStatic', groupId: 'a', }) @@ -3292,9 +3240,9 @@ describe('IndexPattern Data Source', () => { }, }, }, - } as IndexPatternPrivateState; + } as FormBasedPrivateState; expect( - indexPatternDatasource.initializeDimension!(state, 'first', indexPatterns, { + FormBasedDatasource.initializeDimension!(state, 'first', indexPatterns, { columnId: 'newStatic', groupId: 'a', staticValue: 0, // use a falsy value to check also this corner case @@ -3329,7 +3277,7 @@ describe('IndexPattern Data Source', () => { describe('#isEqual', () => { const layerId = '8bd66b66-aba3-49fb-9ff2-4bf83f2be08e'; - const persistableState: IndexPatternPersistedState = { + const persistableState: FormBasedPersistedState = { layers: { [layerId]: { columns: { @@ -3366,7 +3314,7 @@ describe('IndexPattern Data Source', () => { it('should be false if datasource states are using different data views', () => { expect( - indexPatternDatasource.isEqual(persistableState, references1, persistableState, references2) + FormBasedDatasource.isEqual(persistableState, references1, persistableState, references2) ).toBe(false); }); @@ -3375,7 +3323,7 @@ describe('IndexPattern Data Source', () => { differentPersistableState.layers[layerId].columnOrder = ['something else']; expect( - indexPatternDatasource.isEqual( + FormBasedDatasource.isEqual( persistableState, references1, differentPersistableState, @@ -3386,7 +3334,7 @@ describe('IndexPattern Data Source', () => { it('should be true if datasource states are identical and they refer to the same data view', () => { expect( - indexPatternDatasource.isEqual(persistableState, references1, persistableState, references1) + FormBasedDatasource.isEqual(persistableState, references1, persistableState, references1) ).toBe(true); }); }); diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.tsx b/x-pack/plugins/lens/public/datasources/form_based/form_based.tsx similarity index 89% rename from x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.tsx rename to x-pack/plugins/lens/public/datasources/form_based/form_based.tsx index fb31c3c1a9a71..67d3acda068c9 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/form_based.tsx @@ -36,7 +36,7 @@ import type { IndexPatternField, IndexPattern, IndexPatternRef, -} from '../types'; +} from '../../types'; import { changeIndexPattern, changeLayerIndexPattern, @@ -49,18 +49,18 @@ import { } from './loader'; import { toExpression } from './to_expression'; import { - IndexPatternDimensionTrigger, - IndexPatternDimensionEditor, + FormBasedDimensionTrigger, + FormBasedDimensionEditor, getDropProps, onDrop, } from './dimension_panel'; -import { IndexPatternDataPanel } from './datapanel'; +import { FormBasedDataPanel } from './datapanel'; import { getDatasourceSuggestionsForField, getDatasourceSuggestionsFromCurrentState, getDatasourceSuggestionsForVisualizeField, getDatasourceSuggestionsForVisualizeCharts, -} from './indexpattern_suggestions'; +} from './form_based_suggestions'; import { getFiltersInLayer, @@ -69,7 +69,7 @@ import { isColumnInvalid, cloneLayer, } from './utils'; -import { isDraggedDataViewField } from '../utils'; +import { isDraggedDataViewField } from '../../utils'; import { normalizeOperationDataType } from './pure_utils'; import { LayerPanel } from './layerpanel'; import { @@ -81,15 +81,15 @@ import { TermsIndexPatternColumn, } from './operations'; import { getReferenceRoot } from './operations/layer_helpers'; -import { IndexPatternPrivateState, IndexPatternPersistedState } from './types'; +import { FormBasedPrivateState, FormBasedPersistedState } from './types'; import { mergeLayer } from './state_helpers'; -import { Datasource, VisualizeEditorContext } from '../types'; +import { Datasource, VisualizeEditorContext } from '../../types'; import { deleteColumn, isReferenced } from './operations'; -import { GeoFieldWorkspacePanel } from '../editor_frame_service/editor_frame/workspace_panel/geo_field_workspace_panel'; -import { DraggingIdentifier } from '../drag_drop'; +import { GeoFieldWorkspacePanel } from '../../editor_frame_service/editor_frame/workspace_panel/geo_field_workspace_panel'; +import { DraggingIdentifier } from '../../drag_drop'; import { getStateTimeShiftWarningMessages } from './time_shift_utils'; import { getPrecisionErrorWarningMessages } from './utils'; -import { DOCUMENT_FIELD_NAME } from '../../common/constants'; +import { DOCUMENT_FIELD_NAME } from '../../../common/constants'; import { isColumnOfType } from './operations/definitions/helpers'; export type { OperationType, GenericIndexPatternColumn } from './operations'; export { deleteColumn } from './operations'; @@ -119,15 +119,15 @@ export function columnToOperation( }; } -export type { FormatColumnArgs, TimeScaleArgs, CounterRateArgs } from '../../common/expressions'; +export type { FormatColumnArgs, TimeScaleArgs, CounterRateArgs } from '../../../common/expressions'; export { getSuffixFormatter, unitSuffixesLong, suffixFormatterId, -} from '../../common/suffix_formatter'; +} from '../../../common/suffix_formatter'; -export function getIndexPatternDatasource({ +export function getFormBasedDatasource({ core, storage, data, @@ -152,14 +152,14 @@ export function getIndexPatternDatasource({ }) { const uiSettings = core.uiSettings; - const DATASOURCE_ID = 'indexpattern'; + const DATASOURCE_ID = 'formBased'; // Not stateful. State is persisted to the frame - const indexPatternDatasource: Datasource = { + const formBasedDatasource: Datasource = { id: DATASOURCE_ID, initialize( - persistedState?: IndexPatternPersistedState, + persistedState?: FormBasedPersistedState, references?: SavedObjectReference[], initialContext?: VisualizeFieldContext | VisualizeEditorContext, indexPatternRefs?: IndexPatternRef[], @@ -176,11 +176,11 @@ export function getIndexPatternDatasource({ }); }, - getPersistableState(state: IndexPatternPrivateState) { + getPersistableState(state: FormBasedPrivateState) { return extractReferences(state); }, - insertLayer(state: IndexPatternPrivateState, newLayerId: string) { + insertLayer(state: FormBasedPrivateState, newLayerId: string) { return { ...state, layers: { @@ -204,7 +204,7 @@ export function getIndexPatternDatasource({ }; }, - removeLayer(state: IndexPatternPrivateState, layerId: string) { + removeLayer(state: FormBasedPrivateState, layerId: string) { const newLayers = { ...state.layers }; delete newLayers[layerId]; @@ -214,7 +214,7 @@ export function getIndexPatternDatasource({ }; }, - clearLayer(state: IndexPatternPrivateState, layerId: string) { + clearLayer(state: FormBasedPrivateState, layerId: string) { return { ...state, layers: { @@ -224,7 +224,7 @@ export function getIndexPatternDatasource({ }; }, - getLayers(state: IndexPatternPrivateState) { + getLayers(state: FormBasedPrivateState) { return Object.keys(state?.layers); }, @@ -263,14 +263,26 @@ export function getIndexPatternDatasource({ }); }, + getSelectedFields(state) { + const fields: string[] = []; + Object.values(state?.layers)?.forEach((l) => { + const { columns } = l; + Object.values(columns).forEach((c) => { + if ('sourceField' in c) { + fields.push(c.sourceField); + } + }); + }); + return fields; + }, + toExpression: (state, layerId, indexPatterns) => toExpression(state, layerId, indexPatterns, uiSettings), - renderDataPanel( - domElement: Element, - props: DatasourceDataPanelProps - ) { + renderDataPanel(domElement: Element, props: DatasourceDataPanelProps) { const { onChangeIndexPattern, ...otherProps } = props; + const layerFields = formBasedDatasource?.getSelectedFields?.(props.state); + render( @@ -285,7 +297,7 @@ export function getIndexPatternDatasource({ discover, }} > - @@ -303,7 +316,7 @@ export function getIndexPatternDatasource({ ); }, - uniqueLabels(state: IndexPatternPrivateState) { + uniqueLabels(state: FormBasedPrivateState) { const layers = state.layers; const columnLabelMap = {} as Record; const counts = {} as Record; @@ -342,9 +355,9 @@ export function getIndexPatternDatasource({ renderDimensionTrigger: ( domElement: Element, - props: DatasourceDimensionTriggerProps + props: DatasourceDimensionTriggerProps ) => { - const columnLabelMap = indexPatternDatasource.uniqueLabels(props.state); + const columnLabelMap = formBasedDatasource.uniqueLabels(props.state); render( @@ -361,10 +374,7 @@ export function getIndexPatternDatasource({ unifiedSearch, }} > - + , @@ -374,9 +384,9 @@ export function getIndexPatternDatasource({ renderDimensionEditor: ( domElement: Element, - props: DatasourceDimensionEditorProps + props: DatasourceDimensionEditorProps ) => { - const columnLabelMap = indexPatternDatasource.uniqueLabels(props.state); + const columnLabelMap = formBasedDatasource.uniqueLabels(props.state); render( @@ -394,7 +404,7 @@ export function getIndexPatternDatasource({ unifiedSearch, }} > - + props: DatasourceLayerPanelProps ) => { const { onChangeIndexPattern, ...otherProps } = props; render( @@ -445,7 +455,7 @@ export function getIndexPatternDatasource({ onDrop, getCustomWorkspaceRenderer: ( - state: IndexPatternPrivateState, + state: FormBasedPrivateState, dragging: DraggingIdentifier, indexPatterns: Record ) => { @@ -501,7 +511,7 @@ export function getIndexPatternDatasource({ onIndexPatternRename: (state, oldIndexPatternId, newIndexPatternId) => { return renameIndexPattern({ state, oldIndexPatternId, newIndexPatternId }); }, - getRenderEventCounters(state: IndexPatternPrivateState): string[] { + getRenderEventCounters(state: FormBasedPrivateState): string[] { const additionalEvents = { time_shift: false, filter: false, @@ -545,8 +555,8 @@ export function getIndexPatternDatasource({ }); }, - getPublicAPI({ state, layerId, indexPatterns }: PublicAPIProps) { - const columnLabelMap = indexPatternDatasource.uniqueLabels(state); + getPublicAPI({ state, layerId, indexPatterns }: PublicAPIProps) { + const columnLabelMap = formBasedDatasource.uniqueLabels(state); const layer = state.layers[layerId]; const visibleColumnIds = layer.columnOrder.filter((colId) => !isReferenced(layer, colId)); @@ -766,16 +776,16 @@ export function getIndexPatternDatasource({ ); }, isEqual: ( - persistableState1: IndexPatternPersistedState, + persistableState1: FormBasedPersistedState, references1: SavedObjectReference[], - persistableState2: IndexPatternPersistedState, + persistableState2: FormBasedPersistedState, references2: SavedObjectReference[] ) => isEqual( injectReferences(persistableState1, references1), injectReferences(persistableState2, references2) ), - getUsedDataView: (state: IndexPatternPrivateState, layerId?: string) => { + getUsedDataView: (state: FormBasedPrivateState, layerId?: string) => { if (!layerId) { return state.currentIndexPatternId; } @@ -786,7 +796,7 @@ export function getIndexPatternDatasource({ }, }; - return indexPatternDatasource; + return formBasedDatasource; } function blankLayer(indexPatternId: string) { diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.test.tsx b/x-pack/plugins/lens/public/datasources/form_based/form_based_suggestions.test.tsx similarity index 98% rename from x-pack/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.test.tsx rename to x-pack/plugins/lens/public/datasources/form_based/form_based_suggestions.test.tsx index 382c11bda545a..d7a544a723e04 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.test.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/form_based_suggestions.test.tsx @@ -12,16 +12,16 @@ import type { StaticValueColumn, CountColumn, } from '@kbn/visualizations-plugin/common/convert_to_lens'; -import { DatasourceSuggestion } from '../types'; -import { generateId } from '../id_generator'; -import type { IndexPatternPrivateState } from './types'; +import { DatasourceSuggestion } from '../../types'; +import { generateId } from '../../id_generator'; +import type { FormBasedPrivateState } from './types'; import { getDatasourceSuggestionsForField, getDatasourceSuggestionsFromCurrentState, getDatasourceSuggestionsForVisualizeField, getDatasourceSuggestionsForVisualizeCharts, IndexPatternSuggestion, -} from './indexpattern_suggestions'; +} from './form_based_suggestions'; import { documentField } from './document_field'; import { getFieldByNameFactory } from './pure_helpers'; import { isEqual } from 'lodash'; @@ -33,7 +33,7 @@ import { } from './operations/definitions'; jest.mock('./loader'); -jest.mock('../id_generator'); +jest.mock('../../id_generator'); const fieldsOne = [ { @@ -171,7 +171,7 @@ const expectedIndexPatterns = { }, }; -function testInitialState(): IndexPatternPrivateState { +function testInitialState(): FormBasedPrivateState { return { currentIndexPatternId: '1', layers: { @@ -206,7 +206,7 @@ function getSuggestionSubset( ): Array> { return suggestions.map((s) => { const newSuggestion = { ...s } as Omit & { - state?: IndexPatternPrivateState; + state?: FormBasedPrivateState; }; delete newSuggestion.state; return newSuggestion; @@ -385,7 +385,7 @@ describe('IndexPattern Data Source suggestions', () => { }); it('should make a metric suggestion for a number field if there is no time field', async () => { - const state: IndexPatternPrivateState = { + const state: FormBasedPrivateState = { currentIndexPatternId: '1', layers: { first: { @@ -628,7 +628,7 @@ describe('IndexPattern Data Source suggestions', () => { }); it('should make a metric suggestion for a number field if there is no time field', async () => { - const state: IndexPatternPrivateState = { + const state: FormBasedPrivateState = { currentIndexPatternId: '1', layers: { previousLayer: { @@ -764,7 +764,7 @@ describe('IndexPattern Data Source suggestions', () => { }); describe('suggesting extensions to non-empty tables', () => { - function stateWithNonEmptyTables(): IndexPatternPrivateState { + function stateWithNonEmptyTables(): FormBasedPrivateState { const state = testInitialState(); return { @@ -1036,7 +1036,7 @@ describe('IndexPattern Data Source suggestions', () => { it('adds a metric column on a number field if no other metrics set', () => { (generateId as jest.Mock).mockReturnValue('newid'); const initialState = stateWithNonEmptyTables(); - const modifiedState: IndexPatternPrivateState = { + const modifiedState: FormBasedPrivateState = { ...initialState, layers: { ...initialState.layers, @@ -1138,7 +1138,7 @@ describe('IndexPattern Data Source suggestions', () => { it('skips duplicates when the document-specific field is already in use', () => { const initialState = stateWithNonEmptyTables(); - const modifiedState: IndexPatternPrivateState = { + const modifiedState: FormBasedPrivateState = { ...initialState, layers: { ...initialState.layers, @@ -1170,7 +1170,7 @@ describe('IndexPattern Data Source suggestions', () => { it('hides any referenced metrics when adding new metrics', () => { (generateId as jest.Mock).mockReturnValue('newid'); const initialState = stateWithNonEmptyTables(); - const modifiedState: IndexPatternPrivateState = { + const modifiedState: FormBasedPrivateState = { ...initialState, layers: { currentLayer: { @@ -1239,7 +1239,7 @@ describe('IndexPattern Data Source suggestions', () => { it('makes a suggestion to extending from an invalid state with a new metric', () => { (generateId as jest.Mock).mockReturnValue('newid'); const initialState = stateWithNonEmptyTables(); - const modifiedState: IndexPatternPrivateState = { + const modifiedState: FormBasedPrivateState = { ...initialState, layers: { currentLayer: { @@ -1306,7 +1306,7 @@ describe('IndexPattern Data Source suggestions', () => { (generateId as jest.Mock).mockReturnValue('newid'); const initialState = stateWithNonEmptyTables(); - const modifiedState: IndexPatternPrivateState = { + const modifiedState: FormBasedPrivateState = { ...initialState, layers: { referenceLineLayer: { @@ -1394,7 +1394,7 @@ describe('IndexPattern Data Source suggestions', () => { }); describe('finding the layer that is using the current index pattern', () => { - function stateWithCurrentIndexPattern(): IndexPatternPrivateState { + function stateWithCurrentIndexPattern(): FormBasedPrivateState { const state = testInitialState(); return { @@ -2140,7 +2140,7 @@ describe('IndexPattern Data Source suggestions', () => { it('returns a single suggestion containing the current columns for each layer', async () => { const initialState = testInitialState(); - const state: IndexPatternPrivateState = { + const state: FormBasedPrivateState = { ...initialState, layers: { ...initialState.layers, @@ -2233,7 +2233,7 @@ describe('IndexPattern Data Source suggestions', () => { it('returns a metric over time for single metric tables', async () => { const initialState = testInitialState(); - const state: IndexPatternPrivateState = { + const state: FormBasedPrivateState = { ...initialState, layers: { first: { @@ -2296,7 +2296,7 @@ describe('IndexPattern Data Source suggestions', () => { it('adds date histogram over default time field for tables without time dimension', async () => { const initialState = testInitialState(); - const state: IndexPatternPrivateState = { + const state: FormBasedPrivateState = { ...initialState, layers: { first: { @@ -2385,7 +2385,7 @@ describe('IndexPattern Data Source suggestions', () => { it('adds date histogram over default time field for tables without time dimension and a referenceLine', async () => { const initialState = testInitialState(); - const state: IndexPatternPrivateState = { + const state: FormBasedPrivateState = { ...initialState, layers: { first: { @@ -2495,7 +2495,7 @@ describe('IndexPattern Data Source suggestions', () => { it('does not create an over time suggestion if tables with numeric buckets with time dimension', async () => { const initialState = testInitialState(); - const state: IndexPatternPrivateState = { + const state: FormBasedPrivateState = { ...initialState, layers: { first: { @@ -2543,7 +2543,7 @@ describe('IndexPattern Data Source suggestions', () => { it('adds date histogram over default time field for custom range intervals', async () => { const initialState = testInitialState(); - const state: IndexPatternPrivateState = { + const state: FormBasedPrivateState = { ...initialState, layers: { first: { @@ -2630,7 +2630,7 @@ describe('IndexPattern Data Source suggestions', () => { it('does not create an over time suggestion if there is no default time field', async () => { const initialState = testInitialState(); - const state: IndexPatternPrivateState = { + const state: FormBasedPrivateState = { ...initialState, layers: { first: { @@ -2667,7 +2667,7 @@ describe('IndexPattern Data Source suggestions', () => { it('should not propose an over time suggestion if there are multiple bucket dimensions', () => { const initialState = testInitialState(); - const state: IndexPatternPrivateState = { + const state: FormBasedPrivateState = { ...initialState, layers: { first: { @@ -2751,7 +2751,7 @@ describe('IndexPattern Data Source suggestions', () => { searchable: true, }, ]; - const state: IndexPatternPrivateState = { + const state: FormBasedPrivateState = { currentIndexPatternId: '1', layers: { first: { @@ -2858,7 +2858,7 @@ describe('IndexPattern Data Source suggestions', () => { it('returns an only metric version of a given table, but does not include current state as reduced', () => { const initialState = testInitialState(); - const state: IndexPatternPrivateState = { + const state: FormBasedPrivateState = { currentIndexPatternId: '1', layers: { first: { @@ -2966,7 +2966,7 @@ describe('IndexPattern Data Source suggestions', () => { it('returns an alternative metric for an only-metric table', () => { const initialState = testInitialState(); - const state: IndexPatternPrivateState = { + const state: FormBasedPrivateState = { currentIndexPatternId: '1', layers: { first: { @@ -3032,7 +3032,7 @@ describe('IndexPattern Data Source suggestions', () => { it('contains a reordering suggestion when there are exactly 2 buckets', () => { const initialState = testInitialState(); - const state: IndexPatternPrivateState = { + const state: FormBasedPrivateState = { currentIndexPatternId: '1', layers: { first: { @@ -3084,7 +3084,7 @@ describe('IndexPattern Data Source suggestions', () => { it('will generate suggestions even if there are errors from missing fields', () => { const initialState = testInitialState(); - const state: IndexPatternPrivateState = { + const state: FormBasedPrivateState = { currentIndexPatternId: '1', layers: { first: { @@ -3148,7 +3148,7 @@ describe('IndexPattern Data Source suggestions', () => { describe('references', () => { it('will extend the table with a date when starting in an invalid state', () => { const initialState = testInitialState(); - const state: IndexPatternPrivateState = { + const state: FormBasedPrivateState = { ...initialState, layers: { ...initialState.layers, @@ -3237,7 +3237,7 @@ describe('IndexPattern Data Source suggestions', () => { it('will make an unchanged suggestion including incomplete references', () => { const initialState = testInitialState(); - const state: IndexPatternPrivateState = { + const state: FormBasedPrivateState = { ...initialState, layers: { ...initialState.layers, @@ -3327,7 +3327,7 @@ describe('IndexPattern Data Source suggestions', () => { it('will create reduced suggestions with all referenced children when handling references', () => { const initialState = testInitialState(); - const state: IndexPatternPrivateState = { + const state: FormBasedPrivateState = { ...initialState, layers: { ...initialState.layers, @@ -3473,7 +3473,7 @@ describe('IndexPattern Data Source suggestions', () => { it('will leave dangling references in place', () => { const initialState = testInitialState(); - const state: IndexPatternPrivateState = { + const state: FormBasedPrivateState = { ...initialState, layers: { ...initialState.layers, @@ -3521,7 +3521,7 @@ describe('IndexPattern Data Source suggestions', () => { it('will not suggest reduced tables if there is just a referenced top level metric', () => { const initialState = testInitialState(); - const state: IndexPatternPrivateState = { + const state: FormBasedPrivateState = { ...initialState, layers: { ...initialState.layers, @@ -3566,7 +3566,7 @@ describe('IndexPattern Data Source suggestions', () => { }); function isTableWithBucketColumns( - suggestion: DatasourceSuggestion, + suggestion: DatasourceSuggestion, columnIds: string[], numBuckets: number ) { @@ -3577,7 +3577,7 @@ function isTableWithBucketColumns( } function isTableWithMetricColumns( - suggestion: DatasourceSuggestion, + suggestion: DatasourceSuggestion, columnIds: string[] ) { expect(suggestion.table.isMultiRow).toEqual(false); diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.ts b/x-pack/plugins/lens/public/datasources/form_based/form_based_suggestions.ts similarity index 95% rename from x-pack/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.ts rename to x-pack/plugins/lens/public/datasources/form_based/form_based_suggestions.ts index 8503c369f4ec2..52008f10bcdeb 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.ts +++ b/x-pack/plugins/lens/public/datasources/form_based/form_based_suggestions.ts @@ -14,7 +14,7 @@ import type { AnyColumnWithSourceField, TermsColumn, } from '@kbn/visualizations-plugin/common/convert_to_lens'; -import { generateId } from '../id_generator'; +import { generateId } from '../../id_generator'; import type { DatasourceSuggestion, IndexPattern, @@ -22,8 +22,8 @@ import type { IndexPatternMap, TableChangeType, VisualizationDimensionGroupConfig, -} from '../types'; -import { columnToOperation } from './indexpattern'; +} from '../../types'; +import { columnToOperation } from './form_based'; import { insertNewColumn, replaceColumn, @@ -41,12 +41,12 @@ import { ColumnAdvancedParams, } from './operations'; import { hasField } from './pure_utils'; -import type { IndexPatternPrivateState, IndexPatternLayer } from './types'; +import type { FormBasedPrivateState, FormBasedLayer } from './types'; import { documentField } from './document_field'; import { OperationDefinition } from './operations/definitions'; import { insertOrReplaceFormulaColumn } from './operations/definitions/formula'; -export type IndexPatternSuggestion = DatasourceSuggestion; +export type IndexPatternSuggestion = DatasourceSuggestion; interface ColumnChange { op: OperationType; @@ -67,12 +67,12 @@ function buildSuggestion({ label, changeType, }: { - state: IndexPatternPrivateState; + state: FormBasedPrivateState; layerId: string; changeType: TableChangeType; - updatedLayer?: IndexPatternLayer; + updatedLayer?: FormBasedLayer; label?: string; -}): DatasourceSuggestion { +}): DatasourceSuggestion { const updatedState = updatedLayer ? { ...state, @@ -120,7 +120,7 @@ function buildSuggestion({ } export function getDatasourceSuggestionsForField( - state: IndexPatternPrivateState, + state: FormBasedPrivateState, indexPatternId: string, field: IndexPatternField, indexPatterns: IndexPatternMap, @@ -176,7 +176,7 @@ export function getDatasourceSuggestionsForField( // Called when the user navigates from Visualize editor to Lens export function getDatasourceSuggestionsForVisualizeCharts( - state: IndexPatternPrivateState, + state: FormBasedPrivateState, contextLayers: Layer[], indexPatterns: IndexPatternMap ): IndexPatternSuggestion[] { @@ -184,7 +184,7 @@ export function getDatasourceSuggestionsForVisualizeCharts( } function getEmptyLayersSuggestionsForVisualizeCharts( - state: IndexPatternPrivateState, + state: FormBasedPrivateState, contextLayers: Layer[], indexPatterns: IndexPatternMap ): IndexPatternSuggestion[] { @@ -280,7 +280,7 @@ function convertToColumnChange(columns: Layer['columns'], indexPattern: IndexPat ) { const orderColumn = column.params.orderAgg; const operationDefinition = operationDefinitionMap[orderColumn.operationType]; - const layer: IndexPatternLayer = { + const layer: FormBasedLayer = { indexPatternId: indexPattern.id, columns: {}, columnOrder: [], @@ -311,7 +311,7 @@ function createNewLayerWithMetricAggregationFromVizEditor( layer: Layer ) { const columns = convertToColumnChange(layer.columns, indexPattern); - let newLayer: IndexPatternLayer = { + let newLayer: FormBasedLayer = { indexPatternId: indexPattern.id, columns: {}, columnOrder: [], @@ -360,7 +360,7 @@ function createNewLayerWithMetricAggregationFromVizEditor( // Called when the user navigates from Discover to Lens (Visualize button) export function getDatasourceSuggestionsForVisualizeField( - state: IndexPatternPrivateState, + state: FormBasedPrivateState, indexPatternId: string, fieldName: string, indexPatterns: IndexPatternMap @@ -400,7 +400,7 @@ function getBucketOperation(field: IndexPatternField) { } function getExistingLayerSuggestionsForField( - state: IndexPatternPrivateState, + state: FormBasedPrivateState, layerId: string, field: IndexPatternField, indexPatterns: IndexPatternMap @@ -514,14 +514,14 @@ function getExistingLayerSuggestionsForField( } function getEmptyLayerSuggestionsForField( - state: IndexPatternPrivateState, + state: FormBasedPrivateState, layerId: string, indexPatternId: string, field: IndexPatternField, indexPatterns: IndexPatternMap ): IndexPatternSuggestion[] { const indexPattern = indexPatterns[indexPatternId]; - let newLayer: IndexPatternLayer | undefined; + let newLayer: FormBasedLayer | undefined; const bucketOperation = getBucketOperation(field); if (bucketOperation) { newLayer = createNewLayerWithBucketAggregation(indexPattern, field, bucketOperation); @@ -549,7 +549,7 @@ function createNewLayerWithBucketAggregation( indexPattern: IndexPattern, field: IndexPatternField, operation: OperationType -): IndexPatternLayer { +): FormBasedLayer { return insertNewColumn({ op: operation, layer: insertNewColumn({ @@ -570,7 +570,7 @@ function createNewLayerWithBucketAggregation( function createNewLayerWithMetricAggregation( indexPattern: IndexPattern, field: IndexPatternField -): IndexPatternLayer | undefined { +): FormBasedLayer | undefined { const dateField = indexPattern.getFieldByName(indexPattern.timeFieldName!); const [metricOperation] = getMetricOperationTypes(field); if (!metricOperation) { @@ -595,10 +595,10 @@ function createNewLayerWithMetricAggregation( } export function getDatasourceSuggestionsFromCurrentState( - state: IndexPatternPrivateState, + state: FormBasedPrivateState, indexPatterns: IndexPatternMap, filterLayers: (layerId: string) => boolean = () => true -): Array> { +): Array> { const layers = Object.entries(state.layers || {}).filter(([layerId]) => filterLayers(layerId)); if (layers.length > 1) { @@ -658,7 +658,7 @@ export function getDatasourceSuggestionsFromCurrentState( buckets.length === 1 && buckets.some((columnId) => layer.columns[columnId].dataType === 'number'); - const suggestions: Array> = []; + const suggestions: Array> = []; // Always suggest an unchanged table, including during invalid states suggestions.push( @@ -708,7 +708,7 @@ export function getDatasourceSuggestionsFromCurrentState( } function createChangedNestingSuggestion( - state: IndexPatternPrivateState, + state: FormBasedPrivateState, layerId: string, indexPatterns: IndexPatternMap ) { @@ -739,7 +739,7 @@ function createChangedNestingSuggestion( function createMetricSuggestion( indexPattern: IndexPattern, layerId: string, - state: IndexPatternPrivateState, + state: FormBasedPrivateState, field: IndexPatternField ) { const [operation] = getMetricOperationTypes(field); @@ -781,10 +781,10 @@ function getNestedTitle([outerBucketLabel, innerBucketLabel]: string[]) { function createAlternativeMetricSuggestions( indexPattern: IndexPattern, layerId: string, - state: IndexPatternPrivateState + state: FormBasedPrivateState ) { const layer = state.layers[layerId]; - const suggestions: Array> = []; + const suggestions: Array> = []; const topLevelMetricColumns = layer.columnOrder.filter( (columnId) => !isReferenced(layer, columnId) ); @@ -826,7 +826,7 @@ function createAlternativeMetricSuggestions( } function createSuggestionWithDefaultDateHistogram( - state: IndexPatternPrivateState, + state: FormBasedPrivateState, layerId: string, timeField: IndexPatternField, indexPatterns: IndexPatternMap @@ -852,7 +852,7 @@ function createSuggestionWithDefaultDateHistogram( }); } -function createSimplifiedTableSuggestions(state: IndexPatternPrivateState, layerId: string) { +function createSimplifiedTableSuggestions(state: FormBasedPrivateState, layerId: string) { const layer = state.layers[layerId]; const [availableBucketedColumns, availableMetricColumns] = partition( @@ -916,7 +916,7 @@ function createSimplifiedTableSuggestions(state: IndexPatternPrivateState, layer }); } -function getMetricSuggestionTitle(layer: IndexPatternLayer, onlySimpleMetric: boolean) { +function getMetricSuggestionTitle(layer: FormBasedLayer, onlySimpleMetric: boolean) { const { operationType, label } = layer.columns[layer.columnOrder[0]]; return i18n.translate('xpack.lens.indexpattern.suggestions.overallLabel', { defaultMessage: '{operation} overall', diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/help_popover.scss b/x-pack/plugins/lens/public/datasources/form_based/help_popover.scss similarity index 100% rename from x-pack/plugins/lens/public/indexpattern_datasource/help_popover.scss rename to x-pack/plugins/lens/public/datasources/form_based/help_popover.scss diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/help_popover.tsx b/x-pack/plugins/lens/public/datasources/form_based/help_popover.tsx similarity index 100% rename from x-pack/plugins/lens/public/indexpattern_datasource/help_popover.tsx rename to x-pack/plugins/lens/public/datasources/form_based/help_popover.tsx diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/index.ts b/x-pack/plugins/lens/public/datasources/form_based/index.ts similarity index 84% rename from x-pack/plugins/lens/public/indexpattern_datasource/index.ts rename to x-pack/plugins/lens/public/datasources/form_based/index.ts index 6b1b052c90b14..3b1f62829fa46 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/index.ts +++ b/x-pack/plugins/lens/public/datasources/form_based/index.ts @@ -16,11 +16,11 @@ import type { IndexPatternFieldEditorStart } from '@kbn/data-view-field-editor-p import type { DataPublicPluginSetup, DataPublicPluginStart } from '@kbn/data-plugin/public'; import type { UiActionsStart } from '@kbn/ui-actions-plugin/public'; import type { FieldFormatsStart, FieldFormatsSetup } from '@kbn/field-formats-plugin/public'; -import type { EditorFrameSetup } from '../types'; +import type { EditorFrameSetup } from '../../types'; export type { PersistedIndexPatternLayer, FormulaPublicApi } from './types'; -export interface IndexPatternDatasourceSetupPlugins { +export interface FormBasedDatasourceSetupPlugins { expressions: ExpressionsSetup; fieldFormats: FieldFormatsSetup; data: DataPublicPluginSetup; @@ -28,7 +28,7 @@ export interface IndexPatternDatasourceSetupPlugins { charts: ChartsPluginSetup; } -export interface IndexPatternDatasourceStartPlugins { +export interface FormBasedDatasourceStartPlugins { data: DataPublicPluginStart; unifiedSearch: UnifiedSearchPublicPluginStart; discover?: DiscoverStart; @@ -38,19 +38,19 @@ export interface IndexPatternDatasourceStartPlugins { uiActions: UiActionsStart; } -export class IndexPatternDatasource { +export class FormBasedDatasource { setup( - core: CoreSetup, + core: CoreSetup, { fieldFormats: fieldFormatsSetup, expressions, editorFrame, charts, - }: IndexPatternDatasourceSetupPlugins + }: FormBasedDatasourceSetupPlugins ) { editorFrame.registerDatasource(async () => { - const { getIndexPatternDatasource, getSuffixFormatter, suffixFormatterId } = await import( - '../async_services' + const { getFormBasedDatasource, getSuffixFormatter, suffixFormatterId } = await import( + '../../async_services' ); if (!fieldFormatsSetup.has(suffixFormatterId)) { @@ -67,7 +67,7 @@ export class IndexPatternDatasource { { dataViewFieldEditor, uiActions, data, fieldFormats, dataViews, unifiedSearch, discover }, ] = await core.getStartServices(); - return getIndexPatternDatasource({ + return getFormBasedDatasource({ core: coreStart, fieldFormats, storage: new Storage(localStorage), diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/layerpanel.test.tsx b/x-pack/plugins/lens/public/datasources/form_based/layerpanel.test.tsx similarity index 95% rename from x-pack/plugins/lens/public/indexpattern_datasource/layerpanel.test.tsx rename to x-pack/plugins/lens/public/datasources/form_based/layerpanel.test.tsx index 7dde02c6c2b61..defc505f1d9e1 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/layerpanel.test.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/layerpanel.test.tsx @@ -6,13 +6,13 @@ */ import React, { MouseEvent } from 'react'; -import { IndexPatternPrivateState } from './types'; -import { IndexPatternLayerPanelProps, LayerPanel } from './layerpanel'; +import { FormBasedPrivateState } from './types'; +import { FormBasedLayerPanelProps, LayerPanel } from './layerpanel'; import { shallowWithIntl as shallow } from '@kbn/test-jest-helpers'; import { ShallowWrapper } from 'enzyme'; import { EuiSelectable } from '@elastic/eui'; import { DataViewsList } from '@kbn/unified-search-plugin/public'; -import { ChangeIndexPattern } from '../shared_components/dataview_picker/dataview_picker'; +import { ChangeIndexPattern } from '../../shared_components/dataview_picker/dataview_picker'; import { getFieldByNameFactory } from './pure_helpers'; import { TermsIndexPatternColumn } from './operations'; @@ -135,7 +135,7 @@ const fieldsThree = [ }, ]; -const initialState: IndexPatternPrivateState = { +const initialState: FormBasedPrivateState = { currentIndexPatternId: '1', layers: { first: { @@ -168,7 +168,7 @@ const initialState: IndexPatternPrivateState = { }, }; describe('Layer Data Panel', () => { - let defaultProps: IndexPatternLayerPanelProps; + let defaultProps: FormBasedLayerPanelProps; beforeEach(() => { defaultProps = { diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/layerpanel.tsx b/x-pack/plugins/lens/public/datasources/form_based/layerpanel.tsx similarity index 78% rename from x-pack/plugins/lens/public/indexpattern_datasource/layerpanel.tsx rename to x-pack/plugins/lens/public/datasources/form_based/layerpanel.tsx index 9824f70eeddfc..c18b79b28c58c 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/layerpanel.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/layerpanel.tsx @@ -8,13 +8,12 @@ import React from 'react'; import { I18nProvider } from '@kbn/i18n-react'; import { i18n } from '@kbn/i18n'; -import { DatasourceLayerPanelProps } from '../types'; -import { IndexPatternPrivateState } from './types'; -import { ChangeIndexPattern } from '../shared_components/dataview_picker/dataview_picker'; +import { DatasourceLayerPanelProps } from '../../types'; +import { FormBasedPrivateState } from './types'; +import { ChangeIndexPattern } from '../../shared_components/dataview_picker/dataview_picker'; -export interface IndexPatternLayerPanelProps - extends DatasourceLayerPanelProps { - state: IndexPatternPrivateState; +export interface FormBasedLayerPanelProps extends DatasourceLayerPanelProps { + state: FormBasedPrivateState; onChangeIndexPattern: (newId: string) => void; } @@ -23,7 +22,7 @@ export function LayerPanel({ layerId, onChangeIndexPattern, dataViews, -}: IndexPatternLayerPanelProps) { +}: FormBasedLayerPanelProps) { const layer = state.layers[layerId]; const indexPattern = dataViews.indexPatterns[layer.indexPatternId]; diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/loader.test.ts b/x-pack/plugins/lens/public/datasources/form_based/loader.test.ts similarity index 96% rename from x-pack/plugins/lens/public/indexpattern_datasource/loader.test.ts rename to x-pack/plugins/lens/public/datasources/form_based/loader.test.ts index a3bc7a21143c4..896fbd0e6404f 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/loader.test.ts +++ b/x-pack/plugins/lens/public/datasources/form_based/loader.test.ts @@ -12,9 +12,9 @@ import { extractReferences, injectReferences, } from './loader'; -import { IndexPatternPersistedState, IndexPatternPrivateState } from './types'; +import { FormBasedPersistedState, FormBasedPrivateState } from './types'; import { DateHistogramIndexPatternColumn, TermsIndexPatternColumn } from './operations'; -import { sampleIndexPatterns } from '../data_views_service/mocks'; +import { sampleIndexPatterns } from '../../data_views_service/mocks'; const createMockStorage = (lastData?: Record) => { return { @@ -141,7 +141,7 @@ describe('loader', () => { }); it('should initialize all the embeddable references without local storage', () => { - const savedState: IndexPatternPersistedState = { + const savedState: FormBasedPersistedState = { layers: { layerb: { columnOrder: ['col1', 'col2'], @@ -189,7 +189,7 @@ describe('loader', () => { }); it('should initialize from saved state', () => { - const savedState: IndexPatternPersistedState = { + const savedState: FormBasedPersistedState = { layers: { layerb: { columnOrder: ['col1', 'col2'], @@ -242,7 +242,7 @@ describe('loader', () => { }); describe('saved object references', () => { - const state: IndexPatternPrivateState = { + const state: FormBasedPrivateState = { currentIndexPatternId: 'b', layers: { a: { @@ -300,7 +300,7 @@ describe('loader', () => { describe('changeIndexPattern', () => { it('sets the given indexpattern as current', () => { - const state: IndexPatternPrivateState = { + const state: FormBasedPrivateState = { currentIndexPatternId: '2', layers: {}, }; @@ -324,7 +324,7 @@ describe('loader', () => { }); it('should update an empty layer on indexpattern change', () => { - const state: IndexPatternPrivateState = { + const state: FormBasedPrivateState = { currentIndexPatternId: '2', layers: { layerId: { columnOrder: [], columns: {}, indexPatternId: '2' } }, }; @@ -345,7 +345,7 @@ describe('loader', () => { }); it('should keep layer indexpattern on change if not empty', () => { - const state: IndexPatternPrivateState = { + const state: FormBasedPrivateState = { currentIndexPatternId: '2', layers: { layerId: { @@ -402,7 +402,7 @@ describe('loader', () => { describe('changeLayerIndexPattern', () => { it('loads the index pattern and then changes the specified layer', async () => { - const state: IndexPatternPrivateState = { + const state: FormBasedPrivateState = { currentIndexPatternId: '1', layers: { l0: { diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/loader.ts b/x-pack/plugins/lens/public/datasources/form_based/loader.ts similarity index 89% rename from x-pack/plugins/lens/public/indexpattern_datasource/loader.ts rename to x-pack/plugins/lens/public/datasources/form_based/loader.ts index e26231995578e..6aa021a6f363f 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/loader.ts +++ b/x-pack/plugins/lens/public/datasources/form_based/loader.ts @@ -17,12 +17,12 @@ import { UiActionsStart, VisualizeFieldContext, } from '@kbn/ui-actions-plugin/public'; -import type { VisualizeEditorContext } from '../types'; -import { IndexPatternPersistedState, IndexPatternPrivateState, IndexPatternLayer } from './types'; +import type { VisualizeEditorContext } from '../../types'; +import { FormBasedPersistedState, FormBasedPrivateState, FormBasedLayer } from './types'; import { memoizedGetAvailableOperationsByMetadata, updateLayerIndexPattern } from './operations'; -import { readFromStorage, writeToStorage } from '../settings_storage'; -import type { IndexPattern, IndexPatternRef } from '../types'; +import { readFromStorage, writeToStorage } from '../../settings_storage'; +import type { IndexPattern, IndexPatternRef } from '../../types'; export function onRefreshIndexPattern() { if (memoizedGetAvailableOperationsByMetadata.cache.clear) { @@ -47,9 +47,9 @@ function getLayerReferenceName(layerId: string) { return `indexpattern-datasource-layer-${layerId}`; } -export function extractReferences({ layers }: IndexPatternPrivateState) { +export function extractReferences({ layers }: FormBasedPrivateState) { const savedObjectReferences: SavedObjectReference[] = []; - const persistableState: IndexPatternPersistedState = { + const persistableState: FormBasedPersistedState = { layers: {}, }; Object.entries(layers).forEach(([layerId, { indexPatternId, ...persistableLayer }]) => { @@ -64,10 +64,10 @@ export function extractReferences({ layers }: IndexPatternPrivateState) { } export function injectReferences( - state: IndexPatternPersistedState, + state: FormBasedPersistedState, references: SavedObjectReference[] ) { - const layers: Record = {}; + const layers: Record = {}; Object.entries(state.layers).forEach(([layerId, persistedLayer]) => { layers[layerId] = { ...persistedLayer, @@ -83,7 +83,7 @@ function createStateFromPersisted({ persistedState, references, }: { - persistedState?: IndexPatternPersistedState; + persistedState?: FormBasedPersistedState; references?: SavedObjectReference[]; }) { return persistedState && references ? injectReferences(persistedState, references) : undefined; @@ -97,7 +97,7 @@ function getUsedIndexPatterns({ defaultIndexPatternId, }: { state?: { - layers: Record; + layers: Record; }; defaultIndexPatternId?: string; storage: IStorageWrapper; @@ -139,14 +139,14 @@ export function loadInitialState({ indexPatternRefs = [], indexPatterns = {}, }: { - persistedState?: IndexPatternPersistedState; + persistedState?: FormBasedPersistedState; references?: SavedObjectReference[]; defaultIndexPatternId?: string; storage: IStorageWrapper; initialContext?: VisualizeFieldContext | VisualizeEditorContext; indexPatternRefs?: IndexPatternRef[]; indexPatterns?: Record; -}): IndexPatternPrivateState { +}): FormBasedPrivateState { const state = createStateFromPersisted({ persistedState, references }); const { usedPatterns, allIndexPatternIds: indexPatternIds } = getUsedIndexPatterns({ state, @@ -186,7 +186,7 @@ export function changeIndexPattern({ indexPatterns, }: { indexPatternId: string; - state: IndexPatternPrivateState; + state: FormBasedPrivateState; storage: IStorageWrapper; indexPatterns: Record; }) { @@ -209,7 +209,7 @@ export function renameIndexPattern({ }: { oldIndexPatternId: string; newIndexPatternId: string; - state: IndexPatternPrivateState; + state: FormBasedPrivateState; }) { return { ...state, @@ -231,7 +231,7 @@ export function triggerActionOnIndexPatternChange({ }: { indexPatternId: string; layerId: string; - state: IndexPatternPrivateState; + state: FormBasedPrivateState; uiActions: UiActionsStart; }) { const fromDataView = state.layers[layerId]?.indexPatternId; @@ -260,7 +260,7 @@ export function changeLayerIndexPattern({ }: { indexPatternId: string; layerId: string; - state: IndexPatternPrivateState; + state: FormBasedPrivateState; replaceIfPossible?: boolean; storage: IStorageWrapper; indexPatterns: Record; @@ -276,7 +276,7 @@ export function changeLayerIndexPattern({ }; } -function isSingleEmptyLayer(layerMap: IndexPatternPrivateState['layers']) { +function isSingleEmptyLayer(layerMap: FormBasedPrivateState['layers']) { const layers = Object.values(layerMap); return layers.length === 1 && layers[0].columnOrder.length === 0; } diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/mocks.ts b/x-pack/plugins/lens/public/datasources/form_based/mocks.ts similarity index 97% rename from x-pack/plugins/lens/public/indexpattern_datasource/mocks.ts rename to x-pack/plugins/lens/public/datasources/form_based/mocks.ts index 7cd3639547e14..c2a85fbf0bac4 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/mocks.ts +++ b/x-pack/plugins/lens/public/datasources/form_based/mocks.ts @@ -5,9 +5,9 @@ * 2.0. */ -import { DragContextState } from '../drag_drop'; +import { DragContextState } from '../../drag_drop'; import { getFieldByNameFactory } from './pure_helpers'; -import type { IndexPattern, IndexPatternField } from '../types'; +import type { IndexPattern, IndexPatternField } from '../../types'; export const createMockedIndexPattern = (someProps?: Partial): IndexPattern => { const fields = [ diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/no_fields_callout.test.tsx b/x-pack/plugins/lens/public/datasources/form_based/no_fields_callout.test.tsx similarity index 100% rename from x-pack/plugins/lens/public/indexpattern_datasource/no_fields_callout.test.tsx rename to x-pack/plugins/lens/public/datasources/form_based/no_fields_callout.test.tsx diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/no_fields_callout.tsx b/x-pack/plugins/lens/public/datasources/form_based/no_fields_callout.tsx similarity index 100% rename from x-pack/plugins/lens/public/indexpattern_datasource/no_fields_callout.tsx rename to x-pack/plugins/lens/public/datasources/form_based/no_fields_callout.tsx diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/__mocks__/index.ts b/x-pack/plugins/lens/public/datasources/form_based/operations/__mocks__/index.ts similarity index 100% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/__mocks__/index.ts rename to x-pack/plugins/lens/public/datasources/form_based/operations/__mocks__/index.ts diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions.test.ts b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions.test.ts similarity index 97% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions.test.ts rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions.test.ts index c9b3ae608ec76..3dc58b7f1ef6c 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions.test.ts +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions.test.ts @@ -18,8 +18,8 @@ import { } from './definitions'; import { getFieldByNameFactory } from '../pure_helpers'; import { documentField } from '../document_field'; -import { IndexPatternLayer } from '../types'; -import { IndexPattern, IndexPatternField } from '../../types'; +import { FormBasedLayer } from '../types'; +import { IndexPattern, IndexPatternField } from '../../../types'; import { GenericIndexPatternColumn } from '.'; import { DateHistogramIndexPatternColumn } from './definitions/date_histogram'; @@ -83,7 +83,7 @@ const indexPattern = { const baseColumnArgs: { previousColumn: GenericIndexPatternColumn; indexPattern: IndexPattern; - layer: IndexPatternLayer; + layer: FormBasedLayer; field: IndexPatternField; } = { previousColumn: { @@ -105,7 +105,7 @@ const baseColumnArgs: { field: indexPattern.fields[2], }; -const layer: IndexPatternLayer = { +const layer: FormBasedLayer = { indexPatternId: '1', columnOrder: ['date', 'metric', 'ref'], columns: { diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/counter_rate.tsx b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/calculations/counter_rate.tsx similarity index 97% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/counter_rate.tsx rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/calculations/counter_rate.tsx index f2c421946bafb..3b89de8e94c51 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/counter_rate.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/calculations/counter_rate.tsx @@ -7,7 +7,7 @@ import { i18n } from '@kbn/i18n'; import { FormattedIndexPatternColumn, ReferenceBasedIndexPatternColumn } from '../column_types'; -import { IndexPatternLayer } from '../../../types'; +import { FormBasedLayer } from '../../../types'; import { buildLabelFunction, getErrorsForDateReference, @@ -106,7 +106,7 @@ export const counterRateOperation: OperationDefinition< isTransferable: (column, newIndexPattern) => { return hasDateField(newIndexPattern); }, - getErrorMessage: (layer: IndexPatternLayer, columnId: string) => { + getErrorMessage: (layer: FormBasedLayer, columnId: string) => { return combineErrorMessages([ getErrorsForDateReference( layer, diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/cumulative_sum.tsx b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/calculations/cumulative_sum.tsx similarity index 96% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/cumulative_sum.tsx rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/calculations/cumulative_sum.tsx index 67260672fa66d..339f5e4bc4003 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/cumulative_sum.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/calculations/cumulative_sum.tsx @@ -7,7 +7,7 @@ import { i18n } from '@kbn/i18n'; import { FormattedIndexPatternColumn, ReferenceBasedIndexPatternColumn } from '../column_types'; -import { IndexPatternLayer } from '../../../types'; +import { FormBasedLayer } from '../../../types'; import { checkForDateHistogram, getErrorsForDateReference, @@ -19,7 +19,7 @@ import { import { OperationDefinition } from '..'; import { getFormatFromPreviousColumn, getFilter, combineErrorMessages } from '../helpers'; import { getDisallowedPreviousShiftMessage } from '../../../time_shift_utils'; -import { DOCUMENT_FIELD_NAME } from '../../../../../common'; +import { DOCUMENT_FIELD_NAME } from '../../../../../../common'; const ofName = buildLabelFunction((name?: string) => { return i18n.translate('xpack.lens.indexPattern.cumulativeSumOf', { @@ -106,7 +106,7 @@ export const cumulativeSumOperation: OperationDefinition< isTransferable: () => { return true; }, - getErrorMessage: (layer: IndexPatternLayer, columnId: string) => { + getErrorMessage: (layer: FormBasedLayer, columnId: string) => { return combineErrorMessages([ getErrorsForDateReference( layer, diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/differences.tsx b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/calculations/differences.tsx similarity index 97% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/differences.tsx rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/calculations/differences.tsx index 1d76667654cb3..f2c379b5af5c1 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/differences.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/calculations/differences.tsx @@ -7,7 +7,7 @@ import { i18n } from '@kbn/i18n'; import { FormattedIndexPatternColumn, ReferenceBasedIndexPatternColumn } from '../column_types'; -import { IndexPatternLayer } from '../../../types'; +import { FormBasedLayer } from '../../../types'; import { buildLabelFunction, checkForDateHistogram, @@ -92,7 +92,7 @@ export const derivativeOperation: OperationDefinition< isTransferable: (column, newIndexPattern) => { return hasDateField(newIndexPattern); }, - getErrorMessage: (layer: IndexPatternLayer, columnId: string) => { + getErrorMessage: (layer: FormBasedLayer, columnId: string) => { return combineErrorMessages([ getErrorsForDateReference( layer, diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/index.ts b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/calculations/index.ts similarity index 100% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/index.ts rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/calculations/index.ts diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/moving_average.tsx b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/calculations/moving_average.tsx similarity index 97% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/moving_average.tsx rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/calculations/moving_average.tsx index 0fbdd96153a0f..d7b46d09c0f1e 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/moving_average.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/calculations/moving_average.tsx @@ -9,9 +9,9 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import React, { useState } from 'react'; import { EuiFieldNumber, EuiFormRow } from '@elastic/eui'; -import { useDebounceWithOptions } from '../../../../shared_components'; +import { useDebounceWithOptions } from '../../../../../shared_components'; import { FormattedIndexPatternColumn, ReferenceBasedIndexPatternColumn } from '../column_types'; -import { IndexPatternLayer } from '../../../types'; +import { FormBasedLayer } from '../../../types'; import { buildLabelFunction, checkForDateHistogram, @@ -114,7 +114,7 @@ export const movingAverageOperation: OperationDefinition< isTransferable: (column, newIndexPattern) => { return hasDateField(newIndexPattern); }, - getErrorMessage: (layer: IndexPatternLayer, columnId: string) => { + getErrorMessage: (layer: FormBasedLayer, columnId: string) => { return combineErrorMessages([ getErrorsForDateReference( layer, diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/overall_metric.test.ts b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/calculations/overall_metric.test.ts similarity index 93% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/overall_metric.test.ts rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/calculations/overall_metric.test.ts index 178a98074ad8a..901600e90f034 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/overall_metric.test.ts +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/calculations/overall_metric.test.ts @@ -6,7 +6,7 @@ */ import { createMockedIndexPattern } from '../../../mocks'; -import type { IndexPatternLayer } from '../../../types'; +import type { FormBasedLayer } from '../../../types'; import { overallAverageOperation, overallMaxOperation, @@ -16,7 +16,7 @@ import { describe('overall_metric', () => { const indexPattern = createMockedIndexPattern(); - let layer: IndexPatternLayer; + let layer: FormBasedLayer; beforeEach(() => { layer = { diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/overall_metric.tsx b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/calculations/overall_metric.tsx similarity index 100% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/overall_metric.tsx rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/calculations/overall_metric.tsx diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/time_scale.tsx b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/calculations/time_scale.tsx similarity index 97% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/time_scale.tsx rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/calculations/time_scale.tsx index 68df34650794d..59eb7fea46233 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/time_scale.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/calculations/time_scale.tsx @@ -13,7 +13,7 @@ import type { import { getErrorsForDateReference } from './utils'; import type { OperationDefinition } from '..'; import { combineErrorMessages, getFormatFromPreviousColumn } from '../helpers'; -import { IndexPatternLayer } from '../../../types'; +import { FormBasedLayer } from '../../../types'; import { getDisallowedPreviousShiftMessage } from '../../../time_shift_utils'; type OverallMetricIndexPatternColumn = FormattedIndexPatternColumn & @@ -101,7 +101,7 @@ export const timeScaleOperation: OperationDefinition { return true; }, - getErrorMessage: (layer: IndexPatternLayer, columnId: string) => { + getErrorMessage: (layer: FormBasedLayer, columnId: string) => { return combineErrorMessages([ getErrorsForDateReference( layer, diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/utils.test.ts b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/calculations/utils.test.ts similarity index 100% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/utils.test.ts rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/calculations/utils.test.ts diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/utils.ts b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/calculations/utils.ts similarity index 90% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/utils.ts rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/calculations/utils.ts index 5b33fb0717539..bac4a8940c689 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/utils.ts +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/calculations/utils.ts @@ -9,10 +9,10 @@ import { i18n } from '@kbn/i18n'; import type { AstFunction } from '@kbn/interpreter'; import memoizeOne from 'memoize-one'; import { LayerTypes } from '@kbn/expression-xy-plugin/public'; -import type { IndexPattern } from '../../../../types'; -import type { LayerType } from '../../../../../common'; -import type { TimeScaleUnit } from '../../../../../common/expressions'; -import type { IndexPatternLayer } from '../../../types'; +import type { IndexPattern } from '../../../../../types'; +import { LayerType } from '../../../../../../common'; +import type { TimeScaleUnit } from '../../../../../../common/expressions'; +import type { FormBasedLayer } from '../../../types'; import { adjustTimeScaleLabelSuffix } from '../../time_scale_utils'; import type { ReferenceBasedIndexPatternColumn } from '../column_types'; import { getManagedColumnsFrom, isColumnValidAsReference } from '../../layer_helpers'; @@ -49,7 +49,7 @@ export function checkForDataLayerType(layerType: LayerType, name: string) { /** * Checks whether the current layer includes a date histogram and returns an error otherwise */ -export function checkForDateHistogram(layer: IndexPatternLayer, name: string) { +export function checkForDateHistogram(layer: FormBasedLayer, name: string) { const buckets = layer.columnOrder.filter((colId) => layer.columns[colId].isBucketed); const hasDateHistogram = buckets.some( (colId) => layer.columns[colId].operationType === 'date_histogram' @@ -68,7 +68,7 @@ export function checkForDateHistogram(layer: IndexPatternLayer, name: string) { ]; } -const getFullyManagedColumnIds = memoizeOne((layer: IndexPatternLayer) => { +const getFullyManagedColumnIds = memoizeOne((layer: FormBasedLayer) => { const managedColumnIds = new Set(); Object.entries(layer.columns).forEach(([id, column]) => { if ( @@ -85,7 +85,7 @@ const getFullyManagedColumnIds = memoizeOne((layer: IndexPatternLayer) => { return managedColumnIds; }); -export function checkReferences(layer: IndexPatternLayer, columnId: string) { +export function checkReferences(layer: FormBasedLayer, columnId: string) { const column = layer.columns[columnId] as ReferenceBasedIndexPatternColumn; const errors: string[] = []; @@ -128,11 +128,7 @@ export function checkReferences(layer: IndexPatternLayer, columnId: string) { return errors.length ? errors : undefined; } -export function getErrorsForDateReference( - layer: IndexPatternLayer, - columnId: string, - name: string -) { +export function getErrorsForDateReference(layer: FormBasedLayer, columnId: string, name: string) { const dateErrors = checkForDateHistogram(layer, name) ?? []; const referenceErrors = checkReferences(layer, columnId) ?? []; if (dateErrors.length || referenceErrors.length) { @@ -149,7 +145,7 @@ export function hasDateField(indexPattern: IndexPattern) { * Creates an expression ast for a date based operation (cumulative sum, derivative, moving average, counter rate) */ export function dateBasedOperationToExpression( - layer: IndexPatternLayer, + layer: FormBasedLayer, columnId: string, functionName: string, additionalArgs: Record = {} @@ -180,7 +176,7 @@ export function dateBasedOperationToExpression( * Creates an expression ast for a date based operation (cumulative sum, derivative, moving average, counter rate) */ export function optionallHistogramBasedOperationToExpression( - layer: IndexPatternLayer, + layer: FormBasedLayer, columnId: string, functionName: string, additionalArgs: Record = {} diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/cardinality.test.ts b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/cardinality.test.ts similarity index 100% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/cardinality.test.ts rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/cardinality.test.ts diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/cardinality.tsx b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/cardinality.tsx similarity index 100% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/cardinality.tsx rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/cardinality.tsx diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/column_types.ts b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/column_types.ts similarity index 91% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/column_types.ts rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/column_types.ts index 8af67468f0ac1..a0931a23f4e5a 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/column_types.ts +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/column_types.ts @@ -6,8 +6,8 @@ */ import type { Query } from '@kbn/es-query'; -import type { Operation } from '../../../types'; -import type { TimeScaleUnit } from '../../../../common/expressions'; +import type { Operation } from '../../../../types'; +import type { TimeScaleUnit } from '../../../../../common/expressions'; import type { OperationType } from '.'; export interface BaseIndexPatternColumn extends Operation { diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/count.test.ts b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/count.test.ts similarity index 100% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/count.test.ts rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/count.test.ts diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/count.tsx b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/count.tsx similarity index 96% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/count.tsx rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/count.tsx index 1f67eebf3541a..c05b8d415de7e 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/count.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/count.tsx @@ -11,10 +11,10 @@ import { euiThemeVars } from '@kbn/ui-theme'; import { EuiSwitch, EuiText } from '@elastic/eui'; import { AggFunctionsMapping } from '@kbn/data-plugin/public'; import { buildExpressionFunction } from '@kbn/expressions-plugin/public'; -import type { TimeScaleUnit } from '../../../../common/expressions'; -import type { OperationDefinition, ParamEditorProps } from '.'; -import type { FieldBasedIndexPatternColumn, ValueFormatConfig } from './column_types'; -import type { IndexPatternField } from '../../../types'; +import { TimeScaleUnit } from '../../../../../common/expressions'; +import { OperationDefinition, ParamEditorProps } from '.'; +import { FieldBasedIndexPatternColumn, ValueFormatConfig } from './column_types'; +import type { IndexPatternField } from '../../../../types'; import { getInvalidFieldMessage, getFilter, diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/date_histogram.test.tsx b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/date_histogram.test.tsx similarity index 97% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/date_histogram.test.tsx rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/date_histogram.test.tsx index a437cf63fd873..c08f8703c723f 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/date_histogram.test.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/date_histogram.test.tsx @@ -18,8 +18,8 @@ import type { IStorageWrapper } from '@kbn/kibana-utils-plugin/public'; import { UI_SETTINGS } from '@kbn/data-plugin/public'; import { dataPluginMock, getCalculateAutoTimeExpression } from '@kbn/data-plugin/public/mocks'; import { createMockedIndexPattern } from '../../mocks'; -import type { IndexPatternLayer } from '../../types'; -import type { IndexPattern } from '../../../types'; +import type { FormBasedLayer } from '../../types'; +import type { IndexPattern } from '../../../../types'; import { getFieldByNameFactory } from '../../pure_helpers'; import { act } from 'react-dom/test-utils'; @@ -124,7 +124,7 @@ const defaultOptions = { }; describe('date_histogram', () => { - let layer: IndexPatternLayer; + let layer: FormBasedLayer; const InlineOptions = dateHistogramOperation.paramEditor!; beforeEach(() => { @@ -160,7 +160,7 @@ describe('date_histogram', () => { }, }, }, - } as unknown as IndexPatternLayer; + } as unknown as FormBasedLayer; } describe('buildColumn', () => { @@ -339,7 +339,7 @@ describe('date_histogram', () => { it('should render current value for other index pattern', () => { const updateLayerSpy = jest.fn(); - const secondLayer: IndexPatternLayer = { + const secondLayer: FormBasedLayer = { indexPatternId: '2', columnOrder: ['col2'], columns: { @@ -374,7 +374,7 @@ describe('date_histogram', () => { }); it('should render time interval control set to auto for auto interval', () => { - const thirdLayer: IndexPatternLayer = { + const thirdLayer: FormBasedLayer = { indexPatternId: '1', columnOrder: ['col1'], columns: { @@ -409,7 +409,7 @@ describe('date_histogram', () => { }); it('should allow switching to manual interval', () => { - const thirdLayer: IndexPatternLayer = { + const thirdLayer: FormBasedLayer = { indexPatternId: '1', columnOrder: ['col1'], columns: { @@ -451,7 +451,7 @@ describe('date_histogram', () => { }); it('should allow turning off time range sync', () => { - const thirdLayer: IndexPatternLayer = { + const thirdLayer: FormBasedLayer = { indexPatternId: '1', columnOrder: ['col1'], columns: { @@ -493,7 +493,7 @@ describe('date_histogram', () => { }); it('turns off time range ignore on switching to auto interval', () => { - const thirdLayer: IndexPatternLayer = { + const thirdLayer: FormBasedLayer = { indexPatternId: '1', columnOrder: ['col1'], columns: { @@ -535,7 +535,7 @@ describe('date_histogram', () => { }); it('turns off drop partial bucket on tuning off time range ignore', () => { - const thirdLayer: IndexPatternLayer = { + const thirdLayer: FormBasedLayer = { indexPatternId: '1', columnOrder: ['col1'], columns: { @@ -735,7 +735,7 @@ describe('date_histogram', () => { }); it('should allow the drop of partial buckets', () => { - const thirdLayer: IndexPatternLayer = { + const thirdLayer: FormBasedLayer = { indexPatternId: '1', columnOrder: ['col1'], columns: { diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/date_histogram.tsx b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/date_histogram.tsx similarity index 98% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/date_histogram.tsx rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/date_histogram.tsx index 8d6b201b2cc19..87261f41338d0 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/date_histogram.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/date_histogram.tsx @@ -33,8 +33,8 @@ import { updateColumnParam } from '../layer_helpers'; import { OperationDefinition, ParamEditorProps } from '.'; import { FieldBasedIndexPatternColumn } from './column_types'; import { getInvalidFieldMessage, getSafeName } from './helpers'; -import { IndexPatternLayer } from '../../types'; -import { TooltipWrapper } from '../../../shared_components'; +import { FormBasedLayer } from '../../types'; +import { TooltipWrapper } from '../../../../shared_components'; const { isValidInterval } = search.aggs; const autoInterval = 'auto'; @@ -50,7 +50,7 @@ export interface DateHistogramIndexPatternColumn extends FieldBasedIndexPatternC }; } -function getMultipleDateHistogramsErrorMessage(layer: IndexPatternLayer, columnId: string) { +function getMultipleDateHistogramsErrorMessage(layer: FormBasedLayer, columnId: string) { const usesTimeShift = Object.values(layer.columns).some( (col) => col.timeShift && col.timeShift !== '' ); diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filter_popover.scss b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/filters/filter_popover.scss similarity index 100% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filter_popover.scss rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/filters/filter_popover.scss diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filter_popover.test.tsx b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/filters/filter_popover.test.tsx similarity index 98% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filter_popover.test.tsx rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/filters/filter_popover.test.tsx index 475761c94ec54..9fbc38732806c 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filter_popover.test.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/filters/filter_popover.test.tsx @@ -13,7 +13,7 @@ import { createMockedIndexPattern } from '../../../mocks'; import { FilterPopover } from './filter_popover'; import { LabelInput } from '../shared_components'; import { QueryStringInput } from '@kbn/unified-search-plugin/public'; -import { QueryInput } from '../../../../shared_components'; +import { QueryInput } from '../../../../../shared_components'; jest.mock('.', () => ({ isQueryValid: () => true, diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filter_popover.tsx b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/filters/filter_popover.tsx similarity index 94% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filter_popover.tsx rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/filters/filter_popover.tsx index 17314bbc991c0..21a52f46e5c58 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filter_popover.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/filters/filter_popover.tsx @@ -12,8 +12,8 @@ import { EuiPopover, EuiSpacer } from '@elastic/eui'; import type { Query } from '@kbn/es-query'; // Need to keep it separate to make it work Jest mocks in dimension_panel tests // import { QueryInput } from '../../../../shared_components/query_input'; -import { isQueryValid, QueryInput } from '../../../../shared_components'; -import { IndexPattern } from '../../../../types'; +import { isQueryValid, QueryInput } from '../../../../../shared_components'; +import { IndexPattern } from '../../../../../types'; import { FilterValue, defaultLabel } from '.'; import { LabelInput } from '../shared_components'; diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filters.scss b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/filters/filters.scss similarity index 100% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filters.scss rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/filters/filters.scss diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filters.test.tsx b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/filters/filters.test.tsx similarity index 99% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filters.test.tsx rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/filters/filters.test.tsx index 2b227674c26e9..2264fa8f185fb 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filters.test.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/filters/filters.test.tsx @@ -16,7 +16,7 @@ import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; import { dataViewPluginMocks } from '@kbn/data-views-plugin/public/mocks'; import type { FiltersIndexPatternColumn } from '.'; import { filtersOperation } from '..'; -import type { IndexPatternLayer } from '../../../types'; +import type { FormBasedLayer } from '../../../types'; import { createMockedIndexPattern } from '../../../mocks'; import { FilterPopover } from './filter_popover'; @@ -62,7 +62,7 @@ jest.mock('@elastic/eui', () => { }); describe('filters', () => { - let layer: IndexPatternLayer; + let layer: FormBasedLayer; const InlineOptions = filtersOperation.paramEditor!; beforeEach(() => { diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filters.tsx b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/filters/filters.tsx similarity index 98% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filters.tsx rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/filters/filters.tsx index 434dbb092bdb0..67f3af575f7db 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/filters.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/filters/filters.tsx @@ -19,8 +19,8 @@ import { DraggableBucketContainer, isQueryValid, NewBucketButton, -} from '../../../../shared_components'; -import { IndexPattern } from '../../../../types'; +} from '../../../../../shared_components'; +import { IndexPattern } from '../../../../../types'; import { updateColumnParam } from '../../layer_helpers'; import type { OperationDefinition } from '..'; import type { BaseIndexPatternColumn } from '../column_types'; diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/index.tsx b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/filters/index.tsx similarity index 100% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/filters/index.tsx rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/filters/index.tsx diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/editor/formula.scss b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/editor/formula.scss similarity index 100% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/editor/formula.scss rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/editor/formula.scss diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/editor/formula_editor.tsx b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/editor/formula_editor.tsx similarity index 96% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/editor/formula_editor.tsx rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/editor/formula_editor.tsx index 1e9a304ffa8a2..fa293a57903fc 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/editor/formula_editor.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/editor/formula_editor.tsx @@ -27,7 +27,7 @@ import { monaco } from '@kbn/monaco'; import classNames from 'classnames'; import { CodeEditor } from '@kbn/kibana-react-plugin/public'; import type { CodeEditorProps } from '@kbn/kibana-react-plugin/public'; -import { TooltipWrapper, useDebounceWithOptions } from '../../../../../shared_components'; +import { TooltipWrapper, useDebounceWithOptions } from '../../../../../../shared_components'; import { ParamEditorProps } from '../..'; import { getManagedColumnsFrom } from '../../../layer_helpers'; import { ErrorWrapper, runASTValidation, tryToParse } from '../validation'; @@ -41,6 +41,8 @@ import { getTokenInfo, offsetToRowColumn, monacoPositionToOffset, + createEditOperation, + MARKER, } from './math_completion'; import { LANGUAGE_ID } from './math_tokenization'; import { MemoizedFormulaHelp } from './formula_help'; @@ -48,7 +50,7 @@ import { MemoizedFormulaHelp } from './formula_help'; import './formula.scss'; import { FormulaIndexPatternColumn } from '../formula'; import { insertOrReplaceFormulaColumn } from '../parse'; -import { filterByVisibleOperation } from '../util'; +import { filterByVisibleOperation, nonNullable } from '../util'; import { getColumnTimeShiftWarnings, getDateHistogramInterval } from '../../../../time_shift_utils'; function tableHasData( @@ -85,6 +87,8 @@ export const WrappedFormulaEditor = ({ const MemoizedFormulaEditor = React.memo(FormulaEditor); +const namedArgumentsTypes = new Set(['kql', 'lucene', 'shift', 'reducedTimeRange']); + export function FormulaEditor({ layer, paramEditorUpdater, @@ -363,7 +367,7 @@ export function FormulaEditor({ } return newWarnings; }) - .filter((marker) => marker); + .filter(nonNullable); setWarnings(markers.map(({ severity, message }) => ({ severity, message }))); monaco.editor.setModelMarkers(editorModel.current, 'LENS', markers); } @@ -533,47 +537,44 @@ export function FormulaEditor({ const isSingleQuoteCase = /'LENS_MATH_MARKER/; // Make sure that we are only adding kql='' or lucene='', and also // check that the = sign isn't inside the KQL expression like kql='=' - if ( - !tokenInfo || - typeof tokenInfo.ast === 'number' || - tokenInfo.ast.type !== 'namedArgument' || - (tokenInfo.ast.name !== 'kql' && - tokenInfo.ast.name !== 'lucene' && - tokenInfo.ast.name !== 'shift' && - tokenInfo.ast.name !== 'reducedTimeRange') || - (tokenInfo.ast.value !== 'LENS_MATH_MARKER' && - !isSingleQuoteCase.test(tokenInfo.ast.value)) - ) { - return; + if (tokenInfo) { + if ( + typeof tokenInfo.ast === 'number' || + tokenInfo.ast.type !== 'namedArgument' || + !namedArgumentsTypes.has(tokenInfo.ast.name) || + (tokenInfo.ast.value !== MARKER && !isSingleQuoteCase.test(tokenInfo.ast.value)) + ) { + return; + } } let editOperation: monaco.editor.IIdentifiedSingleEditOperation | null = null; + const cursorOffset = 2; if (char === '=') { - editOperation = { - range: { - ...currentPosition, - // Insert after the current char - startColumn: currentPosition.startColumn + 1, - endColumn: currentPosition.startColumn + 1, - }, - text: `''`, - }; + // check also the previous char whether it was already a = + // to avoid infinite loops + if (!tokenInfo && currentText.charAt(offset - 1) !== '=') { + editOperation = createEditOperation('=', currentPosition, 1); + } + if (tokenInfo) { + editOperation = createEditOperation(`''`, currentPosition, 1); + } } + + if (!tokenInfo && !editOperation) { + return; + } + if ( char === "'" && + tokenInfo?.ast && + typeof tokenInfo.ast !== 'number' && + 'name' in tokenInfo.ast && tokenInfo.ast.name !== 'shift' && tokenInfo.ast.name !== 'reducedTimeRange' ) { - editOperation = { - range: { - ...currentPosition, - // Insert after the current char - startColumn: currentPosition.startColumn, - endColumn: currentPosition.startColumn + 1, - }, - text: `\\'`, - }; + editOperation = createEditOperation(`\\'`, currentPosition); } if (editOperation) { diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/editor/formula_help.tsx b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/editor/formula_help.tsx similarity index 83% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/editor/formula_help.tsx rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/editor/formula_help.tsx index 0a1cf746c19f8..d0b4b3b0bb173 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/editor/formula_help.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/editor/formula_help.tsx @@ -21,7 +21,8 @@ import { EuiSpacer, } from '@elastic/eui'; import { Markdown } from '@kbn/kibana-react-plugin/public'; -import type { IndexPattern } from '../../../../../types'; +import { groupBy } from 'lodash'; +import type { IndexPattern } from '../../../../../../types'; import { tinymathFunctions } from '../util'; import { getPossibleFunctions } from './math_completion'; import { hasFunctionFieldArgument } from '../validation'; @@ -193,31 +194,40 @@ max(system.network.in.bytes, reducedTimeRange="30m") items: [], }); - const availableFunctions = getPossibleFunctions(indexPattern); + const { + elasticsearch: esFunction, + calculation: calculationFunction, + math: mathOperations, + comparison: comparisonOperations, + } = useMemo( + () => + groupBy(getPossibleFunctions(indexPattern), (key) => { + if (key in operationDefinitionMap) { + return operationDefinitionMap[key].documentation?.section; + } + if (key in tinymathFunctions) { + return tinymathFunctions[key].section; + } + }), + [operationDefinitionMap, indexPattern] + ); // Es aggs helpGroups[2].items.push( - ...availableFunctions - .filter( - (key) => - key in operationDefinitionMap && - operationDefinitionMap[key].documentation?.section === 'elasticsearch' - ) - .sort() - .map((key) => ({ - label: key, - description: ( - <> -

- {key}({operationDefinitionMap[key].documentation?.signature}) -

- - {operationDefinitionMap[key].documentation?.description ? ( - - ) : null} - - ), - })) + ...esFunction.sort().map((key) => ({ + label: key, + description: ( + <> +

+ {key}({operationDefinitionMap[key].documentation?.signature}) +

+ + {operationDefinitionMap[key].documentation?.description ? ( + + ) : null} + + ), + })) ); helpGroups.push({ @@ -236,31 +246,24 @@ max(system.network.in.bytes, reducedTimeRange="30m") // Calculations aggs helpGroups[3].items.push( - ...availableFunctions - .filter( - (key) => - key in operationDefinitionMap && - operationDefinitionMap[key].documentation?.section === 'calculation' - ) - .sort() - .map((key) => ({ - label: key, - description: ( - <> -

- {key}({operationDefinitionMap[key].documentation?.signature}) -

- - {operationDefinitionMap[key].documentation?.description ? ( - - ) : null} - - ), - checked: - selectedFunction === `${key}: ${operationDefinitionMap[key].displayName}` - ? ('on' as const) - : undefined, - })) + ...calculationFunction.sort().map((key) => ({ + label: key, + description: ( + <> +

+ {key}({operationDefinitionMap[key].documentation?.signature}) +

+ + {operationDefinitionMap[key].documentation?.description ? ( + + ) : null} + + ), + checked: + selectedFunction === `${key}: ${operationDefinitionMap[key].displayName}` + ? ('on' as const) + : undefined, + })) ); helpGroups.push({ @@ -274,22 +277,55 @@ max(system.network.in.bytes, reducedTimeRange="30m") items: [], }); - const tinymathFns = useMemo(() => { - return getPossibleFunctions(indexPattern) - .filter((key) => key in tinymathFunctions) - .sort() - .map((key) => { - const [description, examples] = tinymathFunctions[key].help.split(`\`\`\``); - return { - label: key, - description: description.replace(/\n/g, '\n\n'), - examples: examples ? `\`\`\`${examples}\`\`\`` : '', - }; - }); - }, [indexPattern]); + const mathFns = useMemo(() => { + return mathOperations.sort().map((key) => { + const [description, examples] = tinymathFunctions[key].help.split(`\`\`\``); + return { + label: key, + description: description.replace(/\n/g, '\n\n'), + examples: examples ? `\`\`\`${examples}\`\`\`` : '', + }; + }); + }, [mathOperations]); helpGroups[4].items.push( - ...tinymathFns.map(({ label, description, examples }) => { + ...mathFns.map(({ label, description, examples }) => { + return { + label, + description: ( + <> +

{getFunctionSignatureLabel(label, operationDefinitionMap)}

+ + + + ), + }; + }) + ); + + helpGroups.push({ + label: i18n.translate('xpack.lens.formulaDocumentation.comparisonSection', { + defaultMessage: 'Comparison', + }), + description: i18n.translate('xpack.lens.formulaDocumentation.comparisonSectionDescription', { + defaultMessage: 'These functions are used to perform value comparison.', + }), + items: [], + }); + + const comparisonFns = useMemo(() => { + return comparisonOperations.sort().map((key) => { + const [description, examples] = tinymathFunctions[key].help.split(`\`\`\``); + return { + label: key, + description: description.replace(/\n/g, '\n\n'), + examples: examples ? `\`\`\`${examples}\`\`\`` : '', + }; + }); + }, [comparisonOperations]); + + helpGroups[5].items.push( + ...comparisonFns.map(({ label, description, examples }) => { return { label, description: ( @@ -507,27 +543,30 @@ export function getFunctionSignatureLabel( } if (operationDefinitionMap[name]) { const def = operationDefinitionMap[name]; - let extraArgs = ''; + const extraArgs: string[] = []; if (def.filterable) { - extraArgs += ','; - extraArgs += i18n.translate('xpack.lens.formula.kqlExtraArguments', { - defaultMessage: '[kql]?: string, [lucene]?: string', - }); - } - if (def.filterable && def.shiftable) { - extraArgs += ', '; + extraArgs.push( + i18n.translate('xpack.lens.formula.kqlExtraArguments', { + defaultMessage: '[kql]?: string, [lucene]?: string', + }) + ); } if (def.shiftable) { - extraArgs += i18n.translate('xpack.lens.formula.shiftExtraArguments', { - defaultMessage: '[shift]?: string', - }); + extraArgs.push( + i18n.translate('xpack.lens.formula.shiftExtraArguments', { + defaultMessage: '[shift]?: string', + }) + ); } if (def.canReduceTimeRange) { - extraArgs += i18n.translate('xpack.lens.formula.reducedTimeRangeExtraArguments', { - defaultMessage: '[reducedTimeRange]?: string', - }); + extraArgs.push( + i18n.translate('xpack.lens.formula.reducedTimeRangeExtraArguments', { + defaultMessage: '[reducedTimeRange]?: string', + }) + ); } - return `${name}(${def.documentation?.signature}${extraArgs})`; + const extraComma = extraArgs.length ? ', ' : ''; + return `${name}(${def.documentation?.signature}${extraComma}${extraArgs.join(', ')})`; } return ''; } diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/editor/index.ts b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/editor/index.ts similarity index 100% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/editor/index.ts rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/editor/index.ts diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/editor/math_completion.test.ts b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/editor/math_completion.test.ts similarity index 99% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/editor/math_completion.test.ts rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/editor/math_completion.test.ts index 79e77c3275ea8..76b70ba9a471c 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/editor/math_completion.test.ts +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/editor/math_completion.test.ts @@ -11,7 +11,7 @@ import { unifiedSearchPluginMock } from '@kbn/unified-search-plugin/public/mocks import { dataViewPluginMocks } from '@kbn/data-views-plugin/public/mocks'; import { createMockedIndexPattern } from '../../../../mocks'; import { GenericOperationDefinition } from '../..'; -import type { IndexPatternField, OperationMetadata } from '../../../../../types'; +import type { OperationMetadata, IndexPatternField } from '../../../../../../types'; import { tinymathFunctions } from '../util'; import { getSignatureHelp, diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/editor/math_completion.ts b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/editor/math_completion.ts similarity index 97% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/editor/math_completion.ts rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/editor/math_completion.ts index 94b8dcc2a9681..8d0c9fd4d6b6b 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/editor/math_completion.ts +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/editor/math_completion.ts @@ -22,9 +22,9 @@ import type { } from '@kbn/unified-search-plugin/public'; import type { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public'; import { parseTimeShift } from '@kbn/data-plugin/common'; -import type { IndexPattern } from '../../../../../types'; +import type { IndexPattern } from '../../../../../../types'; import { memoizedGetAvailableOperationsByMetadata } from '../../../operations'; -import { tinymathFunctions, groupArgsByType, unquotedStringRegex } from '../util'; +import { tinymathFunctions, groupArgsByType, unquotedStringRegex, nonNullable } from '../util'; import type { GenericOperationDefinition } from '../..'; import { getFunctionSignatureLabel, getHelpTextContent } from './formula_help'; import { hasFunctionFieldArgument } from '../validation'; @@ -61,7 +61,7 @@ function inLocation(cursorPosition: number, location: TinymathLocation) { return cursorPosition >= location.min && cursorPosition < location.max; } -const MARKER = 'LENS_MATH_MARKER'; +export const MARKER = 'LENS_MATH_MARKER'; export function getInfoAtZeroIndexedPosition( ast: TinymathAST, @@ -78,7 +78,7 @@ export function getInfoAtZeroIndexedPosition( if (ast.type === 'function') { const [match] = ast.args .map((arg) => getInfoAtZeroIndexedPosition(arg, zeroIndexedPosition, ast)) - .filter((a) => a); + .filter(nonNullable); if (match) { return match; } else if (ast.location) { @@ -94,6 +94,23 @@ export function getInfoAtZeroIndexedPosition( }; } +export function createEditOperation( + textToInject: string, + currentPosition: monaco.IRange, + startOffset: number = 0, + endOffset: number = 1 +) { + return { + range: { + ...currentPosition, + // Insert after the current char + startColumn: currentPosition.startColumn + startOffset, + endColumn: currentPosition.startColumn + endOffset, + }, + text: textToInject, + }; +} + export function offsetToRowColumn(expression: string, offset: number): monaco.Position { const lines = expression.split(/\n/); let remainingChars = offset; @@ -297,7 +314,7 @@ function getArgumentSuggestions( const fields = validOperation.operations .filter((op) => op.operationType === operation.type) .map((op) => ('field' in op ? op.field : undefined)) - .filter((field) => field); + .filter(nonNullable); const fieldArg = ast.args[0]; const location = typeof fieldArg !== 'string' && (fieldArg as TinymathVariable).location; let range: monaco.IRange | undefined; diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/editor/math_tokenization.tsx b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/editor/math_tokenization.tsx similarity index 100% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/editor/math_tokenization.tsx rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/editor/math_tokenization.tsx diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula.test.tsx b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/formula.test.tsx similarity index 90% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula.test.tsx rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/formula.test.tsx index 9c5cf27e60a88..90ece71627f42 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula.test.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/formula.test.tsx @@ -13,8 +13,8 @@ import { } from '..'; import type { FormulaIndexPatternColumn } from './formula'; import { insertOrReplaceFormulaColumn } from './parse'; -import type { IndexPatternLayer } from '../../../types'; -import { IndexPattern } from '../../../../types'; +import type { FormBasedLayer } from '../../../types'; +import { IndexPattern } from '../../../../../types'; import { tinymathFunctions } from './util'; import { TermsIndexPatternColumn } from '../terms'; import { MovingAverageIndexPatternColumn } from '../calculations'; @@ -69,7 +69,7 @@ const operationDefinitionMap: Record = { }; describe('formula', () => { - let layer: IndexPatternLayer; + let layer: FormBasedLayer; beforeEach(() => { layer = { @@ -894,7 +894,7 @@ describe('formula', () => { formula: string, isBroken = true, columnParams: Partial> = {} - ): IndexPatternLayer { + ): FormBasedLayer { return { columns: { col1: { @@ -1491,6 +1491,23 @@ invalid: " ).toEqual(undefined); }); + it('returns no error if the formula contains comparison operator within the ifelse operation', () => { + const formulas = [ + ...['lt', 'gt', 'lte', 'gte', 'eq'].map((op) => `${op}(5, 1)`), + ...['<', '>', '==', '>=', '<='].map((symbol) => `5 ${symbol} 1`), + ]; + for (const formula of formulas) { + expect( + formulaOperation.getErrorMessage!( + getNewLayerWithFormula(`ifelse(${formula}, 1, 5)`), + 'col1', + indexPattern, + operationDefinitionMap + ) + ).toEqual(undefined); + } + }); + it('returns no error if a math operation is passed to fullReference operations', () => { const formulas = [ 'derivative(7+1)', @@ -1534,6 +1551,8 @@ invalid: " { formula: 'last_value(dest)' }, { formula: 'terms(dest)' }, { formula: 'moving_average(last_value(dest), window=7)', errorFormula: 'last_value(dest)' }, + ...['lt', 'gt', 'lte', 'gte', 'eq'].map((op) => ({ formula: `${op}(5, 1)` })), + ...['<', '>', '==', '>=', '<='].map((symbol) => ({ formula: `5 ${symbol} 1` })), ]; for (const { formula, errorFormula } of formulas) { expect( @@ -1546,7 +1565,7 @@ invalid: " ).toEqual([ `The return value type of the operation ${ errorFormula ?? formula - } is not supported in Formula.`, + } is not supported in Formula`, ]); } }); @@ -1557,8 +1576,14 @@ invalid: " // * field passed // * missing argument const errors = [ - (operation: string) => - `The first argument for ${operation} should be a operation name. Found ()`, + (operation: string) => { + const required = tinymathFunctions[operation].positionalArguments.filter( + ({ optional }) => !optional + ); + return `The operation ${operation} in the Formula is missing ${ + required.length + } arguments: ${required.map(({ name }) => name).join(', ')}`; + }, (operation: string) => `The operation ${operation} has too many arguments`, (operation: string) => `The operation ${operation} does not accept any field as argument`, (operation: string) => { @@ -1573,9 +1598,11 @@ invalid: " .join(', ')}`; }, ]; + + const mathFns = Object.keys(tinymathFunctions); // we'll try to map all of these here in this test - for (const fn of Object.keys(tinymathFunctions)) { - it(`returns an error for the math functions available: ${fn}`, () => { + for (const fn of mathFns) { + it(`[${fn}] returns an error for the math functions available`, () => { const nArgs = tinymathFunctions[fn].positionalArguments; // start with the first 3 types const formulas = [ @@ -1585,14 +1612,22 @@ invalid: " `${fn}(${Array(nArgs.length).fill('bytes').join(', ')})`, ]; // add the fourth check only for those functions with more than 1 arg required + // and check that this first argument is of type number const enableFourthCheck = nArgs.filter( ({ optional, alternativeWhenMissing }) => !optional && !alternativeWhenMissing - ).length > 1; + ).length > 1 && nArgs[0]?.type === 'number'; if (enableFourthCheck) { formulas.push(`${fn}(1)`); } - formulas.forEach((formula, i) => { + const finalFormulas = formulas.map((text) => { + if (tinymathFunctions[fn].outputType !== 'boolean') { + return text; + } + // for comparison functions wrap the existing formula within the ifelse function + return `ifelse(${text}, 1, 0)`; + }); + finalFormulas.forEach((formula, i) => { expect( formulaOperation.getErrorMessage!( getNewLayerWithFormula(formula), @@ -1600,16 +1635,87 @@ invalid: " indexPattern, operationDefinitionMap ) - ).toEqual([errors[i](fn)]); + ).toContain(errors[i](fn)); }); }); } + // comparison tests + for (const fn of mathFns.filter((name) => tinymathFunctions[name].section === 'comparison')) { + if (tinymathFunctions[fn].outputType === 'boolean') { + it(`[${fn}] returns an error about unsupported return type and when partial arguments are passed`, () => { + const formulas = [`${fn}()`, `${fn}(1)`]; + formulas.forEach((formula, nArg) => { + const expectedCount = tinymathFunctions[fn].positionalArguments.length - nArg; + const expectedArgs = ['left', 'right'].slice(nArg).join(', '); + expect( + formulaOperation.getErrorMessage!( + getNewLayerWithFormula(formula), + 'col1', + indexPattern, + operationDefinitionMap + ) + ).toEqual([ + `The return value type of the operation ${formula} is not supported in Formula`, + `The operation ${fn} in the Formula is missing ${expectedCount} arguments: ${expectedArgs}`, + ]); + }); + }); + } else { + const indexReverseMap = { + cond: [0], + left: [1], + right: [2], + all: [0, 1, 2], + }; + it.each` + cond | left | right | expectedFail + ${'1'} | ${'2'} | ${'3'} | ${'cond'} + ${'1 > 1'} | ${'2 > 2'} | ${'3'} | ${'left'} + ${'1 > 1'} | ${'2'} | ${'3 > 3'} | ${'right'} + ${'1'} | ${'2 > 2'} | ${'3 > 3'} | ${'all'} + ${'count()'} | ${'average(bytes)'} | ${'average(bytes)'} | ${'cond'} + ${'count() > 1'} | ${'average(bytes) > 2'} | ${'average(bytes)'} | ${'left'} + ${'count() > 1'} | ${'average(bytes)'} | ${'average(bytes) > 3'} | ${'right'} + ${'count()'} | ${'average(bytes) > 2'} | ${'average(bytes) > 3'} | ${'all'} + `( + `[${fn}] returns an error if $expectedFail argument is/are of the wrong type: ${fn}($cond, $left, $right)`, + ({ + cond, + left, + right, + expectedFail, + }: { + cond: string; + left: string; + right: string; + expectedFail: keyof typeof indexReverseMap; + }) => { + const argsSorted = [cond, left, right]; + expect( + formulaOperation.getErrorMessage!( + getNewLayerWithFormula(`${fn}(${cond}, ${left}, ${right})`), + 'col1', + indexPattern, + operationDefinitionMap + ) + ).toEqual( + indexReverseMap[expectedFail].map((i) => { + const arg = tinymathFunctions[fn].positionalArguments[i]; + const passedValue = />/.test(argsSorted[i]) ? 'boolean' : 'number'; + return `The ${arg.name} argument for the operation ${fn} in the Formula is of the wrong type: ${passedValue} instead of ${arg.type}`; + }) + ); + } + ); + } + } + it('returns an error suggesting to use an alternative function', () => { const formulas = [`clamp(1)`, 'clamp(1, 5)']; const errorsWithSuggestions = [ - 'The operation clamp in the Formula is missing the min argument: use the pick_max operation instead.', - 'The operation clamp in the Formula is missing the max argument: use the pick_min operation instead.', + 'The operation clamp in the Formula is missing the min argument: use the pick_max operation instead', + 'The operation clamp in the Formula is missing the max argument: use the pick_min operation instead', ]; formulas.forEach((formula, i) => { expect( @@ -1648,7 +1754,7 @@ invalid: " operationDefinitionMap ) ).toEqual([ - `The Formula filter of type "lucene" is not compatible with the inner filter of type "kql" from the ${operation} operation.`, + `The Formula filter of type "lucene" is not compatible with the inner filter of type "kql" from the ${operation} operation`, ]); } }); @@ -1668,8 +1774,8 @@ invalid: " operationDefinitionMap ) ).toEqual([ - `The Formula filter of type "lucene" is not compatible with the inner filter of type "kql" from the count operation.`, - `The Formula filter of type "lucene" is not compatible with the inner filter of type "kql" from the sum operation.`, + `The Formula filter of type "lucene" is not compatible with the inner filter of type "kql" from the count operation`, + `The Formula filter of type "lucene" is not compatible with the inner filter of type "kql" from the sum operation`, ]); }); diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula.tsx b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/formula.tsx similarity index 96% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula.tsx rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/formula.tsx index 2715ab96cef0c..9746a25ebf907 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/formula.tsx @@ -8,12 +8,12 @@ import { i18n } from '@kbn/i18n'; import type { BaseIndexPatternColumn, OperationDefinition } from '..'; import type { ReferenceBasedIndexPatternColumn } from '../column_types'; -import type { IndexPattern } from '../../../../types'; +import type { IndexPattern } from '../../../../../types'; import { runASTValidation, tryToParse } from './validation'; import { WrappedFormulaEditor } from './editor'; import { insertOrReplaceFormulaColumn } from './parse'; import { generateFormula } from './generate'; -import { filterByVisibleOperation } from './util'; +import { filterByVisibleOperation, nonNullable } from './util'; import { getManagedColumnsFrom } from '../../layer_helpers'; import { getFilter, isColumnFormatted } from '../helpers'; @@ -77,7 +77,8 @@ export const formulaOperation: OperationDefinition message); + // remove duplicates + return Array.from(new Set(errors.map(({ message }) => message))); } const managedColumns = getManagedColumnsFrom(columnId, layer.columns); @@ -90,7 +91,7 @@ export const formulaOperation: OperationDefinition marker); + .filter(nonNullable); const hasBuckets = layer.columnOrder.some((colId) => layer.columns[colId].isBucketed); const hasOtherMetrics = layer.columnOrder.some((colId) => { const col = layer.columns[colId]; diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula_public_api.test.ts b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/formula_public_api.test.ts similarity index 96% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula_public_api.test.ts rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/formula_public_api.test.ts index c854595757a0c..4c1ba662d1861 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula_public_api.test.ts +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/formula_public_api.test.ts @@ -10,13 +10,13 @@ import { createFormulaPublicApi, FormulaPublicApi } from './formula_public_api'; import type { DataView } from '@kbn/data-views-plugin/public'; import type { DateHistogramIndexPatternColumn, PersistedIndexPatternLayer } from '../../../types'; -import { convertDataViewIntoLensIndexPattern } from '../../../../data_views_service/loader'; +import { convertDataViewIntoLensIndexPattern } from '../../../../../data_views_service/loader'; jest.mock('./parse', () => ({ insertOrReplaceFormulaColumn: jest.fn().mockReturnValue({}), })); -jest.mock('../../../../data_views_service/loader', () => ({ +jest.mock('../../../../../data_views_service/loader', () => ({ convertDataViewIntoLensIndexPattern: jest.fn((v) => v), })); diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula_public_api.ts b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/formula_public_api.ts similarity index 96% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula_public_api.ts rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/formula_public_api.ts index 4085ec931d3a6..231cd82804c8f 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula_public_api.ts +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/formula_public_api.ts @@ -6,8 +6,8 @@ */ import type { DataView } from '@kbn/data-views-plugin/public'; -import { convertDataViewIntoLensIndexPattern } from '../../../../data_views_service/loader'; -import type { IndexPattern } from '../../../../types'; +import { convertDataViewIntoLensIndexPattern } from '../../../../../data_views_service/loader'; +import type { IndexPattern } from '../../../../../types'; import type { PersistedIndexPatternLayer } from '../../../types'; import { insertOrReplaceFormulaColumn } from './parse'; diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/generate.ts b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/generate.ts similarity index 97% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/generate.ts rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/generate.ts index 189a8d342b903..2315d6d164fc8 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/generate.ts +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/generate.ts @@ -6,14 +6,14 @@ */ import { isObject } from 'lodash'; -import { DOCUMENT_FIELD_NAME } from '../../../../../common'; +import { DOCUMENT_FIELD_NAME } from '../../../../../../common'; import { FieldBasedIndexPatternColumn, GenericOperationDefinition, GenericIndexPatternColumn, } from '..'; import { BaseIndexPatternColumn, ReferenceBasedIndexPatternColumn } from '../column_types'; -import { IndexPatternLayer } from '../../../types'; +import { FormBasedLayer } from '../../../types'; import { unquotedStringRegex } from './util'; import { isColumnOfType } from '../helpers'; import { StaticValueIndexPatternColumn } from '../static_value'; @@ -37,7 +37,7 @@ export function getSafeFieldName({ export function generateFormula( previousColumn: ReferenceBasedIndexPatternColumn | GenericIndexPatternColumn, - layer: IndexPatternLayer, + layer: FormBasedLayer, previousFormula: string, operationDefinitionMap: Record | undefined ) { diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/index.ts b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/index.ts similarity index 100% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/index.ts rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/index.ts diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/math.test.ts b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/math.test.ts similarity index 83% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/math.test.ts rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/math.test.ts index fdf4cc98c59d7..c96bff33b5267 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/math.test.ts +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/math.test.ts @@ -6,11 +6,11 @@ */ import { TinymathAST } from '@kbn/tinymath'; -import { IndexPattern } from '../../../../types'; -import { IndexPatternLayer } from '../../../types'; +import { IndexPattern } from '../../../../../types'; +import { FormBasedLayer } from '../../../types'; import { MathIndexPatternColumn, mathOperation } from './math'; -function createLayerWithMathColumn(tinymathAst: string | TinymathAST): IndexPatternLayer { +function createLayerWithMathColumn(tinymathAst: string | TinymathAST): FormBasedLayer { return { columnOrder: ['myColumnId'], columns: { @@ -348,5 +348,90 @@ describe('math operation', () => { }, ]); }); + + it('should work for comparison operations as well', () => { + const tinymathAst = { + type: 'function', + name: 'ifelse', + args: [ + { + type: 'function', + name: 'eq', + args: ['columnX0', 0], + }, + { + type: 'function', + name: 'ifelse', + args: [ + { + type: 'function', + name: 'lt', + args: ['columnX1', 0], + }, + { + type: 'function', + name: 'ifelse', + args: [ + { + type: 'function', + name: 'lte', + args: ['columnX2', 0], + }, + 'columnX3', + 'columnX4', + ], + }, + 'columnX5', + ], + }, + { + type: 'function', + name: 'ifelse', + args: [ + { + type: 'function', + name: 'gt', + args: ['columnX6', 0], + }, + { + type: 'function', + name: 'ifelse', + args: [ + { + type: 'function', + name: 'gte', + args: ['columnX7', 0], + }, + 'columnX8', + 'columnX9', + ], + }, + 'columnX10', + ], + }, + ], + } as unknown as TinymathAST; + + const expression = mathOperation.toExpression( + createLayerWithMathColumn(tinymathAst), + 'myColumnId', + {} as IndexPattern + ); + + expect(expression).toEqual([ + { + type: 'function', + function: 'mathColumn', + arguments: { + id: ['myColumnId'], + name: ['Math'], + expression: [ + 'ifelse(("columnX0" == 0),ifelse(("columnX1" < 0),ifelse(("columnX2" <= 0),"columnX3","columnX4"),"columnX5"),ifelse(("columnX6" > 0),ifelse(("columnX7" >= 0),"columnX8","columnX9"),"columnX10"))', + ], + onError: ['null'], + }, + }, + ]); + }); }); }); diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/math.tsx b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/math.tsx similarity index 96% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/math.tsx rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/math.tsx index c4e0cbed627f2..4215d727a4c42 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/math.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/math.tsx @@ -8,7 +8,7 @@ import type { TinymathAST } from '@kbn/tinymath'; import { OperationDefinition } from '..'; import { ValueFormatConfig, ReferenceBasedIndexPatternColumn } from '../column_types'; -import { IndexPattern } from '../../../../types'; +import { IndexPattern } from '../../../../../types'; export interface MathIndexPatternColumn extends ReferenceBasedIndexPatternColumn { operationType: 'math'; @@ -77,6 +77,11 @@ const optimizableFnsMap: Record = { subtract: '-', multiply: '*', divide: '/', + lt: '<', + gt: '>', + eq: '==', + lte: '<=', + gte: '>=', }; function astToString(ast: TinymathAST | string): string | number { diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/math_examples.md b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/math_examples.md similarity index 100% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/math_examples.md rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/math_examples.md diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/mocks/operation_mocks.ts b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/mocks/operation_mocks.ts similarity index 100% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/mocks/operation_mocks.ts rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/mocks/operation_mocks.ts diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/parse.ts b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/parse.ts similarity index 95% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/parse.ts rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/parse.ts index 10789e181dcb9..ea204295500d4 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/parse.ts +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/parse.ts @@ -8,14 +8,14 @@ import { i18n } from '@kbn/i18n'; import { isObject } from 'lodash'; import type { TinymathAST, TinymathVariable, TinymathLocation } from '@kbn/tinymath'; -import type { IndexPattern } from '../../../../types'; +import type { IndexPattern } from '../../../../../types'; import { OperationDefinition, GenericOperationDefinition, GenericIndexPatternColumn, operationDefinitionMap, } from '..'; -import type { IndexPatternLayer } from '../../../types'; +import type { FormBasedLayer } from '../../../types'; import { mathOperation } from './math'; import { documentField } from '../../../document_field'; import { runASTValidation, shouldHaveFieldArgument, tryToParse } from './validation'; @@ -25,6 +25,7 @@ import { getOperationParams, groupArgsByType, mergeWithGlobalFilters, + nonNullable, } from './util'; import { FormulaIndexPatternColumn, isFormulaIndexPatternColumn } from './formula'; import { getColumnOrder } from '../../layer_helpers'; @@ -36,7 +37,7 @@ export function getManagedId(mainId: string, index: number) { function parseAndExtract( text: string, - layer: IndexPatternLayer, + layer: FormBasedLayer, columnId: string, indexPattern: IndexPattern, operations: Record, @@ -72,7 +73,7 @@ function extractColumns( idPrefix: string, operations: Record, ast: TinymathAST, - layer: IndexPatternLayer, + layer: FormBasedLayer, indexPattern: IndexPattern, label: string ): Array<{ column: GenericIndexPatternColumn; location?: TinymathLocation }> { @@ -89,9 +90,9 @@ function extractColumns( const nodeOperation = operations[node.name]; if (!nodeOperation) { // it's a regular math node - const consumedArgs = node.args - .map(parseNode) - .filter((n) => typeof n !== 'undefined' && n !== null) as Array; + const consumedArgs = node.args.map(parseNode).filter(nonNullable) as Array< + number | TinymathVariable + >; return { ...node, args: consumedArgs, @@ -226,7 +227,7 @@ const getEmptyColumnsWithFormulaMeta = (): { function generateFormulaColumns( id: string, column: FormulaIndexPatternColumn, - layer: IndexPatternLayer, + layer: FormBasedLayer, { indexPattern, operations = operationDefinitionMap }: ExpandColumnProperties ) { const { columns, meta } = getEmptyColumnsWithFormulaMeta(); @@ -273,7 +274,7 @@ function generateFormulaColumns( export function insertOrReplaceFormulaColumn( id: string, column: FormulaIndexPatternColumn, - baseLayer: IndexPatternLayer, + baseLayer: FormBasedLayer, params: ExpandColumnProperties ) { const layer = { diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/types.ts b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/types.ts similarity index 100% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/types.ts rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/types.ts diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/util.ts b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/util.ts similarity index 73% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/util.ts rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/util.ts index d66bac4cc8719..4c310b5efa5d3 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/util.ts +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/util.ts @@ -114,12 +114,16 @@ function getTypeI18n(type: string) { if (type === 'string') { return i18n.translate('xpack.lens.formula.string', { defaultMessage: 'string' }); } + if (type === 'boolean') { + return i18n.translate('xpack.lens.formula.boolean', { defaultMessage: 'boolean' }); + } return ''; } export const tinymathFunctions: Record< string, { + section: 'math' | 'comparison'; positionalArguments: Array<{ name: string; optional?: boolean; @@ -129,9 +133,13 @@ export const tinymathFunctions: Record< }>; // Help is in Markdown format help: string; + // When omitted defaults to "number". + // Used for comparison functions return type + outputType?: string; } > = { add: { + section: 'math', positionalArguments: [ { name: i18n.translate('xpack.lens.formula.left', { defaultMessage: 'left' }), @@ -158,6 +166,7 @@ Example: Offset count by a static value }), }, subtract: { + section: 'math', positionalArguments: [ { name: i18n.translate('xpack.lens.formula.left', { defaultMessage: 'left' }), @@ -179,6 +188,7 @@ Example: Calculate the range of a field }), }, multiply: { + section: 'math', positionalArguments: [ { name: i18n.translate('xpack.lens.formula.left', { defaultMessage: 'left' }), @@ -203,6 +213,7 @@ Example: Calculate price after constant tax rate }), }, divide: { + section: 'math', positionalArguments: [ { name: i18n.translate('xpack.lens.formula.left', { defaultMessage: 'left' }), @@ -226,6 +237,7 @@ Example: \`divide(sum(bytes), 2)\` }), }, abs: { + section: 'math', positionalArguments: [ { name: i18n.translate('xpack.lens.formula.value', { defaultMessage: 'value' }), @@ -241,6 +253,7 @@ Example: Calculate average distance to sea level \`abs(average(altitude))\` }), }, cbrt: { + section: 'math', positionalArguments: [ { name: i18n.translate('xpack.lens.formula.value', { defaultMessage: 'value' }), @@ -257,6 +270,7 @@ Example: Calculate side length from volume }), }, ceil: { + section: 'math', positionalArguments: [ { name: i18n.translate('xpack.lens.formula.value', { defaultMessage: 'value' }), @@ -273,6 +287,7 @@ Example: Round up price to the next dollar }), }, clamp: { + section: 'math', positionalArguments: [ { name: i18n.translate('xpack.lens.formula.value', { defaultMessage: 'value' }), @@ -305,6 +320,7 @@ clamp( }), }, cube: { + section: 'math', positionalArguments: [ { name: i18n.translate('xpack.lens.formula.value', { defaultMessage: 'value' }), @@ -321,6 +337,7 @@ Example: Calculate volume from side length }), }, exp: { + section: 'math', positionalArguments: [ { name: i18n.translate('xpack.lens.formula.value', { defaultMessage: 'value' }), @@ -338,6 +355,7 @@ Example: Calculate the natural exponential function }), }, fix: { + section: 'math', positionalArguments: [ { name: i18n.translate('xpack.lens.formula.value', { defaultMessage: 'value' }), @@ -354,6 +372,7 @@ Example: Rounding towards zero }), }, floor: { + section: 'math', positionalArguments: [ { name: i18n.translate('xpack.lens.formula.value', { defaultMessage: 'value' }), @@ -370,6 +389,7 @@ Example: Round down a price }), }, log: { + section: 'math', positionalArguments: [ { name: i18n.translate('xpack.lens.formula.value', { defaultMessage: 'value' }), @@ -395,6 +415,7 @@ log(sum(bytes), 2) }), }, mod: { + section: 'math', positionalArguments: [ { name: i18n.translate('xpack.lens.formula.value', { defaultMessage: 'value' }), @@ -415,6 +436,7 @@ Example: Calculate last three digits of a value }), }, pow: { + section: 'math', positionalArguments: [ { name: i18n.translate('xpack.lens.formula.value', { defaultMessage: 'value' }), @@ -435,6 +457,7 @@ Example: Calculate volume based on side length }), }, round: { + section: 'math', positionalArguments: [ { name: i18n.translate('xpack.lens.formula.value', { defaultMessage: 'value' }), @@ -460,6 +483,7 @@ round(sum(bytes), 2) }), }, sqrt: { + section: 'math', positionalArguments: [ { name: i18n.translate('xpack.lens.formula.value', { defaultMessage: 'value' }), @@ -476,6 +500,7 @@ Example: Calculate side length based on area }), }, square: { + section: 'math', positionalArguments: [ { name: i18n.translate('xpack.lens.formula.value', { defaultMessage: 'value' }), @@ -492,6 +517,7 @@ Example: Calculate area based on side length }), }, pick_max: { + section: 'math', positionalArguments: [ { name: i18n.translate('xpack.lens.formula.left', { defaultMessage: 'left' }), @@ -512,6 +538,7 @@ Example: Find the maximum between two fields averages }), }, pick_min: { + section: 'math', positionalArguments: [ { name: i18n.translate('xpack.lens.formula.left', { defaultMessage: 'left' }), @@ -532,6 +559,7 @@ Example: Find the minimum between two fields averages }), }, defaults: { + section: 'math', positionalArguments: [ { name: i18n.translate('xpack.lens.formula.value', { defaultMessage: 'value' }), @@ -548,11 +576,170 @@ Returns a default numeric value when value is null. Example: Return -1 when a field has no data \`defaults(average(bytes), -1)\` +`, + }), + }, + lt: { + section: 'comparison', + positionalArguments: [ + { + name: i18n.translate('xpack.lens.formula.left', { defaultMessage: 'left' }), + type: getTypeI18n('number'), + }, + { + name: i18n.translate('xpack.lens.formula.right', { defaultMessage: 'right' }), + type: getTypeI18n('number'), + }, + ], + outputType: getTypeI18n('boolean'), + help: i18n.translate('xpack.lens.formula.ltFunction.markdown', { + defaultMessage: ` +Performs a lower than comparison between two values. +To be used as condition for \`ifelse\` comparison function. +Also works with \`<\` symbol. + +Example: Returns true if the average of bytes is lower than the average amount of memory +\`average(bytes) <= average(memory)\` + +Example: \`lt(average(bytes), 1000)\` + `, + }), + }, + gt: { + section: 'comparison', + positionalArguments: [ + { + name: i18n.translate('xpack.lens.formula.left', { defaultMessage: 'left' }), + type: getTypeI18n('number'), + }, + { + name: i18n.translate('xpack.lens.formula.right', { defaultMessage: 'right' }), + type: getTypeI18n('number'), + }, + ], + outputType: getTypeI18n('boolean'), + help: i18n.translate('xpack.lens.formula.gtFunction.markdown', { + defaultMessage: ` +Performs a greater than comparison between two values. +To be used as condition for \`ifelse\` comparison function. +Also works with \`>\` symbol. + +Example: Returns true if the average of bytes is greater than the average amount of memory +\`average(bytes) > average(memory)\` + +Example: \`gt(average(bytes), 1000)\` + `, + }), + }, + eq: { + section: 'comparison', + positionalArguments: [ + { + name: i18n.translate('xpack.lens.formula.left', { defaultMessage: 'left' }), + type: getTypeI18n('number'), + }, + { + name: i18n.translate('xpack.lens.formula.right', { defaultMessage: 'right' }), + type: getTypeI18n('number'), + }, + ], + outputType: getTypeI18n('boolean'), + help: i18n.translate('xpack.lens.formula.eqFunction.markdown', { + defaultMessage: ` +Performs an equality comparison between two values. +To be used as condition for \`ifelse\` comparison function. +Also works with \`==\` symbol. + +Example: Returns true if the average of bytes is exactly the same amount of average memory +\`average(bytes) == average(memory)\` + +Example: \`eq(sum(bytes), 1000000)\` + `, + }), + }, + lte: { + section: 'comparison', + positionalArguments: [ + { + name: i18n.translate('xpack.lens.formula.left', { defaultMessage: 'left' }), + type: getTypeI18n('number'), + }, + { + name: i18n.translate('xpack.lens.formula.right', { defaultMessage: 'right' }), + type: getTypeI18n('number'), + }, + ], + outputType: getTypeI18n('boolean'), + help: i18n.translate('xpack.lens.formula.lteFunction.markdown', { + defaultMessage: ` +Performs a lower than or equal comparison between two values. +To be used as condition for \`ifelse\` comparison function. +Also works with \`<=\` symbol. + +Example: Returns true if the average of bytes is lower than or equal to the average amount of memory +\`average(bytes) <= average(memory)\` + +Example: \`lte(average(bytes), 1000)\` + `, + }), + }, + gte: { + section: 'comparison', + positionalArguments: [ + { + name: i18n.translate('xpack.lens.formula.left', { defaultMessage: 'left' }), + type: getTypeI18n('number'), + }, + { + name: i18n.translate('xpack.lens.formula.right', { defaultMessage: 'right' }), + type: getTypeI18n('number'), + }, + ], + outputType: getTypeI18n('boolean'), + help: i18n.translate('xpack.lens.formula.gteFunction.markdown', { + defaultMessage: ` +Performs a greater than comparison between two values. +To be used as condition for \`ifelse\` comparison function. +Also works with \`>=\` symbol. + +Example: Returns true if the average of bytes is greater than or equal to the average amount of memory +\`average(bytes) >= average(memory)\` + +Example: \`gte(average(bytes), 1000)\` + `, + }), + }, + ifelse: { + section: 'comparison', + positionalArguments: [ + { + name: i18n.translate('xpack.lens.formula.condition', { defaultMessage: 'condition' }), + type: getTypeI18n('boolean'), + }, + { + name: i18n.translate('xpack.lens.formula.left', { defaultMessage: 'left' }), + type: getTypeI18n('number'), + }, + { + name: i18n.translate('xpack.lens.formula.right', { defaultMessage: 'right' }), + type: getTypeI18n('number'), + }, + ], + help: i18n.translate('xpack.lens.formula.ifElseFunction.markdown', { + defaultMessage: ` +Returns a value depending on whether the element of condition is true or false. + +Example: Average revenue per customer but in some cases customer id is not provided which counts as additional customer +\`sum(total)/(unique_count(customer_id) + ifelse( count() > count(kql='customer_id:*'), 1, 0))\` `, }), }, }; +export function nonNullable(v: T): v is NonNullable { + return v != null; +} + export function isMathNode(node: TinymathAST | string) { return isObject(node) && node.type === 'function' && tinymathFunctions[node.name]; } @@ -562,7 +749,7 @@ export function findMathNodes(root: TinymathAST | string): TinymathFunction[] { if (!isObject(node) || node.type !== 'function' || !isMathNode(node)) { return []; } - return [node, ...node.args.flatMap(flattenMathNodes)].filter(Boolean); + return [node, ...node.args.flatMap(flattenMathNodes)].filter(nonNullable); } return flattenMathNodes(root); diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/validation.ts b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/validation.ts similarity index 89% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/validation.ts rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/validation.ts index a7ffc57a2361e..1601e53fef33d 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/validation.ts +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/validation.ts @@ -19,6 +19,7 @@ import { getValueOrName, groupArgsByType, isMathNode, + nonNullable, tinymathFunctions, } from './util'; @@ -27,8 +28,8 @@ import type { GenericIndexPatternColumn, GenericOperationDefinition, } from '..'; -import type { IndexPatternLayer } from '../../../types'; -import type { IndexPattern } from '../../../../types'; +import type { FormBasedLayer } from '../../../types'; +import type { IndexPattern } from '../../../../../types'; import type { TinymathNodeTypes } from './types'; interface ValidationErrors { @@ -45,6 +46,10 @@ interface ValidationErrors { message: string; type: { operation: string; params: string }; }; + wrongTypeArgument: { + message: string; + type: { operation: string; name: string; type: string; expectedType: string }; + }; wrongFirstArgument: { message: string; type: { operation: string; type: string; argument: string | number }; @@ -109,6 +114,26 @@ export interface ErrorWrapper { severity?: 'error' | 'warning'; } +function getNodeLocation(node: TinymathFunction): TinymathLocation[] { + return [node.location].filter(nonNullable); +} + +function getArgumentType(arg: TinymathAST, operations: Record) { + if (!isObject(arg)) { + return typeof arg; + } + if (arg.type === 'function') { + if (tinymathFunctions[arg.name]) { + return tinymathFunctions[arg.name].outputType ?? 'number'; + } + // Assume it's a number for now + if (operations[arg.name]) { + return 'number'; + } + } + // leave for now other argument types +} + export function isParsingError(message: string) { return message.includes('Failed to parse expression'); } @@ -118,7 +143,7 @@ function findFunctionNodes(root: TinymathAST | string): TinymathFunction[] { if (!isObject(node) || node.type !== 'function') { return []; } - return [node, ...node.args.flatMap(flattenFunctionNodes)].filter(Boolean); + return [node, ...node.args.flatMap(flattenFunctionNodes)].filter(nonNullable); } return flattenFunctionNodes(root); @@ -132,14 +157,15 @@ export function hasInvalidOperations( return { // avoid duplicates names: Array.from(new Set(nodes.map(({ name }) => name))), - locations: nodes.map(({ location }) => location).filter((a) => a) as TinymathLocation[], + locations: nodes.map(({ location }) => location).filter(nonNullable), }; } export const getRawQueryValidationError = (text: string, operations: Record) => { // try to extract the query context here const singleLine = text.split('\n').join(''); - const allArgs = singleLine.split(',').filter((args) => /(kql|lucene)/.test(args)); + const languagesRegexp = /(kql|lucene)/; + const allArgs = singleLine.split(',').filter((args) => languagesRegexp.test(args)); // check for the presence of a valid ES operation const containsOneValidOperation = Object.keys(operations).some((operation) => singleLine.includes(operation) @@ -153,7 +179,7 @@ export const getRawQueryValidationError = (text: string, operations: Record - arg.split('count').filter((subArg) => /(kql|lucene)/.test(subArg)) + arg.split('count').filter((subArg) => languagesRegexp.test(subArg)) ); const [kqlQueries, luceneQueries] = partition(flattenArgs, (arg) => /kql/.test(arg)); const errors = []; @@ -260,6 +286,18 @@ function getMessageFromId({ values: { operation: out.operation, params: out.params }, }); break; + case 'wrongTypeArgument': + message = i18n.translate('xpack.lens.indexPattern.formulaExpressionWrongTypeArgument', { + defaultMessage: + 'The {name} argument for the operation {operation} in the Formula is of the wrong type: {type} instead of {expectedType}', + values: { + operation: out.operation, + name: out.name, + type: out.type, + expectedType: out.expectedType, + }, + }); + break; case 'duplicateArgument': message = i18n.translate('xpack.lens.indexPattern.formulaOperationDuplicateParams', { defaultMessage: @@ -332,21 +370,20 @@ function getMessageFromId({ break; case 'wrongReturnedType': message = i18n.translate('xpack.lens.indexPattern.formulaOperationWrongReturnedType', { - defaultMessage: - 'The return value type of the operation {text} is not supported in Formula.', + defaultMessage: 'The return value type of the operation {text} is not supported in Formula', values: { text: out.text }, }); break; case 'filtersTypeConflict': message = i18n.translate('xpack.lens.indexPattern.formulaOperationFiltersTypeConflicts', { defaultMessage: - 'The Formula filter of type "{outerType}" is not compatible with the inner filter of type "{innerType}" from the {operation} operation.', + 'The Formula filter of type "{outerType}" is not compatible with the inner filter of type "{innerType}" from the {operation} operation', values: { operation: out.operation, outerType: out.outerType, innerType: out.innerType }, }); break; case 'useAlternativeFunction': message = i18n.translate('xpack.lens.indexPattern.formulaUseAlternative', { - defaultMessage: `The operation {operation} in the Formula is missing the {params} argument: use the {alternativeFn} operation instead.`, + defaultMessage: `The operation {operation} in the Formula is missing the {params} argument: use the {alternativeFn} operation instead`, values: { operation: out.operation, params: out.params, alternativeFn: out.alternativeFn }, }); break; @@ -397,13 +434,14 @@ export function tryToParse( export function runASTValidation( ast: TinymathAST, - layer: IndexPatternLayer, + layer: FormBasedLayer, indexPattern: IndexPattern, operations: Record, currentColumn: GenericIndexPatternColumn ) { return [ ...checkMissingVariableOrFunctions(ast, layer, indexPattern, operations), + ...checkTopNodeReturnType(ast), ...runFullASTValidation(ast, layer, indexPattern, operations, currentColumn), ]; } @@ -426,7 +464,7 @@ function checkVariableEdgeCases(ast: TinymathAST, missingVariables: Set) function checkMissingVariableOrFunctions( ast: TinymathAST, - layer: IndexPatternLayer, + layer: FormBasedLayer, indexPattern: IndexPattern, operations: Record ): ErrorWrapper[] { @@ -548,7 +586,7 @@ function validateFiltersArguments( innerType, outerType, }, - locations: node.location ? [node.location] : [], + locations: getNodeLocation(node), }) ); } @@ -574,7 +612,7 @@ function validateNameArguments( operation: node.name, params: missingParams.map(({ name }) => name).join(', '), }, - locations: node.location ? [node.location] : [], + locations: getNodeLocation(node), }) ); } @@ -587,7 +625,7 @@ function validateNameArguments( operation: node.name, params: wrongTypeParams.map(({ name }) => name).join(', '), }, - locations: node.location ? [node.location] : [], + locations: getNodeLocation(node), }) ); } @@ -600,7 +638,7 @@ function validateNameArguments( operation: node.name, params: duplicateParams.join(', '), }, - locations: node.location ? [node.location] : [], + locations: getNodeLocation(node), }) ); } @@ -614,16 +652,37 @@ function validateNameArguments( getMessageFromId({ messageId: 'tooManyQueries', values: {}, - locations: node.location ? [node.location] : [], + locations: getNodeLocation(node), }) ); } return errors; } +const DEFAULT_RETURN_TYPE = 'number'; +function checkTopNodeReturnType(ast: TinymathAST): ErrorWrapper[] { + if ( + isObject(ast) && + ast.type === 'function' && + ast.text && + (tinymathFunctions[ast.name]?.outputType || DEFAULT_RETURN_TYPE) !== DEFAULT_RETURN_TYPE + ) { + return [ + getMessageFromId({ + messageId: 'wrongReturnedType', + values: { + text: ast.text, + }, + locations: getNodeLocation(ast), + }), + ]; + } + return []; +} + function runFullASTValidation( ast: TinymathAST, - layer: IndexPatternLayer, + layer: FormBasedLayer, indexPattern: IndexPattern, operations: Record, currentColumn?: GenericIndexPatternColumn @@ -645,7 +704,7 @@ function runFullASTValidation( const [firstArg] = node?.args || []; if (!nodeOperation) { - errors.push(...validateMathNodes(node, missingVariablesSet)); + errors.push(...validateMathNodes(node, missingVariablesSet, operations)); // carry on with the validation for all the functions within the math operation if (functions?.length) { return errors.concat(functions.flatMap((fn) => validateNode(fn))); @@ -664,7 +723,7 @@ function runFullASTValidation( }), argument: `math operation`, }, - locations: node.location ? [node.location] : [], + locations: getNodeLocation(node), }) ); } else { @@ -683,7 +742,7 @@ function runFullASTValidation( defaultMessage: 'no field', }), }, - locations: node.location ? [node.location] : [], + locations: getNodeLocation(node), }) ); } @@ -716,7 +775,7 @@ function runFullASTValidation( values: { operation: node.name, }, - locations: node.location ? [node.location] : [], + locations: getNodeLocation(node), }) ); } else { @@ -742,7 +801,8 @@ function runFullASTValidation( // In general this should be handled down the Esaggs route rather than here const isFirstArgumentNotValid = Boolean( !isArgumentValidType(firstArg, 'function') || - (isMathNode(firstArg) && validateMathNodes(firstArg, missingVariablesSet).length) + (isMathNode(firstArg) && + validateMathNodes(firstArg, missingVariablesSet, operations).length) ); // First field has a special handling if (isFirstArgumentNotValid) { @@ -760,7 +820,7 @@ function runFullASTValidation( defaultMessage: 'no operation', }), }, - locations: node.location ? [node.location] : [], + locations: getNodeLocation(node), }) ); } @@ -786,7 +846,7 @@ function runFullASTValidation( values: { operation: node.name, }, - locations: node.location ? [node.location] : [], + locations: getNodeLocation(node), }) ); } else { @@ -946,22 +1006,27 @@ export function isArgumentValidType(arg: TinymathAST | string, type: TinymathNod return isObject(arg) && arg.type === type; } -export function validateMathNodes(root: TinymathAST, missingVariableSet: Set) { +export function validateMathNodes( + root: TinymathAST, + missingVariableSet: Set, + operations: Record +) { const mathNodes = findMathNodes(root); const errors: ErrorWrapper[] = []; mathNodes.forEach((node: TinymathFunction) => { const { positionalArguments } = tinymathFunctions[node.name]; + const mandatoryArguments = positionalArguments.filter(({ optional }) => !optional); if (!node.args.length) { // we can stop here return errors.push( getMessageFromId({ - messageId: 'wrongFirstArgument', + messageId: 'missingMathArgument', values: { operation: node.name, - type: 'operation', - argument: `()`, + count: mandatoryArguments.length, + params: mandatoryArguments.map(({ name }) => name).join(', '), }, - locations: node.location ? [node.location] : [], + locations: getNodeLocation(node), }) ); } @@ -973,12 +1038,12 @@ export function validateMathNodes(root: TinymathAST, missingVariableSet: Set { const arg = node.args[index]; if (arg != null && typeof arg !== 'number') { @@ -992,12 +1057,11 @@ export function validateMathNodes(root: TinymathAST, missingVariableSet: Set !optional); // if there is only 1 mandatory arg, this is already handled by the wrongFirstArgument check if (mandatoryArguments.length > 1 && node.args.length < mandatoryArguments.length) { const missingArgs = mandatoryArguments.filter((_, i) => node.args[i] == null); @@ -1020,7 +1084,7 @@ export function validateMathNodes(root: TinymathAST, missingVariableSet: Set name).join(', '), }, - locations: node.location ? [node.location] : [], + locations: getNodeLocation(node), }) ); } @@ -1035,11 +1099,37 @@ export function validateMathNodes(root: TinymathAST, missingVariableSet: Set { + const arg = node.args[index]; + if (arg != null) { + const argType = getArgumentType(arg, operations); + if (argType && argType !== type) { + return index; + } + } + }) + .filter(nonNullable); + for (const wrongTypeArgumentIndex of wrongTypeArgumentIndexes) { + const arg = node.args[wrongTypeArgumentIndex]; + errors.push( + getMessageFromId({ + messageId: 'wrongTypeArgument', + values: { + operation: node.name, + name: positionalArguments[wrongTypeArgumentIndex].name, + type: getArgumentType(arg, operations) || 'number', + expectedType: positionalArguments[wrongTypeArgumentIndex].type || '', + }, + locations: getNodeLocation(node), + }) + ); + } }); return errors; } @@ -1073,7 +1163,7 @@ function validateFieldArguments( supported: 1, text: (fields as TinymathVariable[]).map(({ text }) => text).join(', '), }, - locations: node.location ? [node.location] : [], + locations: getNodeLocation(node), }) ); } @@ -1085,7 +1175,7 @@ function validateFieldArguments( values: { text: node.text ?? `${node.name}(${getValueOrName(firstArg)})`, }, - locations: node.location ? [node.location] : [], + locations: getNodeLocation(node), }) ); } @@ -1101,7 +1191,7 @@ function validateFieldArguments( defaultMessage: 'field', }), }, - locations: node.location ? [node.location] : [], + locations: getNodeLocation(node), }) ); } @@ -1133,7 +1223,7 @@ function validateFunctionArguments( defaultMessage: 'metric', }), }, - locations: node.location ? [node.location] : [], + locations: getNodeLocation(node), }) ); } else { @@ -1146,7 +1236,7 @@ function validateFunctionArguments( supported: requiredFunctions, text: (esOperations as TinymathFunction[]).map(({ text }) => text).join(', '), }, - locations: node.location ? [node.location] : [], + locations: getNodeLocation(node), }) ); } @@ -1164,7 +1254,7 @@ function validateFunctionArguments( type, text: (mathOperations as TinymathFunction[]).map(({ text }) => text).join(', '), }, - locations: node.location ? [node.location] : [], + locations: getNodeLocation(node), }) ); } diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/get_group_by_key.ts b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/get_group_by_key.ts similarity index 100% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/get_group_by_key.ts rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/get_group_by_key.ts diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/helpers.test.ts b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/helpers.test.ts similarity index 100% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/helpers.test.ts rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/helpers.test.ts diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/helpers.tsx b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/helpers.tsx similarity index 96% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/helpers.tsx rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/helpers.tsx index 868d5e2557e49..32d39f9527ef4 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/helpers.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/helpers.tsx @@ -6,14 +6,14 @@ */ import { i18n } from '@kbn/i18n'; -import type { IndexPattern, IndexPatternField } from '../../../types'; +import type { IndexPattern, IndexPatternField } from '../../../../types'; import { GenericIndexPatternColumn, operationDefinitionMap } from '.'; import { FieldBasedIndexPatternColumn, FormattedIndexPatternColumn, ReferenceBasedIndexPatternColumn, } from './column_types'; -import type { IndexPatternLayer } from '../../types'; +import type { FormBasedLayer } from '../../types'; import { hasField } from '../../pure_utils'; export function getInvalidFieldMessage( @@ -132,8 +132,8 @@ export function isColumnOfType( export const isColumn = ( setter: | GenericIndexPatternColumn - | IndexPatternLayer - | ((prevLayer: IndexPatternLayer) => IndexPatternLayer) + | FormBasedLayer + | ((prevLayer: FormBasedLayer) => FormBasedLayer) ): setter is GenericIndexPatternColumn => { return 'operationType' in setter; }; diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/index.ts b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/index.ts similarity index 95% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/index.ts rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/index.ts index bde67ea14a488..5253267b286cd 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/index.ts +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/index.ts @@ -55,17 +55,17 @@ import { IndexPatternField, OperationMetadata, ParamEditorCustomProps, -} from '../../../types'; +} from '../../../../types'; import type { BaseIndexPatternColumn, IncompleteColumn, GenericIndexPatternColumn, ReferenceBasedIndexPatternColumn, } from './column_types'; -import { DataViewDragDropOperation, IndexPatternLayer } from '../../types'; -import { DateRange, LayerType } from '../../../../common'; +import { DataViewDragDropOperation, FormBasedLayer } from '../../types'; +import { DateRange, LayerType } from '../../../../../common'; import { rangeOperation } from './ranges'; -import { IndexPatternDimensionEditorProps, OperationSupportMatrix } from '../../dimension_panel'; +import { FormBasedDimensionEditorProps, OperationSupportMatrix } from '../../dimension_panel'; import type { OriginalColumn } from '../../to_expression'; import { ReferenceEditorProps } from '../../dimension_panel/reference_editor'; @@ -174,10 +174,10 @@ export { staticValueOperation } from './static_value'; */ export interface ParamEditorProps< C, - U = IndexPatternLayer | ((prevLayer: IndexPatternLayer) => IndexPatternLayer) + U = FormBasedLayer | ((prevLayer: FormBasedLayer) => FormBasedLayer) > { currentColumn: C; - layer: IndexPatternLayer; + layer: FormBasedLayer; paramEditorUpdater: (setter: U) => void; ReferenceEditor?: (props: ReferenceEditorProps) => JSX.Element | null; toggleFullscreen: () => void; @@ -195,7 +195,7 @@ export interface ParamEditorProps< fieldFormats: FieldFormatsStart; unifiedSearch: UnifiedSearchPublicPluginStart; dataViews: DataViewsPublicPluginStart; - activeData?: IndexPatternDimensionEditorProps['activeData']; + activeData?: FormBasedDimensionEditorProps['activeData']; operationDefinitionMap: Record; paramEditorCustomProps?: ParamEditorCustomProps; existingFields: Record>; @@ -203,20 +203,18 @@ export interface ParamEditorProps< } export interface FieldInputProps { - layer: IndexPatternLayer; + layer: FormBasedLayer; selectedColumn?: C; columnId: string; indexPattern: IndexPattern; - updateLayer: ( - setter: IndexPatternLayer | ((prevLayer: IndexPatternLayer) => IndexPatternLayer) - ) => void; + updateLayer: (setter: FormBasedLayer | ((prevLayer: FormBasedLayer) => FormBasedLayer)) => void; onDeleteColumn?: () => void; currentFieldIsInvalid: boolean; incompleteField: IncompleteColumn['sourceField'] | null; incompleteOperation: IncompleteColumn['operationType']; incompleteParams: Omit; - dimensionGroups: IndexPatternDimensionEditorProps['dimensionGroups']; - groupId: IndexPatternDimensionEditorProps['groupId']; + dimensionGroups: FormBasedDimensionEditorProps['dimensionGroups']; + groupId: FormBasedDimensionEditorProps['groupId']; /** * indexPatternId -> fieldName -> boolean */ @@ -271,7 +269,7 @@ interface BaseOperationDefinitionProps< * Based on the current column and the other updated columns, this function has to * return an updated column. If not implemented, the `id` function is used instead. */ - onOtherColumnChanged?: (layer: IndexPatternLayer, thisColumnId: string) => C; + onOtherColumnChanged?: (layer: FormBasedLayer, thisColumnId: string) => C; /** * React component for operation specific settings shown in the flyout editor */ @@ -303,7 +301,7 @@ interface BaseOperationDefinitionProps< */ getDisabledStatus?: ( indexPattern: IndexPattern, - layer: IndexPatternLayer, + layer: FormBasedLayer, layerType?: LayerType ) => string | undefined; /** @@ -313,7 +311,7 @@ interface BaseOperationDefinitionProps< * - Missing references */ getErrorMessage?: ( - layer: IndexPatternLayer, + layer: FormBasedLayer, columnId: string, indexPattern: IndexPattern, operationDefinitionMap?: Record @@ -329,7 +327,7 @@ interface BaseOperationDefinitionProps< core: CoreStart, frame: FrameDatasourceAPI, layerId: string - ) => Promise; + ) => Promise; }; } > @@ -453,7 +451,7 @@ interface BaseOperationDefinitionProps< } interface BaseBuildColumnArgs { - layer: IndexPatternLayer; + layer: FormBasedLayer; indexPattern: IndexPattern; } @@ -499,7 +497,7 @@ interface FieldlessOperationDefinition column: C, columnId: string, indexPattern: IndexPattern, - layer: IndexPatternLayer, + layer: FormBasedLayer, uiSettings: IUiSettingsClient ) => ExpressionAstFunction; } @@ -556,7 +554,7 @@ interface FieldBasedOperationDefinition @@ -568,7 +566,7 @@ interface FieldBasedOperationDefinition @@ -584,7 +582,7 @@ interface FieldBasedOperationDefinition Promise; + ) => Promise; }; } > @@ -652,7 +650,7 @@ interface FullReferenceOperationDefinition { * A chain of expression functions which will transform the table */ toExpression: ( - layer: IndexPatternLayer, + layer: FormBasedLayer, columnId: string, indexPattern: IndexPattern ) => ExpressionAstFunction[]; @@ -680,7 +678,7 @@ interface ManagedReferenceOperationDefinition * A chain of expression functions which will transform the table */ toExpression: ( - layer: IndexPatternLayer, + layer: FormBasedLayer, columnId: string, indexPattern: IndexPattern ) => ExpressionAstFunction[]; @@ -689,11 +687,11 @@ interface ManagedReferenceOperationDefinition * root level */ createCopy: ( - layers: Record, + layers: Record, source: DataViewDragDropOperation, target: DataViewDragDropOperation, operationDefinitionMap: Record - ) => Record; + ) => Record; } interface OperationDefinitionMap { diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/last_value.test.tsx b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/last_value.test.tsx similarity index 99% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/last_value.test.tsx rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/last_value.test.tsx index 05386492544f4..16c6f2727ea50 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/last_value.test.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/last_value.test.tsx @@ -17,8 +17,8 @@ import { dataViewPluginMocks } from '@kbn/data-views-plugin/public/mocks'; import { createMockedIndexPattern } from '../../mocks'; import { LastValueIndexPatternColumn } from './last_value'; import { lastValueOperation } from '.'; -import type { IndexPatternLayer } from '../../types'; -import type { IndexPattern } from '../../../types'; +import type { FormBasedLayer } from '../../types'; +import type { IndexPattern } from '../../../../types'; import { TermsIndexPatternColumn } from './terms'; import { EuiSwitch, EuiSwitchEvent } from '@elastic/eui'; import { buildExpression, parseExpression } from '@kbn/expressions-plugin/common'; @@ -55,7 +55,7 @@ const defaultProps = { }; describe('last_value', () => { - let layer: IndexPatternLayer; + let layer: FormBasedLayer; const InlineOptions = lastValueOperation.paramEditor!; beforeEach(() => { @@ -506,7 +506,7 @@ describe('last_value', () => { }, columnOrder: [], indexPatternId: '', - } as IndexPatternLayer; + } as FormBasedLayer; expect( lastValueOperation.buildColumn({ @@ -829,7 +829,7 @@ describe('last_value', () => { describe('getErrorMessage', () => { let indexPattern: IndexPattern; - let errorLayer: IndexPatternLayer; + let errorLayer: FormBasedLayer; beforeEach(() => { indexPattern = createMockedIndexPattern(); errorLayer = { diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/last_value.tsx b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/last_value.tsx similarity index 99% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/last_value.tsx rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/last_value.tsx index 4206cd8109760..59b77cd73fc9d 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/last_value.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/last_value.tsx @@ -20,8 +20,8 @@ import { AggFunctionsMapping } from '@kbn/data-plugin/public'; import { buildExpressionFunction } from '@kbn/expressions-plugin/public'; import { OperationDefinition } from '.'; import { FieldBasedIndexPatternColumn, ValueFormatConfig } from './column_types'; -import type { IndexPatternField, IndexPattern } from '../../../types'; -import { DataType } from '../../../types'; +import type { IndexPatternField, IndexPattern } from '../../../../types'; +import { DataType } from '../../../../types'; import { getFormatFromPreviousColumn, getInvalidFieldMessage, diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/metrics.test.ts b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/metrics.test.ts similarity index 100% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/metrics.test.ts rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/metrics.test.ts diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/metrics.tsx b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/metrics.tsx similarity index 100% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/metrics.tsx rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/metrics.tsx diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/percentile.test.tsx b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/percentile.test.tsx similarity index 99% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/percentile.test.tsx rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/percentile.test.tsx index 77434d7ecc7ad..e78ac9e9360da 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/percentile.test.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/percentile.test.tsx @@ -18,7 +18,7 @@ import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; import { dataViewPluginMocks } from '@kbn/data-views-plugin/public/mocks'; import { createMockedIndexPattern } from '../../mocks'; import { percentileOperation } from '.'; -import { IndexPatternLayer } from '../../types'; +import { FormBasedLayer } from '../../types'; import { PercentileIndexPatternColumn } from './percentile'; import { TermsIndexPatternColumn } from './terms'; import { @@ -27,7 +27,7 @@ import { ExpressionAstExpressionBuilder, } from '@kbn/expressions-plugin/public'; import type { OriginalColumn } from '../../to_expression'; -import { IndexPattern } from '../../../types'; +import { IndexPattern } from '../../../../types'; import faker from 'faker'; jest.mock('lodash', () => { @@ -71,7 +71,7 @@ const defaultProps = { }; describe('percentile', () => { - let layer: IndexPatternLayer; + let layer: FormBasedLayer; const InlineOptions = percentileOperation.paramEditor!; beforeEach(() => { diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/percentile.tsx b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/percentile.tsx similarity index 99% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/percentile.tsx rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/percentile.tsx index ec4a3d569e7da..f391e3a6f9a2f 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/percentile.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/percentile.tsx @@ -28,7 +28,7 @@ import { } from './helpers'; import { FieldBasedIndexPatternColumn } from './column_types'; import { adjustTimeScaleLabelSuffix } from '../time_scale_utils'; -import { useDebouncedValue } from '../../../shared_components'; +import { useDebouncedValue } from '../../../../shared_components'; import { getDisallowedPreviousShiftMessage } from '../../time_shift_utils'; import { FormRow } from './shared_components'; import { getColumnReducedTimeRangeError } from '../../reduced_time_range_utils'; diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/percentile_ranks.test.tsx b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/percentile_ranks.test.tsx similarity index 98% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/percentile_ranks.test.tsx rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/percentile_ranks.test.tsx index a0c69a7354849..adb0d8e491fd7 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/percentile_ranks.test.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/percentile_ranks.test.tsx @@ -18,10 +18,10 @@ import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; import { dataViewPluginMocks } from '@kbn/data-views-plugin/public/mocks'; import { createMockedIndexPattern } from '../../mocks'; import { percentileRanksOperation } from '.'; -import { IndexPatternLayer } from '../../types'; +import { FormBasedLayer } from '../../types'; import type { PercentileRanksIndexPatternColumn } from './percentile_ranks'; import { TermsIndexPatternColumn } from './terms'; -import { IndexPattern } from '../../../types'; +import { IndexPattern } from '../../../../types'; jest.mock('lodash', () => { const original = jest.requireActual('lodash'); @@ -64,7 +64,7 @@ const defaultProps = { }; describe('percentile ranks', () => { - let layer: IndexPatternLayer; + let layer: FormBasedLayer; const InlineOptions = percentileRanksOperation.paramEditor!; beforeEach(() => { diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/percentile_ranks.tsx b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/percentile_ranks.tsx similarity index 99% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/percentile_ranks.tsx rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/percentile_ranks.tsx index 45bd05f37372f..3d7b12802858c 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/percentile_ranks.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/percentile_ranks.tsx @@ -22,7 +22,7 @@ import { } from './helpers'; import { FieldBasedIndexPatternColumn } from './column_types'; import { adjustTimeScaleLabelSuffix } from '../time_scale_utils'; -import { useDebouncedValue } from '../../../shared_components'; +import { useDebouncedValue } from '../../../../shared_components'; import { getDisallowedPreviousShiftMessage } from '../../time_shift_utils'; import { FormRow } from './shared_components'; import { getColumnReducedTimeRangeError } from '../../reduced_time_range_utils'; diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/ranges/advanced_editor.scss b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/ranges/advanced_editor.scss similarity index 100% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/ranges/advanced_editor.scss rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/ranges/advanced_editor.scss diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/ranges/advanced_editor.tsx b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/ranges/advanced_editor.tsx similarity index 99% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/ranges/advanced_editor.tsx rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/ranges/advanced_editor.tsx index d3f5000646bc9..c3212642e0064 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/ranges/advanced_editor.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/ranges/advanced_editor.tsx @@ -28,7 +28,7 @@ import { DraggableBucketContainer, NewBucketButton, useDebounceWithOptions, -} from '../../../../shared_components'; +} from '../../../../../shared_components'; import { RangeTypeLens, isValidRange } from './ranges'; import { FROM_PLACEHOLDER, TO_PLACEHOLDER, TYPING_DEBOUNCE_TIME } from './constants'; import { LabelInput } from '../shared_components'; diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/ranges/constants.ts b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/ranges/constants.ts similarity index 100% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/ranges/constants.ts rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/ranges/constants.ts diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/ranges/index.ts b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/ranges/index.ts similarity index 100% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/ranges/index.ts rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/ranges/index.ts diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/ranges/range_editor.tsx b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/ranges/range_editor.tsx similarity index 99% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/ranges/range_editor.tsx rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/ranges/range_editor.tsx index 92f0196b9cbb5..1f7565c9d31d6 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/ranges/range_editor.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/ranges/range_editor.tsx @@ -26,7 +26,7 @@ import { UI_SETTINGS } from '@kbn/data-plugin/public'; import { RangeColumnParams, UpdateParamsFnType, MODES_TYPES } from './ranges'; import { AdvancedRangeEditor } from './advanced_editor'; import { TYPING_DEBOUNCE_TIME, MODES, MIN_HISTOGRAM_BARS } from './constants'; -import { useDebounceWithOptions } from '../../../../shared_components'; +import { useDebounceWithOptions } from '../../../../../shared_components'; import { HelpPopover, HelpPopoverButton } from '../../../help_popover'; const GranularityHelpPopover = () => { diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/ranges/ranges.test.tsx b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/ranges/ranges.test.tsx similarity index 99% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/ranges/ranges.test.tsx rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/ranges/ranges.test.tsx index 874559ae66c19..d0dd9f6458612 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/ranges/ranges.test.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/ranges/ranges.test.tsx @@ -15,7 +15,7 @@ import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; import { dataViewPluginMocks } from '@kbn/data-views-plugin/public/mocks'; import { fieldFormatsServiceMock } from '@kbn/field-formats-plugin/public/mocks'; import { unifiedSearchPluginMock } from '@kbn/unified-search-plugin/public/mocks'; -import type { IndexPatternLayer } from '../../../types'; +import type { FormBasedLayer } from '../../../types'; import { rangeOperation } from '..'; import { RangeIndexPatternColumn } from './ranges'; import { @@ -26,9 +26,9 @@ import { SLICES, } from './constants'; import { RangePopover } from './advanced_editor'; -import { DragDropBuckets } from '../../../../shared_components'; +import { DragDropBuckets } from '../../../../../shared_components'; import { getFieldByNameFactory } from '../../../pure_helpers'; -import { IndexPattern } from '../../../../types'; +import { IndexPattern } from '../../../../../types'; // mocking random id generator function jest.mock('@elastic/eui', () => { @@ -136,7 +136,7 @@ const defaultOptions = { }; describe('ranges', () => { - let layer: IndexPatternLayer; + let layer: FormBasedLayer; const InlineOptions = rangeOperation.paramEditor!; const MAX_HISTOGRAM_VALUE = 100; const GRANULARITY_DEFAULT_VALUE = (MAX_HISTOGRAM_VALUE - MIN_HISTOGRAM_BARS) / 2; @@ -156,7 +156,7 @@ describe('ranges', () => { column.params.type = MODES.Range; } - function getDefaultLayer(): IndexPatternLayer { + function getDefaultLayer(): FormBasedLayer { return { indexPatternId: '1', columnOrder: ['col1', 'col2'], diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/ranges/ranges.tsx b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/ranges/ranges.tsx similarity index 98% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/ranges/ranges.tsx rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/ranges/ranges.tsx index 52c9471aefe0e..2dab571dcfc39 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/ranges/ranges.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/ranges/ranges.tsx @@ -15,9 +15,9 @@ import { RangeEditor } from './range_editor'; import { OperationDefinition } from '..'; import { FieldBasedIndexPatternColumn } from '../column_types'; import { updateColumnParam } from '../../layer_helpers'; -import { supportedFormats } from '../../../../../common/expressions/format_column/supported_formats'; +import { supportedFormats } from '../../../../../../common/expressions/format_column/supported_formats'; import { MODES, AUTO_BARS, DEFAULT_INTERVAL, MIN_HISTOGRAM_BARS, SLICES } from './constants'; -import { IndexPattern, IndexPatternField } from '../../../../types'; +import { IndexPattern, IndexPatternField } from '../../../../../types'; import { getInvalidFieldMessage, isValidNumber } from '../helpers'; type RangeType = Omit; diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/shared_components/form_row.scss b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/shared_components/form_row.scss similarity index 100% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/shared_components/form_row.scss rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/shared_components/form_row.scss diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/shared_components/form_row.tsx b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/shared_components/form_row.tsx similarity index 100% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/shared_components/form_row.tsx rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/shared_components/form_row.tsx diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/shared_components/index.tsx b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/shared_components/index.tsx similarity index 100% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/shared_components/index.tsx rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/shared_components/index.tsx diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/shared_components/label_input.tsx b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/shared_components/label_input.tsx similarity index 96% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/shared_components/label_input.tsx rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/shared_components/label_input.tsx index 4bc461aaa319b..9d8730d38216a 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/shared_components/label_input.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/shared_components/label_input.tsx @@ -8,7 +8,7 @@ import React, { useRef } from 'react'; import { EuiFieldText, keys } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { useDebouncedValue } from '../../../../shared_components'; +import { useDebouncedValue } from '../../../../../shared_components'; export const LabelInput = ({ value, diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/static_value.test.tsx b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/static_value.test.tsx similarity index 98% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/static_value.test.tsx rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/static_value.test.tsx index a93b1ece5e13f..0ed6a60677f73 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/static_value.test.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/static_value.test.tsx @@ -17,8 +17,8 @@ import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; import { dataViewPluginMocks } from '@kbn/data-views-plugin/public/mocks'; import { createMockedIndexPattern } from '../../mocks'; import { staticValueOperation } from '.'; -import { IndexPatternLayer } from '../../types'; -import { IndexPattern } from '../../../types'; +import { FormBasedLayer } from '../../types'; +import { IndexPattern } from '../../../../types'; import { StaticValueIndexPatternColumn } from './static_value'; import { TermsIndexPatternColumn } from './terms'; @@ -63,7 +63,7 @@ const defaultProps = { }; describe('static_value', () => { - let layer: IndexPatternLayer; + let layer: FormBasedLayer; beforeEach(() => { layer = { @@ -97,7 +97,7 @@ describe('static_value', () => { }; }); - function getLayerWithStaticValue(newValue: string | null | undefined): IndexPatternLayer { + function getLayerWithStaticValue(newValue: string | null | undefined): FormBasedLayer { return { ...layer, columns: { @@ -377,7 +377,7 @@ describe('static_value', () => { }, } as StaticValueIndexPatternColumn, }, - } as IndexPatternLayer; + } as FormBasedLayer; const instance = shallow( { - let layer: IndexPatternLayer; + let layer: FormBasedLayer; const InlineOptions = termsOperation.paramEditor!; const InlineFieldInput = termsOperation.renderFieldInput!; @@ -1187,7 +1187,7 @@ describe('terms', () => { return getOperationSupportMatrix({ state: { layers: { layer1: layer }, - } as unknown as IndexPatternPrivateState, + } as unknown as FormBasedPrivateState, layerId: 'layer1', filterOperations: () => true, columnId, diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms/types.ts b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/terms/types.ts similarity index 100% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms/types.ts rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/terms/types.ts diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms/values_input.test.tsx b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/terms/values_input.test.tsx similarity index 100% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms/values_input.test.tsx rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/terms/values_input.test.tsx diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms/values_input.tsx b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/terms/values_input.tsx similarity index 97% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms/values_input.tsx rename to x-pack/plugins/lens/public/datasources/form_based/operations/definitions/terms/values_input.tsx index 9e86ea8525adc..33dd5b7206008 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms/values_input.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/terms/values_input.tsx @@ -8,7 +8,7 @@ import React, { useState } from 'react'; import { i18n } from '@kbn/i18n'; import { EuiFieldNumber, EuiFormRow } from '@elastic/eui'; -import { useDebounceWithOptions } from '../../../../shared_components'; +import { useDebounceWithOptions } from '../../../../../shared_components'; export const ValuesInput = ({ value, diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/index.ts b/x-pack/plugins/lens/public/datasources/form_based/operations/index.ts similarity index 100% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/index.ts rename to x-pack/plugins/lens/public/datasources/form_based/operations/index.ts diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/layer_helpers.test.ts b/x-pack/plugins/lens/public/datasources/form_based/operations/layer_helpers.test.ts similarity index 97% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/layer_helpers.test.ts rename to x-pack/plugins/lens/public/datasources/form_based/operations/layer_helpers.test.ts index 1a77cd253424f..65b11c2605cc3 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/layer_helpers.test.ts +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/layer_helpers.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { OperationMetadata } from '../../types'; +import type { OperationMetadata } from '../../../types'; import { copyColumn, insertNewColumn, @@ -23,10 +23,10 @@ import { operationDefinitionMap, OperationType } from '.'; import { TermsIndexPatternColumn } from './definitions/terms'; import { DateHistogramIndexPatternColumn } from './definitions/date_histogram'; import { AvgIndexPatternColumn } from './definitions/metrics'; -import type { IndexPatternLayer, IndexPatternPrivateState } from '../types'; +import type { FormBasedLayer, FormBasedPrivateState } from '../types'; import { documentField } from '../document_field'; import { getFieldByNameFactory } from '../pure_helpers'; -import { generateId } from '../../id_generator'; +import { generateId } from '../../../id_generator'; import { createMockedFullReference, createMockedManagedReference } from './mocks'; import { FiltersIndexPatternColumn, @@ -38,13 +38,13 @@ import { } from './definitions'; import { TinymathAST } from '@kbn/tinymath'; import { CoreStart } from '@kbn/core/public'; -import { IndexPattern } from '../../types'; +import { IndexPattern } from '../../../types'; import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; const dataMock = dataPluginMock.createStartContract(); jest.mock('.'); -jest.mock('../../id_generator'); +jest.mock('../../../id_generator'); jest.mock('../dimension_panel/reference_editor', () => ({ ReferenceEditor: () => null, })); @@ -257,7 +257,7 @@ describe('state_helpers', () => { }); it('should update order on inserting a bucketed fieldless operation', () => { - const layer: IndexPatternLayer = { + const layer: FormBasedLayer = { indexPatternId: '1', columnOrder: ['col1'], columns: { @@ -284,7 +284,7 @@ describe('state_helpers', () => { }); it('should update order on inserting a bucketed field-based operation', () => { - const layer: IndexPatternLayer = { + const layer: FormBasedLayer = { indexPatternId: '1', columnOrder: ['col1'], columns: { @@ -312,7 +312,7 @@ describe('state_helpers', () => { }); it('should insert a metric after buckets', () => { - const layer: IndexPatternLayer = { + const layer: FormBasedLayer = { indexPatternId: '1', columnOrder: ['col1'], columns: { @@ -343,7 +343,7 @@ describe('state_helpers', () => { }); it('should insert a metric after references', () => { - const layer: IndexPatternLayer = { + const layer: FormBasedLayer = { indexPatternId: '1', columnOrder: ['col1'], columns: { @@ -382,7 +382,7 @@ describe('state_helpers', () => { }); it('should insert new buckets at the end of previous buckets', () => { - const layer: IndexPatternLayer = { + const layer: FormBasedLayer = { indexPatternId: '1', columnOrder: ['col1', 'col3'], columns: { @@ -421,7 +421,7 @@ describe('state_helpers', () => { }); it('should not change order of metrics and references on inserting new buckets', () => { - const layer: IndexPatternLayer = { + const layer: FormBasedLayer = { indexPatternId: '1', columnOrder: ['col1', 'col2'], columns: { @@ -665,7 +665,7 @@ describe('state_helpers', () => { specificOperations: [], }, ]; - const layer: IndexPatternLayer = { indexPatternId: '1', columnOrder: [], columns: {} }; + const layer: FormBasedLayer = { indexPatternId: '1', columnOrder: [], columns: {} }; expect(() => { insertNewColumn({ layer, @@ -678,7 +678,7 @@ describe('state_helpers', () => { }); it('should leave the references empty if too ambiguous', () => { - const layer: IndexPatternLayer = { indexPatternId: '1', columnOrder: [], columns: {} }; + const layer: FormBasedLayer = { indexPatternId: '1', columnOrder: [], columns: {} }; const result = insertNewColumn({ layer, indexPattern, @@ -710,7 +710,7 @@ describe('state_helpers', () => { validateMetadata: () => true, }, ]; - const layer: IndexPatternLayer = { indexPatternId: '1', columnOrder: [], columns: {} }; + const layer: FormBasedLayer = { indexPatternId: '1', columnOrder: [], columns: {} }; const result = insertNewColumn({ layer, indexPattern, @@ -728,7 +728,7 @@ describe('state_helpers', () => { }); it('should create a referenced column if the ID is being used as a reference', () => { - const layer: IndexPatternLayer = { + const layer: FormBasedLayer = { indexPatternId: '1', columnOrder: ['col1'], columns: { @@ -825,7 +825,7 @@ describe('state_helpers', () => { }); it('should update order on changing the column', () => { - const layer: IndexPatternLayer = { + const layer: FormBasedLayer = { indexPatternId: '1', columnOrder: ['col1', 'col2'], columns: { @@ -1498,7 +1498,7 @@ describe('state_helpers', () => { operationType: 'count' as const, }; - const layer: IndexPatternLayer = { + const layer: FormBasedLayer = { indexPatternId: '1', columnOrder: ['col1'], columns: { col1: expectedColumn }, @@ -1526,7 +1526,7 @@ describe('state_helpers', () => { }); it('should not wrap around the previous operation as a reference if excluded by validateMetadata (case new1)', () => { - const layer: IndexPatternLayer = { + const layer: FormBasedLayer = { indexPatternId: '1', columnOrder: ['col1'], columns: { @@ -1573,7 +1573,7 @@ describe('state_helpers', () => { const testFilter = { language: 'kuery', query: '' }; - const layer: IndexPatternLayer = { + const layer: FormBasedLayer = { indexPatternId: '1', columnOrder: ['col1'], columns: { col1: { ...expectedColumn, filter: testFilter } }, @@ -1612,7 +1612,7 @@ describe('state_helpers', () => { validateMetadata: () => true, }, ]; - const layer: IndexPatternLayer = { + const layer: FormBasedLayer = { indexPatternId: '1', columnOrder: ['col1'], columns: { @@ -1653,7 +1653,7 @@ describe('state_helpers', () => { specificOperations: ['unique_count', 'sum', 'average'], // this order is ignored }, ]; - const layer: IndexPatternLayer = { + const layer: FormBasedLayer = { indexPatternId: '1', columnOrder: ['col1'], columns: { @@ -1694,7 +1694,7 @@ describe('state_helpers', () => { specificOperations: ['unique_count'], }, ]; - const layer: IndexPatternLayer = { + const layer: FormBasedLayer = { indexPatternId: '1', columnOrder: ['col1'], columns: { @@ -1734,7 +1734,7 @@ describe('state_helpers', () => { specificOperations: [], }, ]; - const layer: IndexPatternLayer = { + const layer: FormBasedLayer = { indexPatternId: '1', columnOrder: ['col1'], columns: { @@ -1804,7 +1804,7 @@ describe('state_helpers', () => { }); it('should use existing references, delete invalid, when switching from one reference to another (case ref1)', () => { - const layer: IndexPatternLayer = { + const layer: FormBasedLayer = { indexPatternId: '1', columnOrder: ['ref1', 'invalid', 'output'], columns: { @@ -1856,7 +1856,7 @@ describe('state_helpers', () => { }); it('should modify a copied object, not the original layer', () => { - const layer: IndexPatternLayer = { + const layer: FormBasedLayer = { indexPatternId: '1', columnOrder: ['ref1', 'invalid', 'output'], columns: { @@ -1907,7 +1907,7 @@ describe('state_helpers', () => { label: 'math', operationType: 'math' as const, }; - const layer: IndexPatternLayer = { + const layer: FormBasedLayer = { indexPatternId: '', columnOrder: [], columns: { @@ -1977,7 +1977,7 @@ describe('state_helpers', () => { }); it('should transition by using the field from the previous reference if nothing else works (case new5)', () => { - const layer: IndexPatternLayer = { + const layer: FormBasedLayer = { indexPatternId: '1', columnOrder: ['fieldReused', 'output'], columns: { @@ -2045,7 +2045,7 @@ describe('state_helpers', () => { ], }, }; - const layer: IndexPatternLayer = { + const layer: FormBasedLayer = { indexPatternId: '1', columnOrder: ['col1', 'col2'], columns: { @@ -2089,7 +2089,7 @@ describe('state_helpers', () => { filter: { language: 'kuery', query: 'bytes > 4000' }, timeShift: '3h', }; - const layer: IndexPatternLayer = { + const layer: FormBasedLayer = { indexPatternId: '1', columnOrder: ['col1', 'col2'], columns: { @@ -2135,7 +2135,7 @@ describe('state_helpers', () => { timeShift: '3h', }; - const layer: IndexPatternLayer = { + const layer: FormBasedLayer = { indexPatternId: '1', columnOrder: ['metric', 'ref'], columns: { @@ -2168,7 +2168,7 @@ describe('state_helpers', () => { }); it('should keep state and set incomplete column on incompatible switch', () => { - const layer: IndexPatternLayer = { + const layer: FormBasedLayer = { indexPatternId: '1', columnOrder: ['metric', 'ref'], columns: { @@ -2272,7 +2272,7 @@ describe('state_helpers', () => { }, ]; - const layer: IndexPatternLayer = { + const layer: FormBasedLayer = { indexPatternId: '1', columnOrder: ['col1', 'col2'], columns: { @@ -2439,7 +2439,7 @@ describe('state_helpers', () => { }); it('should delete the column and all of its references', () => { - const layer: IndexPatternLayer = { + const layer: FormBasedLayer = { indexPatternId: '1', columnOrder: ['col1', 'col2'], columns: { @@ -2467,7 +2467,7 @@ describe('state_helpers', () => { }); it('should update the labels when deleting columns', () => { - const layer: IndexPatternLayer = { + const layer: FormBasedLayer = { indexPatternId: '1', columnOrder: ['col1', 'col2'], columns: { @@ -2512,7 +2512,7 @@ describe('state_helpers', () => { }); it('should recursively delete references', () => { - const layer: IndexPatternLayer = { + const layer: FormBasedLayer = { indexPatternId: '1', columnOrder: ['col1', 'col2', 'col3'], columns: { @@ -2837,7 +2837,7 @@ describe('state_helpers', () => { }); it('should remove operations referencing unavailable fields', () => { - const layer: IndexPatternLayer = { + const layer: FormBasedLayer = { columnOrder: ['col1', 'col2'], columns: { col1: { @@ -2870,7 +2870,7 @@ describe('state_helpers', () => { }); it('should remove operations indirectly referencing unavailable fields', () => { - const layer: IndexPatternLayer = { + const layer: FormBasedLayer = { columnOrder: ['col1', 'col2'], columns: { col1: { @@ -2902,7 +2902,7 @@ describe('state_helpers', () => { }); it('should remove operations referencing fields with insufficient capabilities', () => { - const layer: IndexPatternLayer = { + const layer: FormBasedLayer = { columnOrder: ['col1', 'col2'], columns: { col1: { @@ -2941,7 +2941,7 @@ describe('state_helpers', () => { interval: 'w', }, })) as OperationDefinition['transfer']; - const layer: IndexPatternLayer = { + const layer: FormBasedLayer = { columnOrder: ['col1', 'col2'], columns: { col1: { @@ -2971,7 +2971,7 @@ describe('state_helpers', () => { }); it('should remove operations referencing fields with wrong field types', () => { - const layer: IndexPatternLayer = { + const layer: FormBasedLayer = { columnOrder: ['col1', 'col2'], columns: { col1: { @@ -3004,7 +3004,7 @@ describe('state_helpers', () => { }); it('should remove operations referencing fields with incompatible restrictions', () => { - const layer: IndexPatternLayer = { + const layer: FormBasedLayer = { columnOrder: ['col1', 'col2'], columns: { col1: { @@ -3078,7 +3078,7 @@ describe('state_helpers', () => { }, }, indexPattern, - {} as IndexPatternPrivateState, + {} as FormBasedPrivateState, '1', {} as CoreStart, dataMock @@ -3114,7 +3114,7 @@ describe('state_helpers', () => { }, }, indexPattern, - {} as IndexPatternPrivateState, + {} as FormBasedPrivateState, '1', {} as CoreStart, dataMock @@ -3151,7 +3151,7 @@ describe('state_helpers', () => { }, }, indexPattern, - {} as IndexPatternPrivateState, + {} as FormBasedPrivateState, '1', {} as CoreStart, dataMock @@ -3181,7 +3181,7 @@ describe('state_helpers', () => { }, }, indexPattern, - {} as IndexPatternPrivateState, + {} as FormBasedPrivateState, '1', {} as CoreStart, dataMock @@ -3209,7 +3209,7 @@ describe('state_helpers', () => { describe('hasTermsWithManyBuckets', () => { it('should return false for a bucketed non terms operation', () => { - const layer: IndexPatternLayer = { + const layer: FormBasedLayer = { columnOrder: ['col1'], columns: { col1: { @@ -3230,7 +3230,7 @@ describe('state_helpers', () => { }); it('should return false if all terms operation have a lower size', () => { - const layer: IndexPatternLayer = { + const layer: FormBasedLayer = { columnOrder: ['col1'], columns: { col1: { @@ -3256,7 +3256,7 @@ describe('state_helpers', () => { }); it('should return true if the size is high', () => { - const layer: IndexPatternLayer = { + const layer: FormBasedLayer = { columnOrder: ['col1'], columns: { col1: { @@ -3284,7 +3284,7 @@ describe('state_helpers', () => { describe('isReferenced', () => { it('should return false for top column which has references', () => { - const layer: IndexPatternLayer = { + const layer: FormBasedLayer = { indexPatternId: '1', columnOrder: [], columns: { @@ -3308,7 +3308,7 @@ describe('state_helpers', () => { }); it('should return true for referenced column', () => { - const layer: IndexPatternLayer = { + const layer: FormBasedLayer = { indexPatternId: '1', columnOrder: [], columns: { @@ -3334,7 +3334,7 @@ describe('state_helpers', () => { describe('getReferenceRoot', () => { it("should just return the column id itself if it's not a referenced column", () => { - const layer: IndexPatternLayer = { + const layer: FormBasedLayer = { indexPatternId: '1', columnOrder: [], columns: { @@ -3358,7 +3358,7 @@ describe('state_helpers', () => { }); it('should return the top column if a referenced column is passed', () => { - const layer: IndexPatternLayer = { + const layer: FormBasedLayer = { indexPatternId: '1', columnOrder: [], columns: { @@ -3389,7 +3389,7 @@ describe('state_helpers', () => { label: 'math', operationType: 'math' as const, }; - const layer: IndexPatternLayer = { + const layer: FormBasedLayer = { indexPatternId: '', columnOrder: [], columns: { diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/layer_helpers.ts b/x-pack/plugins/lens/public/datasources/form_based/operations/layer_helpers.ts similarity index 95% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/layer_helpers.ts rename to x-pack/plugins/lens/public/datasources/form_based/operations/layer_helpers.ts index eb0f39262874b..db9b744cd43b2 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/layer_helpers.ts +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/layer_helpers.ts @@ -17,7 +17,7 @@ import type { IndexPatternField, OperationMetadata, VisualizationDimensionGroupConfig, -} from '../../types'; +} from '../../../types'; import { operationDefinitionMap, operationDefinitions, @@ -27,23 +27,19 @@ import { GenericOperationDefinition, TermsIndexPatternColumn, } from './definitions'; -import type { - DataViewDragDropOperation, - IndexPatternLayer, - IndexPatternPrivateState, -} from '../types'; +import type { DataViewDragDropOperation, FormBasedLayer, FormBasedPrivateState } from '../types'; import { getSortScoreByPriorityForField } from './operations'; -import { generateId } from '../../id_generator'; +import { generateId } from '../../../id_generator'; import { GenericIndexPatternColumn, ReferenceBasedIndexPatternColumn, BaseIndexPatternColumn, } from './definitions/column_types'; import { FormulaIndexPatternColumn, insertOrReplaceFormulaColumn } from './definitions/formula'; -import type { TimeScaleUnit } from '../../../common/expressions'; +import type { TimeScaleUnit } from '../../../../common/expressions'; import { documentField } from '../document_field'; import { isColumnOfType } from './definitions/helpers'; -import type { DataType } from '../..'; +import type { DataType } from '../../..'; export interface ColumnAdvancedParams { filter?: Query | undefined; @@ -54,7 +50,7 @@ export interface ColumnAdvancedParams { interface ColumnChange { op: OperationType; - layer: IndexPatternLayer; + layer: FormBasedLayer; columnId: string; indexPattern: IndexPattern; field?: IndexPatternField; @@ -72,7 +68,7 @@ interface ColumnChange { } interface ColumnCopy { - layers: Record; + layers: Record; target: DataViewDragDropOperation; source: DataViewDragDropOperation; shouldDeleteSource?: boolean; @@ -82,7 +78,7 @@ export const deleteColumnInLayers = ({ layers, source, }: { - layers: Record; + layers: Record; source: DataViewDragDropOperation; }) => ({ ...layers, @@ -98,7 +94,7 @@ export function copyColumn({ source, target, shouldDeleteSource, -}: ColumnCopy): Record { +}: ColumnCopy): Record { const outputLayers = createCopiedColumn(layers, target, source); return shouldDeleteSource ? deleteColumnInLayers({ @@ -109,10 +105,10 @@ export function copyColumn({ } function createCopiedColumn( - layers: Record, + layers: Record, target: DataViewDragDropOperation, source: DataViewDragDropOperation -): Record { +): Record { const sourceLayer = layers[source.layerId]; const sourceColumn = sourceLayer.columns[source.columnId]; const targetLayer = layers[target.layerId]; @@ -152,7 +148,7 @@ function createCopiedColumn( }; } -export function insertOrReplaceColumn(args: ColumnChange): IndexPatternLayer { +export function insertOrReplaceColumn(args: ColumnChange): FormBasedLayer { if (args.layer.columns[args.columnId]) { return replaceColumn(args); } @@ -185,7 +181,7 @@ const insertReferences = ({ visualizationGroups, targetGroup, }: { - layer: IndexPatternLayer; + layer: FormBasedLayer; references: Exclude; requiredReferences: RequiredReference[]; indexPattern: IndexPattern; @@ -269,7 +265,7 @@ const generateNewReferences = ({ incompleteFieldName?: string; incompleteFieldOperation?: OperationType; columnParams?: Record; - layer: IndexPatternLayer; + layer: FormBasedLayer; requiredReferences: RequiredReference[]; indexPattern: IndexPattern; visualizationGroups: VisualizationDimensionGroupConfig[]; @@ -364,7 +360,7 @@ export function insertNewColumn({ initialParams, references, respectOrder, -}: ColumnChange): IndexPatternLayer { +}: ColumnChange): FormBasedLayer { const operationDefinition = operationDefinitionMap[op]; if (!operationDefinition) { @@ -541,8 +537,8 @@ function replaceFormulaColumn( }: { operationDefinition: Extract; previousDefinition: GenericOperationDefinition; - layer: IndexPatternLayer; - previousColumn: IndexPatternLayer['columns'][number]; + layer: FormBasedLayer; + previousColumn: FormBasedLayer['columns'][number]; indexPattern: IndexPattern; columnId: string; }, @@ -615,7 +611,7 @@ export function replaceColumn({ initialParams, shouldResetLabel, shouldCombineField, -}: ColumnChange): IndexPatternLayer { +}: ColumnChange): FormBasedLayer { const previousColumn = layer.columns[columnId]; if (!previousColumn) { throw new Error(`Can't replace column because there is no prior column`); @@ -901,10 +897,10 @@ function removeOrphanedColumns( | OperationDefinition | OperationDefinition, previousColumn: GenericIndexPatternColumn, - tempLayer: IndexPatternLayer, + tempLayer: FormBasedLayer, indexPattern: IndexPattern ) { - let newLayer: IndexPatternLayer = tempLayer; + let newLayer: FormBasedLayer = tempLayer; if (previousDefinition.input === 'managedReference') { const [columnId] = Object.entries(tempLayer.columns).find(([_, currColumn]) => currColumn === previousColumn) || @@ -994,13 +990,13 @@ function applyReferenceTransition({ indexPattern, visualizationGroups, }: { - layer: IndexPatternLayer; + layer: FormBasedLayer; columnId: string; previousColumn: GenericIndexPatternColumn; op: OperationType; indexPattern: IndexPattern; visualizationGroups: VisualizationDimensionGroupConfig[]; -}): IndexPatternLayer { +}): FormBasedLayer { const operationDefinition = operationDefinitionMap[op]; if (operationDefinition.input !== 'fullReference') { @@ -1218,13 +1214,13 @@ function copyCustomLabel( } function addBucket( - layer: IndexPatternLayer, + layer: FormBasedLayer, column: BaseIndexPatternColumn, addedColumnId: string, visualizationGroups: VisualizationDimensionGroupConfig[], targetGroup?: string, respectOrder?: boolean -): IndexPatternLayer { +): FormBasedLayer { const [buckets, metrics] = partition( layer.columnOrder, (colId) => layer.columns[colId].isBucketed @@ -1314,10 +1310,10 @@ export function reorderByGroups( } function addMetric( - layer: IndexPatternLayer, + layer: FormBasedLayer, column: BaseIndexPatternColumn, addedColumnId: string -): IndexPatternLayer { +): FormBasedLayer { const tempLayer = { ...resetIncomplete(layer, addedColumnId), columns: { @@ -1347,10 +1343,10 @@ export function updateColumnLabel({ columnId, customLabel, }: { - layer: IndexPatternLayer; + layer: FormBasedLayer; columnId: string; customLabel?: string; -}): IndexPatternLayer { +}): FormBasedLayer { const oldColumn = layer.columns[columnId]; return { ...layer, @@ -1371,11 +1367,11 @@ export function updateColumnParam({ paramName, value, }: { - layer: IndexPatternLayer; + layer: FormBasedLayer; columnId: string; paramName: string; value: unknown; -}): IndexPatternLayer { +}): FormBasedLayer { const currentColumn = layer.columns[columnId]; return { ...layer, @@ -1392,7 +1388,7 @@ export function updateColumnParam({ }; } -export function adjustColumnReferences(layer: IndexPatternLayer) { +export function adjustColumnReferences(layer: FormBasedLayer) { const newColumns = { ...layer.columns }; Object.keys(newColumns).forEach((currentColumnId) => { const currentColumn = newColumns[currentColumnId]; @@ -1413,7 +1409,7 @@ export function adjustColumnReferences(layer: IndexPatternLayer) { } export function adjustColumnReferencesForChangedColumn( - layer: IndexPatternLayer, + layer: FormBasedLayer, changedColumnId: string ) { const newColumns = { ...layer.columns }; @@ -1440,10 +1436,10 @@ export function deleteColumn({ columnId, indexPattern, }: { - layer: IndexPatternLayer; + layer: FormBasedLayer; columnId: string; indexPattern: IndexPattern; -}): IndexPatternLayer { +}): FormBasedLayer { const column = layer.columns[columnId]; if (!column) { const newIncomplete = { ...(layer.incompleteColumns || {}) }; @@ -1491,7 +1487,7 @@ export function deleteColumn({ // // This does NOT topologically sort references, as this would cause the order in the UI // to change. Reference order is determined before creating the pipeline in to_expression -export function getColumnOrder(layer: IndexPatternLayer): string[] { +export function getColumnOrder(layer: FormBasedLayer): string[] { const entries = Object.entries(layer.columns); entries.sort(([idA], [idB]) => { const indexA = layer.columnOrder.indexOf(idA); @@ -1511,7 +1507,7 @@ export function getColumnOrder(layer: IndexPatternLayer): string[] { } // Splits existing columnOrder into the three categories -export function getExistingColumnGroups(layer: IndexPatternLayer): [string[], string[], string[]] { +export function getExistingColumnGroups(layer: FormBasedLayer): [string[], string[], string[]] { const [direct, referenced] = partition( layer.columnOrder, (columnId) => layer.columns[columnId] && !('references' in layer.columns[columnId]) @@ -1525,7 +1521,7 @@ export function getExistingColumnGroups(layer: IndexPatternLayer): [string[], st export function isColumnTransferable( column: GenericIndexPatternColumn, newIndexPattern: IndexPattern, - layer: IndexPatternLayer + layer: FormBasedLayer ): boolean { return ( operationDefinitionMap[column.operationType].isTransferable( @@ -1541,13 +1537,13 @@ export function isColumnTransferable( } export function updateLayerIndexPattern( - layer: IndexPatternLayer, + layer: FormBasedLayer, newIndexPattern: IndexPattern -): IndexPatternLayer { - const keptColumns: IndexPatternLayer['columns'] = pickBy(layer.columns, (column) => { +): FormBasedLayer { + const keptColumns: FormBasedLayer['columns'] = pickBy(layer.columns, (column) => { return isColumnTransferable(column, newIndexPattern, layer); }); - const newColumns: IndexPatternLayer['columns'] = mapValues(keptColumns, (column) => { + const newColumns: FormBasedLayer['columns'] = mapValues(keptColumns, (column) => { const operationDefinition = operationDefinitionMap[column.operationType]; return operationDefinition.transfer ? operationDefinition.transfer(column, newIndexPattern) @@ -1573,9 +1569,9 @@ export function updateLayerIndexPattern( * - If timeshift is used, only a single date histogram can be used */ export function getErrorMessages( - layer: IndexPatternLayer, + layer: FormBasedLayer, indexPattern: IndexPattern, - state: IndexPatternPrivateState, + state: FormBasedPrivateState, layerId: string, core: CoreStart, data: DataPublicPluginStart @@ -1584,7 +1580,7 @@ export function getErrorMessages( | string | { message: string; - fixAction?: DatasourceFixAction; + fixAction?: DatasourceFixAction; } > | undefined { @@ -1632,21 +1628,21 @@ export function getErrorMessages( | string | { message: string; - fixAction?: DatasourceFixAction; + fixAction?: DatasourceFixAction; } >; return errors.length ? errors : undefined; } -export function isReferenced(layer: IndexPatternLayer, columnId: string): boolean { +export function isReferenced(layer: FormBasedLayer, columnId: string): boolean { const allReferences = Object.values(layer.columns).flatMap((col) => 'references' in col ? col.references : [] ); return allReferences.includes(columnId); } -const computeReferenceLookup = memoizeOne((layer: IndexPatternLayer): Record => { +const computeReferenceLookup = memoizeOne((layer: FormBasedLayer): Record => { // speed up things for deep chains as in formula const refLookup: Record = {}; for (const [parentId, col] of Object.entries(layer.columns)) { @@ -1666,7 +1662,7 @@ const computeReferenceLookup = memoizeOne((layer: IndexPatternLayer): Record { const column = layer.columns[columnId]; if (column) { @@ -1740,9 +1736,9 @@ export function isOperationAllowedAsReference({ // Labels need to be updated when columns are added because reference-based column labels // are sometimes copied into the parents export function updateDefaultLabels( - layer: IndexPatternLayer, + layer: FormBasedLayer, indexPattern: IndexPattern -): IndexPatternLayer { +): FormBasedLayer { const copiedColumns = { ...layer.columns }; layer.columnOrder.forEach((id) => { const col = copiedColumns[id]; @@ -1760,7 +1756,7 @@ export function updateDefaultLabels( return { ...layer, columns: copiedColumns }; } -export function resetIncomplete(layer: IndexPatternLayer, columnId: string): IndexPatternLayer { +export function resetIncomplete(layer: FormBasedLayer, columnId: string): FormBasedLayer { const incompleteColumns = { ...(layer.incompleteColumns ?? {}) }; delete incompleteColumns[columnId]; return { ...layer, incompleteColumns }; diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/mocks.ts b/x-pack/plugins/lens/public/datasources/form_based/operations/mocks.ts similarity index 97% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/mocks.ts rename to x-pack/plugins/lens/public/datasources/form_based/operations/mocks.ts index 2d7e70179fb3f..3884bab02f200 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/mocks.ts +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/mocks.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { OperationMetadata } from '../../types'; +import type { OperationMetadata } from '../../../types'; import type { OperationType } from './definitions'; export const createMockedFullReference = () => { diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/operations.test.ts b/x-pack/plugins/lens/public/datasources/form_based/operations/operations.test.ts similarity index 100% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/operations.test.ts rename to x-pack/plugins/lens/public/datasources/form_based/operations/operations.test.ts diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/operations.ts b/x-pack/plugins/lens/public/datasources/form_based/operations/operations.ts similarity index 99% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/operations.ts rename to x-pack/plugins/lens/public/datasources/form_based/operations/operations.ts index 27071e5f0ee74..b44c0a0e4cc55 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/operations.ts +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/operations.ts @@ -6,7 +6,7 @@ */ import { memoize } from 'lodash'; -import type { IndexPattern, IndexPatternField, OperationMetadata } from '../../types'; +import type { IndexPattern, IndexPatternField, OperationMetadata } from '../../../types'; import { operationDefinitionMap, operationDefinitions, diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/time_scale_utils.test.ts b/x-pack/plugins/lens/public/datasources/form_based/operations/time_scale_utils.test.ts similarity index 98% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/time_scale_utils.test.ts rename to x-pack/plugins/lens/public/datasources/form_based/operations/time_scale_utils.test.ts index 559086cf69b84..e249be575aac2 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/time_scale_utils.test.ts +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/time_scale_utils.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { TimeScaleUnit } from '../../../common/expressions'; +import type { TimeScaleUnit } from '../../../../common/expressions'; import { adjustTimeScaleLabelSuffix } from './time_scale_utils'; export const DEFAULT_TIME_SCALE = 's' as TimeScaleUnit; diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/time_scale_utils.ts b/x-pack/plugins/lens/public/datasources/form_based/operations/time_scale_utils.ts similarity index 92% rename from x-pack/plugins/lens/public/indexpattern_datasource/operations/time_scale_utils.ts rename to x-pack/plugins/lens/public/datasources/form_based/operations/time_scale_utils.ts index 1ebf4ccc76a36..08dfa147bf88e 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/time_scale_utils.ts +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/time_scale_utils.ts @@ -6,8 +6,8 @@ */ import { i18n } from '@kbn/i18n'; -import { unitSuffixesLong } from '../../../common/suffix_formatter'; -import type { TimeScaleUnit } from '../../../common/expressions'; +import { unitSuffixesLong } from '../../../../common/suffix_formatter'; +import type { TimeScaleUnit } from '../../../../common/expressions'; export const DEFAULT_TIME_SCALE = 's' as TimeScaleUnit; diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/pure_helpers.ts b/x-pack/plugins/lens/public/datasources/form_based/pure_helpers.ts similarity index 92% rename from x-pack/plugins/lens/public/indexpattern_datasource/pure_helpers.ts rename to x-pack/plugins/lens/public/datasources/form_based/pure_helpers.ts index ba3ba9bbb824f..6355809369804 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/pure_helpers.ts +++ b/x-pack/plugins/lens/public/datasources/form_based/pure_helpers.ts @@ -6,7 +6,7 @@ */ import { keyBy } from 'lodash'; -import { IndexPatternField } from '../types'; +import { IndexPatternField } from '../../types'; import { documentField } from './document_field'; export function getFieldByNameFactory( diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/pure_utils.ts b/x-pack/plugins/lens/public/datasources/form_based/pure_utils.ts similarity index 95% rename from x-pack/plugins/lens/public/indexpattern_datasource/pure_utils.ts rename to x-pack/plugins/lens/public/datasources/form_based/pure_utils.ts index 39b4bcdf49229..5d8d823c30ab4 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/pure_utils.ts +++ b/x-pack/plugins/lens/public/datasources/form_based/pure_utils.ts @@ -5,8 +5,8 @@ * 2.0. */ -import type { DataType, IndexPattern, IndexPatternField } from '../types'; -import type { IndexPatternLayer } from './types'; +import type { DataType, IndexPattern, IndexPatternField } from '../../types'; +import type { FormBasedLayer } from './types'; import type { BaseIndexPatternColumn, FieldBasedIndexPatternColumn, @@ -36,7 +36,7 @@ export function getFieldType(field: IndexPatternField) { export function getReferencedField( column: GenericIndexPatternColumn | undefined, indexPattern: IndexPattern, - layer: IndexPatternLayer + layer: FormBasedLayer ) { if (!column) return; if (!('references' in column)) return; diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/reduced_time_range_utils.tsx b/x-pack/plugins/lens/public/datasources/form_based/reduced_time_range_utils.tsx similarity index 95% rename from x-pack/plugins/lens/public/indexpattern_datasource/reduced_time_range_utils.tsx rename to x-pack/plugins/lens/public/datasources/form_based/reduced_time_range_utils.tsx index 04984a1c782bf..69e0fb4f07a5e 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/reduced_time_range_utils.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/reduced_time_range_utils.tsx @@ -6,8 +6,8 @@ */ import { i18n } from '@kbn/i18n'; -import type { IndexPatternLayer } from './types'; -import type { IndexPattern } from '../types'; +import type { FormBasedLayer } from './types'; +import type { IndexPattern } from '../../types'; export const reducedTimeRangeOptions = [ { @@ -53,7 +53,7 @@ export const reducedTimeRangeOptionOrder = reducedTimeRangeOptions.reduce<{ ); export function getColumnReducedTimeRangeError( - layer: IndexPatternLayer, + layer: FormBasedLayer, columnId: string, indexPattern: IndexPattern ): string[] | undefined { diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/state_helpers.ts b/x-pack/plugins/lens/public/datasources/form_based/state_helpers.ts similarity index 73% rename from x-pack/plugins/lens/public/indexpattern_datasource/state_helpers.ts rename to x-pack/plugins/lens/public/datasources/form_based/state_helpers.ts index 6e16ebe5e8d53..0120c29713a83 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/state_helpers.ts +++ b/x-pack/plugins/lens/public/datasources/form_based/state_helpers.ts @@ -5,16 +5,16 @@ * 2.0. */ -import { IndexPatternPrivateState, IndexPatternLayer } from './types'; +import { FormBasedPrivateState, FormBasedLayer } from './types'; export function mergeLayer({ state, layerId, newLayer, }: { - state: IndexPatternPrivateState; + state: FormBasedPrivateState; layerId: string; - newLayer: Partial; + newLayer: Partial; }) { return { ...state, @@ -29,8 +29,8 @@ export function mergeLayers({ state, newLayers, }: { - state: IndexPatternPrivateState; - newLayers: Record; + state: FormBasedPrivateState; + newLayers: Record; }) { return { ...state, diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/time_shift_utils.test.tsx b/x-pack/plugins/lens/public/datasources/form_based/time_shift_utils.test.tsx similarity index 96% rename from x-pack/plugins/lens/public/indexpattern_datasource/time_shift_utils.test.tsx rename to x-pack/plugins/lens/public/datasources/form_based/time_shift_utils.test.tsx index 4cb251e3820be..a0ff29a684150 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/time_shift_utils.test.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/time_shift_utils.test.tsx @@ -6,11 +6,11 @@ */ import { getDisallowedPreviousShiftMessage } from './time_shift_utils'; -import { IndexPatternLayer } from './types'; +import { FormBasedLayer } from './types'; describe('time_shift_utils', () => { describe('getDisallowedPreviousShiftMessage', () => { - const layer: IndexPatternLayer = { + const layer: FormBasedLayer = { indexPatternId: '', columnOrder: [], columns: { diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/time_shift_utils.tsx b/x-pack/plugins/lens/public/datasources/form_based/time_shift_utils.tsx similarity index 97% rename from x-pack/plugins/lens/public/indexpattern_datasource/time_shift_utils.tsx rename to x-pack/plugins/lens/public/datasources/form_based/time_shift_utils.tsx index 51f389e69a4f0..6dd4b88d3422a 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/time_shift_utils.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/time_shift_utils.tsx @@ -13,12 +13,8 @@ import type { DatatableUtilitiesService } from '@kbn/data-plugin/common'; import { Datatable } from '@kbn/expressions-plugin/common'; import { search } from '@kbn/data-plugin/public'; import { parseTimeShift } from '@kbn/data-plugin/common'; -import type { - GenericIndexPatternColumn, - IndexPatternLayer, - IndexPatternPrivateState, -} from './types'; -import type { FramePublicAPI, IndexPattern } from '../types'; +import type { GenericIndexPatternColumn, FormBasedLayer, FormBasedPrivateState } from './types'; +import type { FramePublicAPI, IndexPattern } from '../../types'; export const timeShiftOptions = [ { @@ -105,7 +101,7 @@ export const timeShiftOptionOrder = timeShiftOptions.reduce<{ [key: string]: num export function getDateHistogramInterval( datatableUtilities: DatatableUtilitiesService, - layer: IndexPatternLayer, + layer: FormBasedLayer, indexPattern: IndexPattern, activeData: Record | undefined, layerId: string @@ -163,7 +159,7 @@ export function getLayerTimeShiftChecks({ } export function getDisallowedPreviousShiftMessage( - layer: IndexPatternLayer, + layer: FormBasedLayer, columnId: string ): string[] | undefined { const currentColumn = layer.columns[columnId]; @@ -191,7 +187,7 @@ export function getDisallowedPreviousShiftMessage( export function getStateTimeShiftWarningMessages( datatableUtilities: DatatableUtilitiesService, - state: IndexPatternPrivateState, + state: FormBasedPrivateState, { activeData, dataViews }: FramePublicAPI ) { if (!state) return; diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/to_expression.ts b/x-pack/plugins/lens/public/datasources/form_based/to_expression.ts similarity index 98% rename from x-pack/plugins/lens/public/indexpattern_datasource/to_expression.ts rename to x-pack/plugins/lens/public/datasources/form_based/to_expression.ts index 72cb2a2ab729e..fc77aa6520bd0 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/to_expression.ts +++ b/x-pack/plugins/lens/public/datasources/form_based/to_expression.ts @@ -20,13 +20,13 @@ import { ExpressionAstExpressionBuilder, ExpressionAstFunction, } from '@kbn/expressions-plugin/public'; -import { GenericIndexPatternColumn } from './indexpattern'; +import { GenericIndexPatternColumn } from './form_based'; import { operationDefinitionMap } from './operations'; -import { IndexPatternPrivateState, IndexPatternLayer } from './types'; +import { FormBasedPrivateState, FormBasedLayer } from './types'; import { DateHistogramIndexPatternColumn, RangeIndexPatternColumn } from './operations/definitions'; import { FormattedIndexPatternColumn } from './operations/definitions/column_types'; import { isColumnFormatted, isColumnOfType } from './operations/definitions/helpers'; -import type { IndexPattern, IndexPatternMap } from '../types'; +import type { IndexPattern, IndexPatternMap } from '../../types'; import { dedupeAggs } from './dedupe_aggs'; export type OriginalColumn = { id: string } & GenericIndexPatternColumn; @@ -50,7 +50,7 @@ const updatePositionIndex = (currentId: string, newIndex: number) => { }; function getExpressionForLayer( - layer: IndexPatternLayer, + layer: FormBasedLayer, indexPattern: IndexPattern, uiSettings: IUiSettingsClient ): ExpressionAstExpression | null { @@ -438,7 +438,7 @@ function sortedReferences(columns: Array; // Each layer is tied to the index pattern that created it @@ -56,15 +55,15 @@ export interface IndexPatternLayer { incompleteColumns?: Record; } -export interface IndexPatternPersistedState { - layers: Record>; +export interface FormBasedPersistedState { + layers: Record>; } -export type PersistedIndexPatternLayer = Omit; +export type PersistedIndexPatternLayer = Omit; -export interface IndexPatternPrivateState { +export interface FormBasedPrivateState { currentIndexPatternId: string; - layers: Record; + layers: Record; isDimensionClosePrevented?: boolean; } diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/utils.test.tsx b/x-pack/plugins/lens/public/datasources/form_based/utils.test.tsx similarity index 95% rename from x-pack/plugins/lens/public/indexpattern_datasource/utils.test.tsx rename to x-pack/plugins/lens/public/datasources/form_based/utils.test.tsx index 2d7a6334adaf6..5349e433f3cac 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/utils.test.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/utils.test.tsx @@ -9,19 +9,19 @@ import React from 'react'; import { shallow } from 'enzyme'; import { createDatatableUtilitiesMock } from '@kbn/data-plugin/common/mocks'; import { getPrecisionErrorWarningMessages, cloneLayer } from './utils'; -import type { IndexPatternPrivateState, GenericIndexPatternColumn } from './types'; -import type { FramePublicAPI } from '../types'; +import type { FormBasedPrivateState, GenericIndexPatternColumn } from './types'; +import type { FramePublicAPI } from '../../types'; import type { DocLinksStart } from '@kbn/core/public'; import { EuiButton } from '@elastic/eui'; import { TermsIndexPatternColumn } from './operations'; import { mountWithIntl } from '@kbn/test-jest-helpers'; import { FormattedMessage } from '@kbn/i18n-react'; -import { IndexPatternLayer } from './types'; +import { FormBasedLayer } from './types'; describe('indexpattern_datasource utils', () => { describe('getPrecisionErrorWarningMessages', () => { const datatableUtilitites = createDatatableUtilitiesMock(); - let state: IndexPatternPrivateState; + let state: FormBasedPrivateState; let framePublicAPI: FramePublicAPI; let docLinks: DocLinksStart; @@ -42,7 +42,7 @@ describe('indexpattern_datasource utils', () => { }, }, }, - } as unknown as IndexPatternPrivateState; + } as unknown as FormBasedPrivateState; framePublicAPI = { activeData: { id: { @@ -227,7 +227,7 @@ describe('indexpattern_datasource utils', () => { incompleteColumns: {}, indexPatternId: 'ff959d40-b880-11e8-a6d9-e546fe2bba5f', }, - } as unknown as Record, + } as unknown as Record, 'a', 'b', (id) => id + 'C' diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/utils.tsx b/x-pack/plugins/lens/public/datasources/form_based/utils.tsx similarity index 96% rename from x-pack/plugins/lens/public/indexpattern_datasource/utils.tsx rename to x-pack/plugins/lens/public/datasources/form_based/utils.tsx index 612719967161c..dfec3c723d189 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/utils.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/utils.tsx @@ -17,13 +17,9 @@ import type { DatatableColumn } from '@kbn/expressions-plugin/common'; import { groupBy, escape, uniq } from 'lodash'; import type { Query } from '@kbn/data-plugin/common'; import { SearchResponseWarning } from '@kbn/data-plugin/public/search/types'; -import type { FramePublicAPI, IndexPattern, StateSetter } from '../types'; -import { renewIDs } from '../utils'; -import type { - IndexPatternLayer, - IndexPatternPersistedState, - IndexPatternPrivateState, -} from './types'; +import type { FramePublicAPI, IndexPattern, StateSetter } from '../../types'; +import { renewIDs } from '../../utils'; +import type { FormBasedLayer, FormBasedPersistedState, FormBasedPrivateState } from './types'; import type { ReferenceBasedIndexPatternColumn } from './operations/definitions/column_types'; import { @@ -44,11 +40,11 @@ import { hasField } from './pure_utils'; import { mergeLayer } from './state_helpers'; import { supportsRarityRanking } from './operations/definitions/terms'; import { DEFAULT_MAX_DOC_COUNT } from './operations/definitions/terms/constants'; -import { getOriginalId } from '../../common/expressions/datatable/transpose_helpers'; -import { isQueryValid } from '../shared_components'; +import { getOriginalId } from '../../../common/expressions/datatable/transpose_helpers'; +import { isQueryValid } from '../../shared_components'; export function isColumnInvalid( - layer: IndexPatternLayer, + layer: FormBasedLayer, columnId: string, indexPattern: IndexPattern ) { @@ -76,7 +72,7 @@ export function isColumnInvalid( } function getReferencesErrors( - layer: IndexPatternLayer, + layer: FormBasedLayer, column: ReferenceBasedIndexPatternColumn, indexPattern: IndexPattern ) { @@ -167,7 +163,7 @@ const accuracyModeEnabledWarning = (columnName: string, docLink: string) => ( ); export function getTSDBRollupWarningMessages( - state: IndexPatternPersistedState, + state: FormBasedPersistedState, warning: SearchResponseWarning ) { if (state) { @@ -208,10 +204,10 @@ export function getTSDBRollupWarningMessages( export function getPrecisionErrorWarningMessages( datatableUtilities: DatatableUtilitiesService, - state: IndexPatternPrivateState, + state: FormBasedPrivateState, { activeData, dataViews }: FramePublicAPI, docLinks: DocLinksStart, - setState: StateSetter + setState: StateSetter ) { const warningMessages: React.ReactNode[] = []; @@ -338,7 +334,7 @@ export function getPrecisionErrorWarningMessages( return warningMessages; } -export function getVisualDefaultsForLayer(layer: IndexPatternLayer) { +export function getVisualDefaultsForLayer(layer: FormBasedLayer) { return Object.keys(layer.columns).reduce>>( (memo, columnId) => { const column = layer.columns[columnId]; @@ -461,7 +457,7 @@ function shouldUseTermsFallback( * * if there's at least one unfiltered metric, then just return an empty list of filters * * otherwise get all the filters, with the only exception of those from formula (referenced columns will have it anyway) */ -function collectFiltersFromMetrics(layer: IndexPatternLayer, columnIds: string[]) { +function collectFiltersFromMetrics(layer: FormBasedLayer, columnIds: string[]) { // Isolate filtered metrics first // mind to ignore non-filterable columns and formula columns const metricColumns = Object.keys(layer.columns).filter((colId) => { @@ -506,7 +502,7 @@ function collectOnlyValidQueries( } export function getFiltersInLayer( - layer: IndexPatternLayer, + layer: FormBasedLayer, columnIds: string[], layerData: NonNullable[string] | undefined, indexPattern: IndexPattern, @@ -617,7 +613,7 @@ export function getFiltersInLayer( } export const cloneLayer = ( - layers: Record, + layers: Record, layerId: string, newLayerId: string, getNewId: (id: string) => string diff --git a/x-pack/plugins/lens/public/text_based_languages_datasource/datapanel.test.tsx b/x-pack/plugins/lens/public/datasources/text_based/datapanel.test.tsx similarity index 82% rename from x-pack/plugins/lens/public/text_based_languages_datasource/datapanel.test.tsx rename to x-pack/plugins/lens/public/datasources/text_based/datapanel.test.tsx index 51ba02c1cdc6f..b5f158ecd453f 100644 --- a/x-pack/plugins/lens/public/text_based_languages_datasource/datapanel.test.tsx +++ b/x-pack/plugins/lens/public/datasources/text_based/datapanel.test.tsx @@ -19,18 +19,18 @@ import { import type { DatatableColumn } from '@kbn/expressions-plugin/public'; import { FieldButton } from '@kbn/react-field'; -import { type TextBasedLanguagesDataPanelProps, TextBasedLanguagesDataPanel } from './datapanel'; +import { type TextBasedDataPanelProps, TextBasedDataPanel } from './datapanel'; import { coreMock } from '@kbn/core/public/mocks'; -import type { TextBasedLanguagesPrivateState } from './types'; +import type { TextBasedPrivateState } from './types'; import { mountWithIntl } from '@kbn/test-jest-helpers'; import { uiActionsPluginMock } from '@kbn/ui-actions-plugin/public/mocks'; -import { createIndexPatternServiceMock } from '../mocks/data_views_service_mock'; -import { createMockFramePublicAPI } from '../mocks'; +import { createIndexPatternServiceMock } from '../../mocks/data_views_service_mock'; +import { createMockFramePublicAPI } from '../../mocks'; import { createMockedDragDropContext } from './mocks'; -import { DataViewsState } from '../state_management'; -import { ExistingFieldsMap, IndexPattern } from '../types'; +import { DataViewsState } from '../../state_management'; +import { ExistingFieldsMap, IndexPattern } from '../../types'; const fieldsFromQuery = [ { @@ -113,7 +113,7 @@ function getExistingFields(indexPatterns: Record) { return existingFields; } -const initialState: TextBasedLanguagesPrivateState = { +const initialState: TextBasedPrivateState = { layers: { first: { index: '1', @@ -163,7 +163,7 @@ describe('TextBased Query Languages Data Panel', () => { let core: ReturnType; let dataViews: DataViewPublicStart; - let defaultProps: TextBasedLanguagesDataPanelProps; + let defaultProps: TextBasedDataPanelProps; const dataViewsMock = dataViewPluginMocks.createStartContract(); beforeEach(() => { core = coreMock.createStart(); @@ -202,12 +202,12 @@ describe('TextBased Query Languages Data Panel', () => { }); it('should render a search box', async () => { - const wrapper = mountWithIntl(); + const wrapper = mountWithIntl(); expect(wrapper.find('[data-test-subj="lnsTextBasedLangugesFieldSearch"]').length).toEqual(1); }); it('should list all supported fields in the pattern', async () => { - const wrapper = mountWithIntl(); + const wrapper = mountWithIntl(); expect( wrapper .find('[data-test-subj="lnsTextBasedLanguagesPanelFields"]') @@ -216,8 +216,22 @@ describe('TextBased Query Languages Data Panel', () => { ).toEqual(['timestamp', 'bytes', 'memory']); }); + it('should not display the selected fields accordion if there are no fields displayed', async () => { + const wrapper = mountWithIntl(); + expect(wrapper.find('[data-test-subj="lnsSelectedFieldsTextBased"]').length).toEqual(0); + }); + + it('should display the selected fields accordion if there are fields displayed', async () => { + const props = { + ...defaultProps, + layerFields: ['memory'], + }; + const wrapper = mountWithIntl(); + expect(wrapper.find('[data-test-subj="lnsSelectedFieldsTextBased"]').length).not.toEqual(0); + }); + it('should list all supported fields in the pattern that match the search input', async () => { - const wrapper = mountWithIntl(); + const wrapper = mountWithIntl(); const searchBox = wrapper.find('[data-test-subj="lnsTextBasedLangugesFieldSearch"]'); act(() => { diff --git a/x-pack/plugins/lens/public/text_based_languages_datasource/datapanel.tsx b/x-pack/plugins/lens/public/datasources/text_based/datapanel.tsx similarity index 69% rename from x-pack/plugins/lens/public/text_based_languages_datasource/datapanel.tsx rename to x-pack/plugins/lens/public/datasources/text_based/datapanel.tsx index 9e15db381549d..1b0699b2eb930 100644 --- a/x-pack/plugins/lens/public/text_based_languages_datasource/datapanel.tsx +++ b/x-pack/plugins/lens/public/datasources/text_based/datapanel.tsx @@ -15,25 +15,23 @@ import type { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public'; import { isOfAggregateQueryType } from '@kbn/es-query'; import { ExpressionsStart } from '@kbn/expressions-plugin/public'; -import { FieldButton } from '@kbn/react-field'; import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; -import { DatasourceDataPanelProps, DataType } from '../types'; -import type { TextBasedLanguagesPrivateState } from './types'; +import type { DatasourceDataPanelProps } from '../../types'; +import type { TextBasedPrivateState } from './types'; import { getStateFromAggregateQuery } from './utils'; -import { DragDrop } from '../drag_drop'; -import { LensFieldIcon } from '../shared_components'; -import { ChildDragDropProvider } from '../drag_drop'; +import { ChildDragDropProvider } from '../../drag_drop'; +import { FieldsAccordion } from './fields_accordion'; -export type TextBasedLanguagesDataPanelProps = - DatasourceDataPanelProps & { - data: DataPublicPluginStart; - expressions: ExpressionsStart; - dataViews: DataViewsPublicPluginStart; - }; +export type TextBasedDataPanelProps = DatasourceDataPanelProps & { + data: DataPublicPluginStart; + expressions: ExpressionsStart; + dataViews: DataViewsPublicPluginStart; + layerFields?: string[]; +}; const htmlId = htmlIdGenerator('datapanel-text-based-languages'); const fieldSearchDescriptionId = htmlId(); -export function TextBasedLanguagesDataPanel({ +export function TextBasedDataPanel({ setState, state, dragDropContext, @@ -44,9 +42,11 @@ export function TextBasedLanguagesDataPanel({ dateRange, expressions, dataViews, -}: TextBasedLanguagesDataPanelProps) { + layerFields, +}: TextBasedDataPanelProps) { const prevQuery = usePrevious(query); const [localState, setLocalState] = useState({ nameFilter: '' }); + const [dataHasLoaded, setDataHasLoaded] = useState(false); const clearLocalState = () => setLocalState((s) => ({ ...s, nameFilter: '' })); useEffect(() => { async function fetchData() { @@ -59,6 +59,7 @@ export function TextBasedLanguagesDataPanel({ expressions ); + setDataHasLoaded(true); setState(stateFromQuery); } } @@ -77,6 +78,7 @@ export function TextBasedLanguagesDataPanel({ return true; }); }, [fieldList, localState.nameFilter]); + const usedByLayersFields = fieldList.filter((field) => layerFields?.includes(field.name)); return (
-
    - {filteredFields.length > 0 && - filteredFields.map((field, index) => ( -
  • - - {}} - fieldIcon={} - fieldName={field?.name} - /> - -
  • - ))} -
+ {usedByLayersFields.length > 0 && ( + + )} +
diff --git a/x-pack/plugins/lens/public/text_based_languages_datasource/fetch_data_from_aggregate_query.ts b/x-pack/plugins/lens/public/datasources/text_based/fetch_data_from_aggregate_query.ts similarity index 100% rename from x-pack/plugins/lens/public/text_based_languages_datasource/fetch_data_from_aggregate_query.ts rename to x-pack/plugins/lens/public/datasources/text_based/fetch_data_from_aggregate_query.ts diff --git a/x-pack/plugins/lens/public/text_based_languages_datasource/field_select.test.tsx b/x-pack/plugins/lens/public/datasources/text_based/field_select.test.tsx similarity index 96% rename from x-pack/plugins/lens/public/text_based_languages_datasource/field_select.test.tsx rename to x-pack/plugins/lens/public/datasources/text_based/field_select.test.tsx index f1051f3b8f61d..b344131747b1b 100644 --- a/x-pack/plugins/lens/public/text_based_languages_datasource/field_select.test.tsx +++ b/x-pack/plugins/lens/public/datasources/text_based/field_select.test.tsx @@ -8,7 +8,7 @@ import React from 'react'; import type { DatatableColumn } from '@kbn/expressions-plugin/public'; -import { FieldPicker, FieldOptionValue } from '../shared_components/field_picker'; +import { FieldPicker, FieldOptionValue } from '../../shared_components/field_picker'; import { FieldSelect, FieldSelectProps } from './field_select'; import { shallowWithIntl as shallow } from '@kbn/test-jest-helpers'; diff --git a/x-pack/plugins/lens/public/text_based_languages_datasource/field_select.tsx b/x-pack/plugins/lens/public/datasources/text_based/field_select.tsx similarity index 89% rename from x-pack/plugins/lens/public/text_based_languages_datasource/field_select.tsx rename to x-pack/plugins/lens/public/datasources/text_based/field_select.tsx index 63153bc87d59e..e7cb5451d31ab 100644 --- a/x-pack/plugins/lens/public/text_based_languages_datasource/field_select.tsx +++ b/x-pack/plugins/lens/public/datasources/text_based/field_select.tsx @@ -9,12 +9,12 @@ import React, { useMemo } from 'react'; import { EuiComboBoxOptionOption, EuiComboBoxProps } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import type { DatatableColumn } from '@kbn/expressions-plugin/public'; -import { FieldPicker, FieldOptionValue, FieldOption } from '../shared_components/field_picker'; -import type { TextBasedLanguagesLayerColumn } from './types'; -import type { DataType } from '../types'; +import { FieldPicker, FieldOptionValue, FieldOption } from '../../shared_components/field_picker'; +import type { TextBasedLayerColumn } from './types'; +import type { DataType } from '../../types'; export interface FieldSelectProps extends EuiComboBoxProps { - selectedField?: TextBasedLanguagesLayerColumn; + selectedField?: TextBasedLayerColumn; onChoose: (choice: FieldOptionValue) => void; existingFields: DatatableColumn[]; } diff --git a/x-pack/plugins/lens/public/datasources/text_based/fields_accordion.tsx b/x-pack/plugins/lens/public/datasources/text_based/fields_accordion.tsx new file mode 100644 index 0000000000000..23f71e991bc82 --- /dev/null +++ b/x-pack/plugins/lens/public/datasources/text_based/fields_accordion.tsx @@ -0,0 +1,102 @@ +/* + * 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, { memo, useMemo } from 'react'; +import type { DatatableColumn } from '@kbn/expressions-plugin/public'; + +import { + EuiText, + EuiNotificationBadge, + EuiAccordion, + EuiLoadingSpinner, + EuiSpacer, +} from '@elastic/eui'; +import { FieldButton } from '@kbn/react-field'; +import { DragDrop } from '../../drag_drop'; +import { LensFieldIcon } from '../../shared_components'; +import type { DataType } from '../../types'; + +export interface FieldsAccordionProps { + initialIsOpen: boolean; + hasLoaded: boolean; + isFiltered: boolean; + // forceState: 'open' | 'closed'; + id: string; + label: string; + fields: DatatableColumn[]; +} + +export const FieldsAccordion = memo(function InnerFieldsAccordion({ + initialIsOpen, + hasLoaded, + isFiltered, + id, + label, + fields, +}: FieldsAccordionProps) { + const renderButton = useMemo(() => { + return ( + + {label} + + ); + }, [label]); + + const extraAction = useMemo(() => { + if (hasLoaded) { + return ( + + {fields.length} + + ); + } + + return ; + }, [fields.length, hasLoaded, isFiltered]); + + return ( + <> + +
    + {fields.length > 0 && + fields.map((field, index) => ( +
  • + + {}} + fieldIcon={} + fieldName={field?.name} + /> + +
  • + ))} +
+
+ + + ); +}); diff --git a/x-pack/plugins/lens/public/text_based_languages_datasource/index.ts b/x-pack/plugins/lens/public/datasources/text_based/index.ts similarity index 71% rename from x-pack/plugins/lens/public/text_based_languages_datasource/index.ts rename to x-pack/plugins/lens/public/datasources/text_based/index.ts index b2cffc5659dbf..1041e94eb7c61 100644 --- a/x-pack/plugins/lens/public/text_based_languages_datasource/index.ts +++ b/x-pack/plugins/lens/public/datasources/text_based/index.ts @@ -10,31 +10,28 @@ import { Storage } from '@kbn/kibana-utils-plugin/public'; import { ExpressionsStart } from '@kbn/expressions-plugin/public'; import { DataPublicPluginSetup, DataPublicPluginStart } from '@kbn/data-plugin/public'; import type { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public'; -import { EditorFrameSetup } from '../types'; +import { EditorFrameSetup } from '../../types'; -export interface TextBasedLanguageSetupPlugins { +export interface TextBasedSetupPlugins { data: DataPublicPluginSetup; editorFrame: EditorFrameSetup; } -export interface TextBasedLanguageStartPlugins { +export interface TextBasedStartPlugins { data: DataPublicPluginStart; dataViews: DataViewsPublicPluginStart; expressions: ExpressionsStart; } -export class TextBasedLanguagesDatasource { +export class TextBasedDatasource { constructor() {} - setup( - core: CoreSetup, - { editorFrame }: TextBasedLanguageSetupPlugins - ) { + setup(core: CoreSetup, { editorFrame }: TextBasedSetupPlugins) { editorFrame.registerDatasource(async () => { - const { getTextBasedLanguagesDatasource } = await import('../async_services'); + const { getTextBasedDatasource } = await import('../../async_services'); const [coreStart, { data, dataViews, expressions }] = await core.getStartServices(); - return getTextBasedLanguagesDatasource({ + return getTextBasedDatasource({ core: coreStart, storage: new Storage(localStorage), data, diff --git a/x-pack/plugins/lens/public/text_based_languages_datasource/layerpanel.test.tsx b/x-pack/plugins/lens/public/datasources/text_based/layerpanel.test.tsx similarity index 83% rename from x-pack/plugins/lens/public/text_based_languages_datasource/layerpanel.test.tsx rename to x-pack/plugins/lens/public/datasources/text_based/layerpanel.test.tsx index 7a3bf25b5e9e6..f0a9d147ddfd6 100644 --- a/x-pack/plugins/lens/public/text_based_languages_datasource/layerpanel.test.tsx +++ b/x-pack/plugins/lens/public/datasources/text_based/layerpanel.test.tsx @@ -7,12 +7,12 @@ import React from 'react'; import type { DatatableColumn } from '@kbn/expressions-plugin/public'; -import { TextBasedLanguagesPrivateState } from './types'; -import type { DataViewsState } from '../state_management/types'; +import { TextBasedPrivateState } from './types'; +import type { DataViewsState } from '../../state_management/types'; -import { TextBasedLanguageLayerPanelProps, LayerPanel } from './layerpanel'; +import { TextBasedLayerPanelProps, LayerPanel } from './layerpanel'; import { shallowWithIntl as shallow } from '@kbn/test-jest-helpers'; -import { ChangeIndexPattern } from '../shared_components/dataview_picker/dataview_picker'; +import { ChangeIndexPattern } from '../../shared_components/dataview_picker/dataview_picker'; const fields = [ { @@ -38,7 +38,7 @@ const fields = [ }, ] as DatatableColumn[]; -const initialState: TextBasedLanguagesPrivateState = { +const initialState: TextBasedPrivateState = { layers: { first: { index: '1', @@ -55,7 +55,7 @@ const initialState: TextBasedLanguagesPrivateState = { fieldList: fields, }; describe('Layer Data Panel', () => { - let defaultProps: TextBasedLanguageLayerPanelProps; + let defaultProps: TextBasedLayerPanelProps; beforeEach(() => { defaultProps = { diff --git a/x-pack/plugins/lens/public/text_based_languages_datasource/layerpanel.tsx b/x-pack/plugins/lens/public/datasources/text_based/layerpanel.tsx similarity index 75% rename from x-pack/plugins/lens/public/text_based_languages_datasource/layerpanel.tsx rename to x-pack/plugins/lens/public/datasources/text_based/layerpanel.tsx index 8f8e4a91242b1..879d28a607c7f 100644 --- a/x-pack/plugins/lens/public/text_based_languages_datasource/layerpanel.tsx +++ b/x-pack/plugins/lens/public/datasources/text_based/layerpanel.tsx @@ -8,16 +8,15 @@ import React from 'react'; import { I18nProvider } from '@kbn/i18n-react'; import { i18n } from '@kbn/i18n'; -import { DatasourceLayerPanelProps } from '../types'; -import { TextBasedLanguagesPrivateState } from './types'; -import { ChangeIndexPattern } from '../shared_components/dataview_picker/dataview_picker'; +import { DatasourceLayerPanelProps } from '../../types'; +import { TextBasedPrivateState } from './types'; +import { ChangeIndexPattern } from '../../shared_components/dataview_picker/dataview_picker'; -export interface TextBasedLanguageLayerPanelProps - extends DatasourceLayerPanelProps { - state: TextBasedLanguagesPrivateState; +export interface TextBasedLayerPanelProps extends DatasourceLayerPanelProps { + state: TextBasedPrivateState; } -export function LayerPanel({ state, layerId, dataViews }: TextBasedLanguageLayerPanelProps) { +export function LayerPanel({ state, layerId, dataViews }: TextBasedLayerPanelProps) { const layer = state.layers[layerId]; const dataView = dataViews.indexPatternRefs.find((ref) => ref.id === layer.index); const notFoundTitleLabel = i18n.translate('xpack.lens.layerPanel.missingDataView', { diff --git a/x-pack/plugins/lens/public/text_based_languages_datasource/mocks.ts b/x-pack/plugins/lens/public/datasources/text_based/mocks.ts similarity index 92% rename from x-pack/plugins/lens/public/text_based_languages_datasource/mocks.ts rename to x-pack/plugins/lens/public/datasources/text_based/mocks.ts index adca02ab2299d..8b191b815100e 100644 --- a/x-pack/plugins/lens/public/text_based_languages_datasource/mocks.ts +++ b/x-pack/plugins/lens/public/datasources/text_based/mocks.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { DragContextState } from '../drag_drop'; +import { DragContextState } from '../../drag_drop'; export function createMockedDragDropContext(): jest.Mocked { return { diff --git a/x-pack/plugins/lens/public/text_based_languages_datasource/text_based_languages.test.ts b/x-pack/plugins/lens/public/datasources/text_based/text_based_languages.test.ts similarity index 87% rename from x-pack/plugins/lens/public/text_based_languages_datasource/text_based_languages.test.ts rename to x-pack/plugins/lens/public/datasources/text_based/text_based_languages.test.ts index ae7e84c61b3c5..968a1ac1e496c 100644 --- a/x-pack/plugins/lens/public/text_based_languages_datasource/text_based_languages.test.ts +++ b/x-pack/plugins/lens/public/datasources/text_based/text_based_languages.test.ts @@ -8,14 +8,14 @@ import { coreMock } from '@kbn/core/public/mocks'; import { IStorageWrapper } from '@kbn/kibana-utils-plugin/public'; import { expressionsPluginMock } from '@kbn/expressions-plugin/public/mocks'; -import { TextBasedLanguagesPersistedState, TextBasedLanguagesPrivateState } from './types'; +import { TextBasedPersistedState, TextBasedPrivateState } from './types'; import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; import { dataViewPluginMocks } from '@kbn/data-views-plugin/public/mocks'; -import { getTextBasedLanguagesDatasource } from './text_based_languages'; -import { generateId } from '../id_generator'; -import { DatasourcePublicAPI, Datasource } from '../types'; +import { getTextBasedDatasource } from './text_based_languages'; +import { generateId } from '../../id_generator'; +import { DatasourcePublicAPI, Datasource } from '../../types'; -jest.mock('../id_generator'); +jest.mock('../../id_generator'); const fieldsOne = [ { @@ -78,14 +78,11 @@ const expectedIndexPatterns = { const indexPatterns = expectedIndexPatterns; describe('IndexPattern Data Source', () => { - let baseState: TextBasedLanguagesPrivateState; - let textBasedLanguagesDatasource: Datasource< - TextBasedLanguagesPrivateState, - TextBasedLanguagesPersistedState - >; + let baseState: TextBasedPrivateState; + let TextBasedDatasource: Datasource; beforeEach(() => { - textBasedLanguagesDatasource = getTextBasedLanguagesDatasource({ + TextBasedDatasource = getTextBasedDatasource({ storage: {} as IStorageWrapper, core: coreMock.createStart(), data: dataPluginMock.createStartContract(), @@ -127,12 +124,12 @@ describe('IndexPattern Data Source', () => { }, }, ], - } as unknown as TextBasedLanguagesPrivateState; + } as unknown as TextBasedPrivateState; }); describe('uniqueLabels', () => { it('appends a suffix to duplicates', () => { - const map = textBasedLanguagesDatasource.uniqueLabels({ + const map = TextBasedDatasource.uniqueLabels({ layers: { a: { columns: [ @@ -154,7 +151,7 @@ describe('IndexPattern Data Source', () => { index: 'foo', }, }, - } as unknown as TextBasedLanguagesPrivateState); + } as unknown as TextBasedPrivateState); expect(map).toMatchInlineSnapshot(` Object { @@ -167,7 +164,7 @@ describe('IndexPattern Data Source', () => { describe('#getPersistedState', () => { it('should persist from saved state', async () => { - expect(textBasedLanguagesDatasource.getPersistableState(baseState)).toEqual({ + expect(TextBasedDatasource.getPersistableState(baseState)).toEqual({ state: { layers: baseState.layers, }, @@ -178,9 +175,23 @@ describe('IndexPattern Data Source', () => { }); }); + describe('#getSelectedFields', () => { + it('should return the fields used per layer', async () => { + expect(TextBasedDatasource?.getSelectedFields?.(baseState)).toEqual(['Test 1']); + }); + + it('should return empty array for empty layers', async () => { + const state = { + ...baseState, + layers: {}, + }; + expect(TextBasedDatasource?.getSelectedFields?.(state)).toEqual([]); + }); + }); + describe('#insertLayer', () => { it('should insert an empty layer into the previous state', () => { - expect(textBasedLanguagesDatasource.insertLayer(baseState, 'newLayer')).toEqual({ + expect(TextBasedDatasource.insertLayer(baseState, 'newLayer')).toEqual({ ...baseState, layers: { ...baseState.layers, @@ -205,7 +216,7 @@ describe('IndexPattern Data Source', () => { describe('#removeLayer', () => { it('should remove a layer', () => { - expect(textBasedLanguagesDatasource.removeLayer(baseState, 'a')).toEqual({ + expect(TextBasedDatasource.removeLayer(baseState, 'a')).toEqual({ ...baseState, layers: { a: { @@ -229,7 +240,7 @@ describe('IndexPattern Data Source', () => { describe('#createEmptyLayer', () => { it('creates state with empty layers', () => { - expect(textBasedLanguagesDatasource.createEmptyLayer('index-pattern-id')).toEqual({ + expect(TextBasedDatasource.createEmptyLayer('index-pattern-id')).toEqual({ fieldList: [], layers: {}, indexPatternRefs: [], @@ -240,7 +251,7 @@ describe('IndexPattern Data Source', () => { describe('#getLayers', () => { it('should list the current layers', () => { expect( - textBasedLanguagesDatasource.getLayers({ + TextBasedDatasource.getLayers({ layers: { a: { columns: [ @@ -279,7 +290,7 @@ describe('IndexPattern Data Source', () => { index: 'foo', }, }, - } as unknown as TextBasedLanguagesPrivateState) + } as unknown as TextBasedPrivateState) ).toEqual(['a']); }); }); @@ -298,8 +309,8 @@ describe('IndexPattern Data Source', () => { name: 'Foo', }, }, - } as unknown as TextBasedLanguagesPrivateState; - const suggestions = textBasedLanguagesDatasource.getDatasourceSuggestionsForVisualizeField( + } as unknown as TextBasedPrivateState; + const suggestions = TextBasedDatasource.getDatasourceSuggestionsForVisualizeField( state, '1', '', @@ -417,8 +428,8 @@ describe('IndexPattern Data Source', () => { index: 'foo', }, }, - } as unknown as TextBasedLanguagesPrivateState; - expect(textBasedLanguagesDatasource.getErrorMessages(state, indexPatterns)).toEqual([ + } as unknown as TextBasedPrivateState; + expect(TextBasedDatasource.getErrorMessages(state, indexPatterns)).toEqual([ { longMessage: 'error 1', shortMessage: 'error 1' }, { longMessage: 'error 2', shortMessage: 'error 2' }, ]); @@ -466,9 +477,9 @@ describe('IndexPattern Data Source', () => { index: '1', }, }, - } as unknown as TextBasedLanguagesPrivateState; + } as unknown as TextBasedPrivateState; expect( - textBasedLanguagesDatasource.isTimeBased(state, { + TextBasedDatasource.isTimeBased(state, { ...indexPatterns, }) ).toEqual(true); @@ -513,9 +524,9 @@ describe('IndexPattern Data Source', () => { index: '1', }, }, - } as unknown as TextBasedLanguagesPrivateState; + } as unknown as TextBasedPrivateState; expect( - textBasedLanguagesDatasource.isTimeBased(state, { + TextBasedDatasource.isTimeBased(state, { ...indexPatterns, '1': { ...indexPatterns['1'], timeFieldName: undefined }, }) @@ -525,10 +536,8 @@ describe('IndexPattern Data Source', () => { describe('#toExpression', () => { it('should generate an empty expression when no columns are selected', async () => { - const state = textBasedLanguagesDatasource.initialize(); - expect(textBasedLanguagesDatasource.toExpression(state, 'first', indexPatterns)).toEqual( - null - ); + const state = TextBasedDatasource.initialize(); + expect(TextBasedDatasource.toExpression(state, 'first', indexPatterns)).toEqual(null); }); it('should generate an expression for an SQL query', async () => { @@ -576,9 +585,9 @@ describe('IndexPattern Data Source', () => { { id: '2', title: 'my-fake-restricted-pattern' }, { id: '3', title: 'my-compatible-pattern' }, ], - } as unknown as TextBasedLanguagesPrivateState; + } as unknown as TextBasedPrivateState; - expect(textBasedLanguagesDatasource.toExpression(queryBaseState, 'a', indexPatterns)) + expect(TextBasedDatasource.toExpression(queryBaseState, 'a', indexPatterns)) .toMatchInlineSnapshot(` Object { "chain": Array [ @@ -621,7 +630,7 @@ describe('IndexPattern Data Source', () => { let publicAPI: DatasourcePublicAPI; beforeEach(async () => { - publicAPI = textBasedLanguagesDatasource.getPublicAPI({ + publicAPI = TextBasedDatasource.getPublicAPI({ state: baseState, layerId: 'a', indexPatterns, @@ -676,9 +685,9 @@ describe('IndexPattern Data Source', () => { }, }, ], - } as unknown as TextBasedLanguagesPrivateState; + } as unknown as TextBasedPrivateState; - publicAPI = textBasedLanguagesDatasource.getPublicAPI({ + publicAPI = TextBasedDatasource.getPublicAPI({ state, layerId: 'a', indexPatterns, @@ -701,9 +710,9 @@ describe('IndexPattern Data Source', () => { }, }, ], - } as unknown as TextBasedLanguagesPrivateState; + } as unknown as TextBasedPrivateState; - publicAPI = textBasedLanguagesDatasource.getPublicAPI({ + publicAPI = TextBasedDatasource.getPublicAPI({ state, layerId: 'a', indexPatterns, diff --git a/x-pack/plugins/lens/public/text_based_languages_datasource/text_based_languages.tsx b/x-pack/plugins/lens/public/datasources/text_based/text_based_languages.tsx similarity index 74% rename from x-pack/plugins/lens/public/text_based_languages_datasource/text_based_languages.tsx rename to x-pack/plugins/lens/public/datasources/text_based/text_based_languages.tsx index 7157f643c6e8c..f7e78e830669a 100644 --- a/x-pack/plugins/lens/public/text_based_languages_datasource/text_based_languages.tsx +++ b/x-pack/plugins/lens/public/datasources/text_based/text_based_languages.tsx @@ -14,6 +14,7 @@ import { IStorageWrapper } from '@kbn/kibana-utils-plugin/public'; import type { AggregateQuery } from '@kbn/es-query'; import type { SavedObjectReference } from '@kbn/core/public'; import { EuiButtonEmpty, EuiFormRow } from '@elastic/eui'; +import { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public'; import type { ExpressionsStart, DatatableColumnType } from '@kbn/expressions-plugin/public'; import type { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public'; import { DataPublicPluginStart } from '@kbn/data-plugin/public'; @@ -25,25 +26,25 @@ import { DataType, TableChangeType, DatasourceDimensionTriggerProps, -} from '../types'; -import { generateId } from '../id_generator'; +} from '../../types'; +import { generateId } from '../../id_generator'; import { toExpression } from './to_expression'; -import { TextBasedLanguagesDataPanel } from './datapanel'; +import { TextBasedDataPanel } from './datapanel'; import type { - TextBasedLanguagesPrivateState, - TextBasedLanguagesPersistedState, - TextBasedLanguagesLayerColumn, - TextBasedLanguageField, + TextBasedPrivateState, + TextBasedPersistedState, + TextBasedLayerColumn, + TextBasedField, } from './types'; import { FieldSelect } from './field_select'; -import type { Datasource, IndexPatternMap } from '../types'; +import type { Datasource, IndexPatternMap } from '../../types'; import { LayerPanel } from './layerpanel'; function getLayerReferenceName(layerId: string) { return `textBasedLanguages-datasource-layer-${layerId}`; } -export function getTextBasedLanguagesDatasource({ +export function getTextBasedDatasource({ core, storage, data, @@ -56,7 +57,7 @@ export function getTextBasedLanguagesDatasource({ expressions: ExpressionsStart; dataViews: DataViewsPublicPluginStart; }) { - const getSuggestionsForState = (state: TextBasedLanguagesPrivateState) => { + const getSuggestionsForState = (state: TextBasedPrivateState) => { return Object.entries(state.layers)?.map(([id, layer]) => { return { state: { @@ -83,7 +84,7 @@ export function getTextBasedLanguagesDatasource({ }); }; const getSuggestionsForVisualizeField = ( - state: TextBasedLanguagesPrivateState, + state: TextBasedPrivateState, indexPatternId: string, fieldName: string, indexPatterns: IndexPatternMap @@ -153,11 +154,8 @@ export function getTextBasedLanguagesDatasource({ return []; }; - const TextBasedLanguagesDatasource: Datasource< - TextBasedLanguagesPrivateState, - TextBasedLanguagesPersistedState - > = { - id: 'textBasedLanguages', + const TextBasedDatasource: Datasource = { + id: 'textBased', checkIntegrity: () => { return []; @@ -188,7 +186,7 @@ export function getTextBasedLanguagesDatasource({ return errors; }, initialize( - state?: TextBasedLanguagesPersistedState, + state?: TextBasedPersistedState, savedObjectReferences?, context?, indexPatternRefs?, @@ -217,7 +215,7 @@ export function getTextBasedLanguagesDatasource({ return Object.values(state.layers).map(({ index }) => index); }, - getPersistableState({ layers }: TextBasedLanguagesPrivateState) { + getPersistableState({ layers }: TextBasedPrivateState) { const savedObjectReferences: SavedObjectReference[] = []; Object.entries(layers).forEach(([layerId, { index, ...persistableLayer }]) => { if (index) { @@ -237,7 +235,7 @@ export function getTextBasedLanguagesDatasource({ if (!column || !indexPattern) return false; return true; }, - insertLayer(state: TextBasedLanguagesPrivateState, newLayerId: string) { + insertLayer(state: TextBasedPrivateState, newLayerId: string) { const layer = Object.values(state?.layers)?.[0]; const query = layer?.query; const columns = layer?.allColumns ?? []; @@ -267,7 +265,7 @@ export function getTextBasedLanguagesDatasource({ }; }, - removeLayer(state: TextBasedLanguagesPrivateState, layerId: string) { + removeLayer(state: TextBasedPrivateState, layerId: string) { const newLayers = { ...state.layers, [layerId]: { @@ -283,7 +281,7 @@ export function getTextBasedLanguagesDatasource({ }; }, - clearLayer(state: TextBasedLanguagesPrivateState, layerId: string) { + clearLayer(state: TextBasedPrivateState, layerId: string) { return { ...state, layers: { @@ -293,7 +291,7 @@ export function getTextBasedLanguagesDatasource({ }; }, - getLayers(state: TextBasedLanguagesPrivateState) { + getLayers(state: TextBasedPrivateState) { return state && state.layers ? Object.keys(state?.layers) : []; }, isTimeBased: (state, indexPatterns) => { @@ -306,7 +304,7 @@ export function getTextBasedLanguagesDatasource({ }) ); }, - getUsedDataView: (state: TextBasedLanguagesPrivateState, layerId?: string) => { + getUsedDataView: (state: TextBasedPrivateState, layerId?: string) => { if (!layerId) { const layers = Object.values(state.layers); return layers?.[0]?.index; @@ -330,29 +328,42 @@ export function getTextBasedLanguagesDatasource({ toExpression: (state, layerId, indexPatterns) => { return toExpression(state, layerId); }, + getSelectedFields(state) { + const fields: string[] = []; + Object.values(state?.layers)?.forEach((l) => { + const { columns } = l; + Object.values(columns).forEach((c) => { + if ('fieldName' in c) { + fields.push(c.fieldName); + } + }); + }); + return fields; + }, - renderDataPanel( - domElement: Element, - props: DatasourceDataPanelProps - ) { + renderDataPanel(domElement: Element, props: DatasourceDataPanelProps) { + const layerFields = TextBasedDatasource?.getSelectedFields?.(props.state); render( - - - , + + + + + , domElement ); }, renderDimensionTrigger: ( domElement: Element, - props: DatasourceDimensionTriggerProps + props: DatasourceDimensionTriggerProps ) => { - const columnLabelMap = TextBasedLanguagesDatasource.uniqueLabels(props.state); + const columnLabelMap = TextBasedDatasource.uniqueLabels(props.state); const layer = props.state.layers[props.layerId]; const selectedField = layer?.allColumns?.find((column) => column.columnId === props.columnId); let customLabel: string | undefined = columnLabelMap[props.columnId]; @@ -377,90 +388,97 @@ export function getTextBasedLanguagesDatasource({ ); }, - getRenderEventCounters(state: TextBasedLanguagesPrivateState): string[] { + getRenderEventCounters(state: TextBasedPrivateState): string[] { return []; }, renderDimensionEditor: ( domElement: Element, - props: DatasourceDimensionEditorProps + props: DatasourceDimensionEditorProps ) => { const fields = props.state.fieldList; const selectedField = props.state.layers[props.layerId]?.allColumns?.find( (column) => column.columnId === props.columnId ); render( - - { - const meta = fields.find((f) => f.name === choice.field)?.meta; - const newColumn = { - columnId: props.columnId, - fieldName: choice.field, - meta, - }; - return props.setState( - !selectedField - ? { - ...props.state, - layers: { - ...props.state.layers, - [props.layerId]: { - ...props.state.layers[props.layerId], - columns: [...props.state.layers[props.layerId].columns, newColumn], - allColumns: [...props.state.layers[props.layerId].allColumns, newColumn], + + + { + const meta = fields.find((f) => f.name === choice.field)?.meta; + const newColumn = { + columnId: props.columnId, + fieldName: choice.field, + meta, + }; + return props.setState( + !selectedField + ? { + ...props.state, + layers: { + ...props.state.layers, + [props.layerId]: { + ...props.state.layers[props.layerId], + columns: [...props.state.layers[props.layerId].columns, newColumn], + allColumns: [ + ...props.state.layers[props.layerId].allColumns, + newColumn, + ], + }, }, - }, - } - : { - ...props.state, - layers: { - ...props.state.layers, - [props.layerId]: { - ...props.state.layers[props.layerId], - columns: props.state.layers[props.layerId].columns.map((col) => - col.columnId !== props.columnId - ? col - : { ...col, fieldName: choice.field } - ), - allColumns: props.state.layers[props.layerId].allColumns.map((col) => - col.columnId !== props.columnId - ? col - : { ...col, fieldName: choice.field } - ), + } + : { + ...props.state, + layers: { + ...props.state.layers, + [props.layerId]: { + ...props.state.layers[props.layerId], + columns: props.state.layers[props.layerId].columns.map((col) => + col.columnId !== props.columnId + ? col + : { ...col, fieldName: choice.field } + ), + allColumns: props.state.layers[props.layerId].allColumns.map((col) => + col.columnId !== props.columnId + ? col + : { ...col, fieldName: choice.field } + ), + }, }, - }, - } - ); - }} - /> - , + } + ); + }} + /> + + , domElement ); }, renderLayerPanel: ( domElement: Element, - props: DatasourceLayerPanelProps + props: DatasourceLayerPanelProps ) => { render( - - - , + + + + + , domElement ); }, - uniqueLabels(state: TextBasedLanguagesPrivateState) { + uniqueLabels(state: TextBasedPrivateState) { const layers = state.layers; const columnLabelMap = {} as Record; const counts = {} as Record; @@ -536,9 +554,9 @@ export function getTextBasedLanguagesDatasource({ return false; }, - getPublicAPI({ state, layerId }: PublicAPIProps) { + getPublicAPI({ state, layerId }: PublicAPIProps) { return { - datasourceId: 'textBasedLanguages', + datasourceId: 'textBased', getTableSpec: () => { const columns = state.layers[layerId]?.columns.filter((c) => { @@ -555,7 +573,7 @@ export function getTextBasedLanguagesDatasource({ getOperationForColumnId: (columnId: string) => { const layer = state.layers[layerId]; const column = layer?.allColumns?.find((c) => c.columnId === columnId); - const columnLabelMap = TextBasedLanguagesDatasource.uniqueLabels(state); + const columnLabelMap = TextBasedDatasource.uniqueLabels(state); if (column) { return { @@ -591,9 +609,7 @@ export function getTextBasedLanguagesDatasource({ }; }, getDatasourceSuggestionsForField(state, draggedField) { - const field = state.fieldList.find( - (f) => f.id === (draggedField as TextBasedLanguageField).id - ); + const field = state.fieldList.find((f) => f.id === (draggedField as TextBasedField).id); if (!field) return []; return Object.entries(state.layers)?.map(([id, layer]) => { const newId = generateId(); @@ -650,14 +666,10 @@ export function getTextBasedLanguagesDatasource({ isEqual: () => true, }; - return TextBasedLanguagesDatasource; + return TextBasedDatasource; } -function blankLayer( - index: string, - query?: AggregateQuery, - columns?: TextBasedLanguagesLayerColumn[] -) { +function blankLayer(index: string, query?: AggregateQuery, columns?: TextBasedLayerColumn[]) { return { index, query, diff --git a/x-pack/plugins/lens/public/text_based_languages_datasource/to_expression.ts b/x-pack/plugins/lens/public/datasources/text_based/to_expression.ts similarity index 80% rename from x-pack/plugins/lens/public/text_based_languages_datasource/to_expression.ts rename to x-pack/plugins/lens/public/datasources/text_based/to_expression.ts index aa7a264673a3e..dba9a93555ce2 100644 --- a/x-pack/plugins/lens/public/text_based_languages_datasource/to_expression.ts +++ b/x-pack/plugins/lens/public/datasources/text_based/to_expression.ts @@ -7,13 +7,10 @@ import { Ast } from '@kbn/interpreter'; import { textBasedQueryStateToExpressionAst } from '@kbn/data-plugin/common'; -import type { OriginalColumn } from '../../common/types'; -import { TextBasedLanguagesPrivateState, TextBasedLanguagesLayer, IndexPatternRef } from './types'; +import type { OriginalColumn } from '../../../common/types'; +import { TextBasedPrivateState, TextBasedLayer, IndexPatternRef } from './types'; -function getExpressionForLayer( - layer: TextBasedLanguagesLayer, - refs: IndexPatternRef[] -): Ast | null { +function getExpressionForLayer(layer: TextBasedLayer, refs: IndexPatternRef[]): Ast | null { if (!layer.columns || layer.columns?.length === 0) { return null; } @@ -53,7 +50,7 @@ function getExpressionForLayer( return textBasedQueryToAst; } -export function toExpression(state: TextBasedLanguagesPrivateState, layerId: string) { +export function toExpression(state: TextBasedPrivateState, layerId: string) { if (state.layers[layerId]) { return getExpressionForLayer(state.layers[layerId], state.indexPatternRefs); } diff --git a/x-pack/plugins/lens/public/text_based_languages_datasource/types.ts b/x-pack/plugins/lens/public/datasources/text_based/types.ts similarity index 65% rename from x-pack/plugins/lens/public/text_based_languages_datasource/types.ts rename to x-pack/plugins/lens/public/datasources/text_based/types.ts index 11b9612624efd..0e30e0d517054 100644 --- a/x-pack/plugins/lens/public/text_based_languages_datasource/types.ts +++ b/x-pack/plugins/lens/public/datasources/text_based/types.ts @@ -7,33 +7,33 @@ import type { DatatableColumn } from '@kbn/expressions-plugin/public'; import type { AggregateQuery } from '@kbn/es-query'; import type { VisualizeFieldContext } from '@kbn/ui-actions-plugin/public'; -import type { VisualizeEditorContext } from '../types'; +import type { VisualizeEditorContext } from '../../types'; -export interface TextBasedLanguagesLayerColumn { +export interface TextBasedLayerColumn { columnId: string; fieldName: string; meta?: DatatableColumn['meta']; } -export interface TextBasedLanguageField { +export interface TextBasedField { id: string; field: string; } -export interface TextBasedLanguagesLayer { +export interface TextBasedLayer { index: string; query: AggregateQuery | undefined; - columns: TextBasedLanguagesLayerColumn[]; - allColumns: TextBasedLanguagesLayerColumn[]; + columns: TextBasedLayerColumn[]; + allColumns: TextBasedLayerColumn[]; timeField?: string; errors?: Error[]; } -export interface TextBasedLanguagesPersistedState { - layers: Record; +export interface TextBasedPersistedState { + layers: Record; } -export type TextBasedLanguagesPrivateState = TextBasedLanguagesPersistedState & { +export type TextBasedPrivateState = TextBasedPersistedState & { indexPatternRefs: IndexPatternRef[]; fieldList: DatatableColumn[]; initialContext?: VisualizeFieldContext | VisualizeEditorContext; diff --git a/x-pack/plugins/lens/public/text_based_languages_datasource/utils.test.ts b/x-pack/plugins/lens/public/datasources/text_based/utils.test.ts similarity index 97% rename from x-pack/plugins/lens/public/text_based_languages_datasource/utils.test.ts rename to x-pack/plugins/lens/public/datasources/text_based/utils.test.ts index 1e7096414d19e..1698ae536f44f 100644 --- a/x-pack/plugins/lens/public/text_based_languages_datasource/utils.test.ts +++ b/x-pack/plugins/lens/public/datasources/text_based/utils.test.ts @@ -9,14 +9,14 @@ import type { DatatableColumn } from '@kbn/expressions-plugin/public'; import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; import { expressionsPluginMock } from '@kbn/expressions-plugin/public/mocks'; import { dataViewPluginMocks } from '@kbn/data-views-plugin/public/mocks'; -import { mockDataViewsService } from '../data_views_service/mocks'; +import { mockDataViewsService } from '../../data_views_service/mocks'; import { getIndexPatternFromTextBasedQuery, loadIndexPatternRefs, getStateFromAggregateQuery, getAllColumns, } from './utils'; -import type { TextBasedLanguagesLayerColumn } from './types'; +import type { TextBasedLayerColumn } from './types'; import { type AggregateQuery } from '@kbn/es-query'; jest.mock('./fetch_data_from_aggregate_query', () => ({ @@ -92,7 +92,7 @@ describe('Text based languages utils', () => { type: 'number', }, }, - ] as TextBasedLanguagesLayerColumn[]; + ] as TextBasedLayerColumn[]; const columnsFromQuery = [ { name: 'timestamp', diff --git a/x-pack/plugins/lens/public/text_based_languages_datasource/utils.ts b/x-pack/plugins/lens/public/datasources/text_based/utils.ts similarity index 92% rename from x-pack/plugins/lens/public/text_based_languages_datasource/utils.ts rename to x-pack/plugins/lens/public/datasources/text_based/utils.ts index 5504cd39bd6a1..5078c967ff9e8 100644 --- a/x-pack/plugins/lens/public/text_based_languages_datasource/utils.ts +++ b/x-pack/plugins/lens/public/datasources/text_based/utils.ts @@ -10,14 +10,10 @@ import type { ExpressionsStart } from '@kbn/expressions-plugin/public'; import { type AggregateQuery, getIndexPatternFromSQLQuery } from '@kbn/es-query'; import type { DatatableColumn } from '@kbn/expressions-plugin/public'; -import { generateId } from '../id_generator'; +import { generateId } from '../../id_generator'; import { fetchDataFromAggregateQuery } from './fetch_data_from_aggregate_query'; -import type { - IndexPatternRef, - TextBasedLanguagesPrivateState, - TextBasedLanguagesLayerColumn, -} from './types'; +import type { IndexPatternRef, TextBasedPrivateState, TextBasedLayerColumn } from './types'; export async function loadIndexPatternRefs( indexPatternsService: DataViewsPublicPluginStart @@ -36,7 +32,7 @@ export async function loadIndexPatternRefs( } export const getAllColumns = ( - existingColumns: TextBasedLanguagesLayerColumn[], + existingColumns: TextBasedLayerColumn[], columnsFromQuery: DatatableColumn[] ) => { // filter out columns that do not exist on the query @@ -64,7 +60,7 @@ export const getAllColumns = ( }; export async function getStateFromAggregateQuery( - state: TextBasedLanguagesPrivateState, + state: TextBasedPrivateState, query: AggregateQuery, dataViews: DataViewsPublicPluginStart, data: DataPublicPluginStart, @@ -80,7 +76,7 @@ export async function getStateFromAggregateQuery( // get the id of the dataview const index = indexPatternRefs.find((r) => r.title === indexPattern)?.id ?? ''; let columnsFromQuery: DatatableColumn[] = []; - let allColumns: TextBasedLanguagesLayerColumn[] = []; + let allColumns: TextBasedLayerColumn[] = []; let timeFieldName; try { const table = await fetchDataFromAggregateQuery(query, dataViews, data, expressions); diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_helpers.ts b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_helpers.ts index c96a022f4aed2..81298a97f650e 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_helpers.ts +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_helpers.ts @@ -209,7 +209,7 @@ export function getVisualizeFieldSuggestions({ // suggestions for visualizing textbased languages if (visualizeTriggerFieldContext && 'query' in visualizeTriggerFieldContext) { if (visualizeTriggerFieldContext.query) { - return suggestions.find((s) => s.datasourceId === 'textBasedLanguages'); + return suggestions.find((s) => s.datasourceId === 'textBased'); } } diff --git a/x-pack/plugins/lens/public/embeddable/embeddable.tsx b/x-pack/plugins/lens/public/embeddable/embeddable.tsx index 8da6ca0e6d5c0..77164cfa1e1fa 100644 --- a/x-pack/plugins/lens/public/embeddable/embeddable.tsx +++ b/x-pack/plugins/lens/public/embeddable/embeddable.tsx @@ -304,13 +304,21 @@ export class Embeddable this.lensInspector = getLensInspectorService(deps.inspector); this.expressionRenderer = deps.expressionRenderer; + let containerStateChangedCalledAlready = false; this.initializeSavedVis(initialInput) - .then(() => this.onContainerStateChanged(initialInput)) + .then(() => { + if (!containerStateChangedCalledAlready) { + this.onContainerStateChanged(initialInput); + } else { + this.reload(); + } + }) .catch((e) => this.onFatalError(e)); - this.subscription = this.getUpdated$().subscribe(() => - this.onContainerStateChanged(this.input) - ); + this.subscription = this.getUpdated$().subscribe(() => { + containerStateChangedCalledAlready = true; + this.onContainerStateChanged(this.input); + }); const input$ = this.getInput$(); this.embeddableTitle = this.getTitle(); diff --git a/x-pack/plugins/lens/public/embeddable/embeddable_component.tsx b/x-pack/plugins/lens/public/embeddable/embeddable_component.tsx index 98c8d363a45b7..56939b54299ce 100644 --- a/x-pack/plugins/lens/public/embeddable/embeddable_component.tsx +++ b/x-pack/plugins/lens/public/embeddable/embeddable_component.tsx @@ -22,7 +22,7 @@ import { } from '@kbn/embeddable-plugin/public'; import type { LensByReferenceInput, LensByValueInput } from './embeddable'; import type { Document } from '../persistence'; -import type { IndexPatternPersistedState } from '../indexpattern_datasource/types'; +import type { FormBasedPersistedState } from '../datasources/form_based/types'; import type { XYState } from '../visualizations/xy/types'; import type { PieVisualizationState, LegacyMetricState } from '../../common'; import type { DatatableVisualizationState } from '../visualizations/datatable/visualization'; @@ -37,7 +37,7 @@ type LensAttributes = Omit< visualizationType: TVisType; state: Omit & { datasourceStates: { - indexpattern: IndexPatternPersistedState; + formBased: FormBasedPersistedState; }; visualization: TVisState; }; diff --git a/x-pack/plugins/lens/public/index.ts b/x-pack/plugins/lens/public/index.ts index 9efe67c4283e3..54380bd7eec63 100644 --- a/x-pack/plugins/lens/public/index.ts +++ b/x-pack/plugins/lens/public/index.ts @@ -44,7 +44,7 @@ export type { DatatableVisualizationState } from './visualizations/datatable/vis export type { HeatmapVisualizationState } from './visualizations/heatmap/types'; export type { GaugeVisualizationState } from './visualizations/gauge/constants'; export type { - IndexPatternPersistedState, + FormBasedPersistedState, PersistedIndexPatternLayer, OperationType, IncompleteColumn, @@ -75,8 +75,8 @@ export type { FormulaPublicApi, StaticValueIndexPatternColumn, TimeScaleIndexPatternColumn, - IndexPatternLayer, -} from './indexpattern_datasource/types'; + FormBasedLayer, +} from './datasources/form_based/types'; export type { XYArgs, XYRender, diff --git a/x-pack/plugins/lens/public/plugin.ts b/x-pack/plugins/lens/public/plugin.ts index 6b06978befea7..c4d4cf9bfab9f 100644 --- a/x-pack/plugins/lens/public/plugin.ts +++ b/x-pack/plugins/lens/public/plugin.ts @@ -52,11 +52,11 @@ import type { AdvancedUiActionsSetup } from '@kbn/ui-actions-enhanced-plugin/pub import type { DocLinksStart } from '@kbn/core-doc-links-browser'; import type { EditorFrameService as EditorFrameServiceType } from './editor_frame_service'; import type { - IndexPatternDatasource as IndexPatternDatasourceType, - IndexPatternDatasourceSetupPlugins, + FormBasedDatasource as FormBasedDatasourceType, + FormBasedDatasourceSetupPlugins, FormulaPublicApi, -} from './indexpattern_datasource'; -import type { TextBasedLanguagesDatasource as TextBasedLanguagesDatasourceType } from './text_based_languages_datasource'; +} from './datasources/form_based'; +import type { TextBasedDatasource as TextBasedDatasourceType } from './datasources/text_based'; import type { XyVisualization as XyVisualizationType, @@ -231,8 +231,8 @@ export class LensPlugin { private editorFrameService: EditorFrameServiceType | undefined; private editorFrameSetup: EditorFrameSetup | undefined; private queuedVisualizations: Array Promise)> = []; - private indexpatternDatasource: IndexPatternDatasourceType | undefined; - private textBasedLanguagesDatasource: TextBasedLanguagesDatasourceType | undefined; + private FormBasedDatasource: FormBasedDatasourceType | undefined; + private TextBasedDatasource: TextBasedDatasourceType | undefined; private xyVisualization: XyVisualizationType | undefined; private legacyMetricVisualization: LegacyMetricVisualizationType | undefined; private metricVisualization: MetricVisualizationType | undefined; @@ -423,19 +423,19 @@ export class LensPlugin { const { DatatableVisualization, EditorFrameService, - IndexPatternDatasource, + FormBasedDatasource, XyVisualization, LegacyMetricVisualization, MetricVisualization, PieVisualization, HeatmapVisualization, GaugeVisualization, - TextBasedLanguagesDatasource, + TextBasedDatasource, } = await import('./async_services'); this.datatableVisualization = new DatatableVisualization(); this.editorFrameService = new EditorFrameService(); - this.indexpatternDatasource = new IndexPatternDatasource(); - this.textBasedLanguagesDatasource = new TextBasedLanguagesDatasource(); + this.FormBasedDatasource = new FormBasedDatasource(); + this.TextBasedDatasource = new TextBasedDatasource(); this.xyVisualization = new XyVisualization(); this.legacyMetricVisualization = new LegacyMetricVisualization(); this.metricVisualization = new MetricVisualization(); @@ -445,7 +445,7 @@ export class LensPlugin { const editorFrameSetupInterface = this.editorFrameService.setup(); - const dependencies: IndexPatternDatasourceSetupPlugins & + const dependencies: FormBasedDatasourceSetupPlugins & XyVisualizationPluginSetupPlugins & DatatableVisualizationPluginSetupPlugins & LegacyMetricVisualizationPluginSetupPlugins & @@ -458,8 +458,8 @@ export class LensPlugin { formatFactory, eventAnnotation, }; - this.indexpatternDatasource.setup(core, dependencies); - this.textBasedLanguagesDatasource.setup(core, dependencies); + this.FormBasedDatasource.setup(core, dependencies); + this.TextBasedDatasource.setup(core, dependencies); this.xyVisualization.setup(core, dependencies); this.datatableVisualization.setup(core, dependencies); this.legacyMetricVisualization.setup(core, dependencies); diff --git a/x-pack/plugins/lens/public/shared_components/field_picker/lens_field_icon.tsx b/x-pack/plugins/lens/public/shared_components/field_picker/lens_field_icon.tsx index fabb8cab6fd0e..e3be012647e8c 100644 --- a/x-pack/plugins/lens/public/shared_components/field_picker/lens_field_icon.tsx +++ b/x-pack/plugins/lens/public/shared_components/field_picker/lens_field_icon.tsx @@ -8,7 +8,7 @@ import React from 'react'; import { FieldIcon, FieldIconProps } from '@kbn/react-field'; import { DataType } from '../../types'; -import { normalizeOperationDataType } from '../../indexpattern_datasource/pure_utils'; +import { normalizeOperationDataType } from '../../datasources/form_based/pure_utils'; export function LensFieldIcon({ type, ...rest }: FieldIconProps & { type: DataType }) { return ( diff --git a/x-pack/plugins/lens/public/state_management/init_middleware/load_initial.ts b/x-pack/plugins/lens/public/state_management/init_middleware/load_initial.ts index 5b942eff4a683..69e93f7a763a3 100644 --- a/x-pack/plugins/lens/public/state_management/init_middleware/load_initial.ts +++ b/x-pack/plugins/lens/public/state_management/init_middleware/load_initial.ts @@ -117,7 +117,7 @@ export function loadInitial( let activeDatasourceId: string | undefined; if (initialContext && 'query' in initialContext) { - activeDatasourceId = 'textBasedLanguages'; + activeDatasourceId = 'textBased'; } if ( diff --git a/x-pack/plugins/lens/public/trigger_actions/open_in_discover_action.ts b/x-pack/plugins/lens/public/trigger_actions/open_in_discover_action.ts index 18782d618a24d..45494c5e14b68 100644 --- a/x-pack/plugins/lens/public/trigger_actions/open_in_discover_action.ts +++ b/x-pack/plugins/lens/public/trigger_actions/open_in_discover_action.ts @@ -17,7 +17,7 @@ interface Context { embeddable: IEmbeddable; } -export const getDiscoverHelpersAsync = async () => await import('./open_in_discover_helpers'); +export const getDiscoverHelpersAsync = async () => await import('../async_services'); export const createOpenInDiscoverAction = ( discover: Pick, diff --git a/x-pack/plugins/lens/public/trigger_actions/open_in_discover_drilldown.test.tsx b/x-pack/plugins/lens/public/trigger_actions/open_in_discover_drilldown.test.tsx index 84ae2a21a9a92..c4e8fe050df23 100644 --- a/x-pack/plugins/lens/public/trigger_actions/open_in_discover_drilldown.test.tsx +++ b/x-pack/plugins/lens/public/trigger_actions/open_in_discover_drilldown.test.tsx @@ -26,6 +26,13 @@ jest.mock('./open_in_discover_helpers', () => ({ describe('open in discover drilldown', () => { let drilldown: OpenInDiscoverDrilldown; + const originalOpen = window.open; + + // Prevent the JSDOM error about missing "window.open" + beforeAll(() => { + window.open = jest.fn(); + }); + beforeEach(() => { drilldown = new OpenInDiscoverDrilldown({ discover: {} as DiscoverSetup, @@ -34,6 +41,11 @@ describe('open in discover drilldown', () => { application: () => ({} as ApplicationStart), }); }); + + afterAll(() => { + window.open = originalOpen; + }); + it('provides UI to edit config', () => { const Component = (drilldown as unknown as { ReactCollectConfig: React.FC }) .ReactCollectConfig; diff --git a/x-pack/plugins/lens/public/trigger_actions/open_in_discover_drilldown.tsx b/x-pack/plugins/lens/public/trigger_actions/open_in_discover_drilldown.tsx index fa262c6b0d534..2022e97fb9b45 100644 --- a/x-pack/plugins/lens/public/trigger_actions/open_in_discover_drilldown.tsx +++ b/x-pack/plugins/lens/public/trigger_actions/open_in_discover_drilldown.tsx @@ -30,7 +30,7 @@ interface EmbeddableQueryInput extends EmbeddableInput { timeRange?: TimeRange; } -export const getDiscoverHelpersAsync = async () => await import('./open_in_discover_helpers'); +export const getDiscoverHelpersAsync = async () => await import('../async_services'); /** @internal */ export type EmbeddableWithQueryInput = IEmbeddable; diff --git a/x-pack/plugins/lens/public/types.ts b/x-pack/plugins/lens/public/types.ts index 29aff3d428690..389e500488c0d 100644 --- a/x-pack/plugins/lens/public/types.ts +++ b/x-pack/plugins/lens/public/types.ts @@ -47,7 +47,7 @@ import { LENS_EDIT_PAGESIZE_ACTION, } from './visualizations/datatable/components/constants'; import type { LensInspector } from './lens_inspector_service'; -import type { FormatSelectorOptions } from './indexpattern_datasource/dimension_panel/format_selector'; +import type { FormatSelectorOptions } from './datasources/form_based/dimension_panel/format_selector'; import type { DataViewsState } from './state_management/types'; import type { IndexPatternServiceAPI } from './data_views_service/service'; import type { Document } from './persistence/saved_object_store'; @@ -282,6 +282,8 @@ export interface Datasource { } ) => T; + getSelectedFields?: (state: T) => string[]; + renderDataPanel: ( domElement: Element, props: DatasourceDataPanelProps @@ -752,14 +754,14 @@ export interface VisualizationDimensionChangeProps { frame: FramePublicAPI; } -export interface Suggestion { +export interface Suggestion { visualizationId: string; - datasourceState?: unknown; + datasourceState?: V; datasourceId?: string; columns: number; score: number; title: string; - visualizationState: unknown; + visualizationState: T; previewExpression?: Ast | string; previewIcon: IconType; hide?: boolean; @@ -1158,7 +1160,7 @@ export interface Visualization { getSuggestionFromConvertToLensContext?: ( props: VisualizationStateFromContextChangeProps - ) => Suggestion | undefined; + ) => Suggestion | undefined; } // Use same technique as TriggerContext diff --git a/x-pack/plugins/lens/public/visualizations/datatable/components/columns.tsx b/x-pack/plugins/lens/public/visualizations/datatable/components/columns.tsx index 2ea1cfd059e40..faf2e9d5d826d 100644 --- a/x-pack/plugins/lens/public/visualizations/datatable/components/columns.tsx +++ b/x-pack/plugins/lens/public/visualizations/datatable/components/columns.tsx @@ -48,7 +48,8 @@ export const createGridColumns = ( alignments: Record, headerRowHeight: 'auto' | 'single' | 'custom', headerRowLines: number, - closeCellPopover?: Function + closeCellPopover?: Function, + columnFilterable?: boolean[] ) => { const columnsReverseLookup = table.columns.reduce< Record @@ -57,8 +58,6 @@ export const createGridColumns = ( return memo; }, {}); - const bucketLookup = new Set(bucketColumns); - const getContentData = ({ rowIndex, columnId, @@ -73,8 +72,8 @@ export const createGridColumns = ( }; return visibleColumns.map((field) => { - const filterable = bucketLookup.has(field); const { name, index: colIndex } = columnsReverseLookup[field]; + const filterable = columnFilterable?.[colIndex] || false; const columnArgs = columnConfig.columns.find(({ columnId }) => columnId === field); diff --git a/x-pack/plugins/lens/public/visualizations/datatable/components/table_basic.test.tsx b/x-pack/plugins/lens/public/visualizations/datatable/components/table_basic.test.tsx index 3583225584ec7..5d5c16f9e8be3 100644 --- a/x-pack/plugins/lens/public/visualizations/datatable/components/table_basic.test.tsx +++ b/x-pack/plugins/lens/public/visualizations/datatable/components/table_basic.test.tsx @@ -201,6 +201,7 @@ describe('DatatableComponent', () => { uiSettings={{ get: jest.fn() } as unknown as IUiSettingsClient} interactive renderComplete={renderComplete} + columnFilterable={[true, true, true]} /> ); @@ -241,6 +242,7 @@ describe('DatatableComponent', () => { uiSettings={{ get: jest.fn() } as unknown as IUiSettingsClient} interactive renderComplete={renderComplete} + columnFilterable={[true, true, true]} /> ); @@ -316,6 +318,7 @@ describe('DatatableComponent', () => { uiSettings={{ get: jest.fn() } as unknown as IUiSettingsClient} interactive renderComplete={renderComplete} + columnFilterable={[true, true, true]} /> ); @@ -356,6 +359,7 @@ describe('DatatableComponent', () => { uiSettings={{ get: jest.fn() } as unknown as IUiSettingsClient} interactive={false} renderComplete={renderComplete} + columnFilterable={[true, true, true]} /> ); diff --git a/x-pack/plugins/lens/public/visualizations/datatable/components/table_basic.tsx b/x-pack/plugins/lens/public/visualizations/datatable/components/table_basic.tsx index bbf5eddef879e..4b8f8067e974e 100644 --- a/x-pack/plugins/lens/public/visualizations/datatable/components/table_basic.tsx +++ b/x-pack/plugins/lens/public/visualizations/datatable/components/table_basic.tsx @@ -310,7 +310,8 @@ export const DatatableComponent = (props: DatatableRenderProps) => { alignments, headerRowHeight, headerRowLines, - dataGridRef.current?.closeCellPopover + dataGridRef.current?.closeCellPopover, + props.columnFilterable ), [ bucketColumns, @@ -326,6 +327,7 @@ export const DatatableComponent = (props: DatatableRenderProps) => { alignments, headerRowHeight, headerRowLines, + props.columnFilterable, ] ); diff --git a/x-pack/plugins/lens/public/visualizations/datatable/components/types.ts b/x-pack/plugins/lens/public/visualizations/datatable/components/types.ts index 96a1e3caf56ce..ec2b687690dd9 100644 --- a/x-pack/plugins/lens/public/visualizations/datatable/components/types.ts +++ b/x-pack/plugins/lens/public/visualizations/datatable/components/types.ts @@ -58,6 +58,7 @@ export type DatatableRenderProps = DatatableProps & { * ROW_CLICK_TRIGGER actions attached to it, otherwise false. */ rowHasRowClickTriggerActions?: boolean[]; + columnFilterable?: boolean[]; }; export interface DataContextType { diff --git a/x-pack/plugins/lens/public/visualizations/datatable/expression.tsx b/x-pack/plugins/lens/public/visualizations/datatable/expression.tsx index da7fbceee5b23..32fb293647620 100644 --- a/x-pack/plugins/lens/public/visualizations/datatable/expression.tsx +++ b/x-pack/plugins/lens/public/visualizations/datatable/expression.tsx @@ -12,7 +12,11 @@ import { I18nProvider } from '@kbn/i18n-react'; import type { PaletteRegistry } from '@kbn/coloring'; import type { IAggType } from '@kbn/data-plugin/public'; import { IUiSettingsClient, ThemeServiceStart } from '@kbn/core/public'; -import type { ExpressionRenderDefinition } from '@kbn/expressions-plugin/common'; +import type { + Datatable, + ExpressionRenderDefinition, + IInterpreterRenderHandlers, +} from '@kbn/expressions-plugin/common'; import { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public'; import { trackUiCounterEvents } from '../../lens_ui_telemetry'; import { DatatableComponent } from './components/table_basic'; @@ -21,6 +25,30 @@ import type { ILensInterpreterRenderHandlers } from '../../types'; import type { FormatFactory } from '../../../common'; import type { DatatableProps } from '../../../common/expressions'; +async function columnsFilterable(table: Datatable, handlers: IInterpreterRenderHandlers) { + if (!table.rows.length) { + return; + } + return Promise.all( + table.columns.map(async (column, colIndex) => { + return Boolean( + await handlers.hasCompatibleActions?.({ + name: 'filter', + data: { + data: [ + { + table, + column: colIndex, + row: 0, + }, + ], + }, + }) + ); + }) + ); +} + export const getDatatableRenderer = (dependencies: { formatFactory: FormatFactory; getType: Promise<(name: string) => IAggType>; @@ -87,6 +115,7 @@ export const getDatatableRenderer = (dependencies: { paletteService={dependencies.paletteService} getType={resolvedGetType} rowHasRowClickTriggerActions={rowHasRowClickTriggerActions} + columnFilterable={await columnsFilterable(config.data, handlers)} interactive={isInteractive()} uiSettings={dependencies.uiSettings} renderComplete={renderComplete} diff --git a/x-pack/plugins/lens/public/visualizations/datatable/visualization.tsx b/x-pack/plugins/lens/public/visualizations/datatable/visualization.tsx index ad5e8118c5226..60de4d4d1148c 100644 --- a/x-pack/plugins/lens/public/visualizations/datatable/visualization.tsx +++ b/x-pack/plugins/lens/public/visualizations/datatable/visualization.tsx @@ -16,6 +16,7 @@ import { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public'; import { VIS_EVENT_TO_TRIGGER } from '@kbn/visualizations-plugin/public'; import { IconChartDatatable } from '@kbn/chart-icons'; import { LayerTypes } from '@kbn/expression-xy-plugin/public'; +import type { FormBasedPersistedState } from '../../datasources/form_based/types'; import type { SuggestionRequest, Visualization, @@ -29,7 +30,6 @@ import type { LayerType } from '../../../common'; import { getDefaultSummaryLabel } from '../../../common/expressions/datatable/summary'; import type { ColumnState, SortingState, PagingState } from '../../../common/expressions'; import { DataTableToolbar } from './components/toolbar'; -import type { IndexPatternLayer } from '../../indexpattern_datasource/types'; export interface DatatableVisualizationState { columns: ColumnState[]; @@ -43,16 +43,6 @@ export interface DatatableVisualizationState { paging?: PagingState; } -interface DatatableDatasourceState { - [prop: string]: unknown; - layers: IndexPatternLayer[]; -} - -export interface DatatableSuggestion extends Suggestion { - datasourceState: DatatableDatasourceState; - visualizationState: DatatableVisualizationState; -} - const visualizationLabel = i18n.translate('xpack.lens.datatable.label', { defaultMessage: 'Table', }); @@ -605,15 +595,17 @@ export const getDatatableVisualization = ({ } }, getSuggestionFromConvertToLensContext({ suggestions, context }) { - const allSuggestions = suggestions as DatatableSuggestion[]; - return { + const allSuggestions = suggestions as Array< + Suggestion + >; + const suggestion: Suggestion = { ...allSuggestions[0], datasourceState: { ...allSuggestions[0].datasourceState, layers: allSuggestions.reduce( (acc, s) => ({ ...acc, - ...s.datasourceState.layers, + ...s.datasourceState?.layers, }), {} ), @@ -623,6 +615,7 @@ export const getDatatableVisualization = ({ ...context.configuration, }, }; + return suggestion; }, }); diff --git a/x-pack/plugins/lens/public/visualizations/gauge/suggestions.ts b/x-pack/plugins/lens/public/visualizations/gauge/suggestions.ts index e90aa5e7d0895..424accee1572c 100644 --- a/x-pack/plugins/lens/public/visualizations/gauge/suggestions.ts +++ b/x-pack/plugins/lens/public/visualizations/gauge/suggestions.ts @@ -41,7 +41,7 @@ export const getSuggestions: Visualization['getSuggesti if ( hasLayerMismatch(keptLayerIds, table) || isNotNumericMetric(table) || - (!isGauge && table.columns.length > 1) || + (state && !isGauge && table.columns.length > 1) || (isGauge && (numberOfAccessors !== table.columns.length || table.changeType === 'initial')) ) { return []; diff --git a/x-pack/plugins/lens/public/visualizations/gauge/visualization.tsx b/x-pack/plugins/lens/public/visualizations/gauge/visualization.tsx index 4ea17a2136aa7..803e4e30acb59 100644 --- a/x-pack/plugins/lens/public/visualizations/gauge/visualization.tsx +++ b/x-pack/plugins/lens/public/visualizations/gauge/visualization.tsx @@ -24,7 +24,8 @@ import { } from '@kbn/expression-gauge-plugin/public'; import { IconChartHorizontalBullet, IconChartVerticalBullet } from '@kbn/chart-icons'; import { LayerTypes } from '@kbn/expression-xy-plugin/public'; -import type { DatasourceLayers, OperationMetadata, Visualization } from '../../types'; +import type { FormBasedPersistedState } from '../../datasources/form_based/types'; +import type { DatasourceLayers, OperationMetadata, Suggestion, Visualization } from '../../types'; import { getSuggestions } from './suggestions'; import { GROUP_ID, @@ -543,4 +544,28 @@ export const getGaugeVisualization = ({ return warnings; }, + + getSuggestionFromConvertToLensContext({ suggestions, context }) { + const allSuggestions = suggestions as Array< + Suggestion + >; + const suggestion: Suggestion = { + ...allSuggestions[0], + datasourceState: { + ...allSuggestions[0].datasourceState, + layers: allSuggestions.reduce( + (acc, s) => ({ + ...acc, + ...s.datasourceState?.layers, + }), + {} + ), + }, + visualizationState: { + ...allSuggestions[0].visualizationState, + ...(context.configuration as GaugeVisualizationState), + }, + }; + return suggestion; + }, }); diff --git a/x-pack/plugins/lens/public/visualizations/metric/visualization.tsx b/x-pack/plugins/lens/public/visualizations/metric/visualization.tsx index e3b42fedc45e4..776944bbdd62c 100644 --- a/x-pack/plugins/lens/public/visualizations/metric/visualization.tsx +++ b/x-pack/plugins/lens/public/visualizations/metric/visualization.tsx @@ -19,6 +19,7 @@ import { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public'; import { IconChartMetric } from '@kbn/chart-icons'; import { LayerTypes } from '@kbn/expression-xy-plugin/public'; import type { LayerType } from '../../../common'; +import type { FormBasedPersistedState } from '../../datasources/form_based/types'; import { getSuggestions } from './suggestions'; import { Visualization, @@ -31,8 +32,7 @@ import { GROUP_ID, LENS_METRIC_ID } from './constants'; import { DimensionEditor } from './dimension_editor'; import { Toolbar } from './toolbar'; import { generateId } from '../../id_generator'; -import { FormatSelectorOptions } from '../../indexpattern_datasource/dimension_panel/format_selector'; -import { IndexPatternLayer } from '../../indexpattern_datasource/types'; +import { FormatSelectorOptions } from '../../datasources/form_based/dimension_panel/format_selector'; export const DEFAULT_MAX_COLUMNS = 3; @@ -57,16 +57,6 @@ export interface MetricVisualizationState { maxCols?: number; } -interface MetricDatasourceState { - [prop: string]: unknown; - layers: IndexPatternLayer[]; -} - -export interface MetricSuggestion extends Suggestion { - datasourceState: MetricDatasourceState; - visualizationState: MetricVisualizationState; -} - export const supportedDataTypes = new Set(['number']); // TODO - deduplicate with gauges? @@ -503,15 +493,17 @@ export const getMetricVisualization = ({ }, getSuggestionFromConvertToLensContext({ suggestions, context }) { - const allSuggestions = suggestions as MetricSuggestion[]; - return { + const allSuggestions = suggestions as Array< + Suggestion + >; + const suggestion: Suggestion = { ...allSuggestions[0], datasourceState: { ...allSuggestions[0].datasourceState, layers: allSuggestions.reduce( (acc, s) => ({ ...acc, - ...s.datasourceState.layers, + ...s.datasourceState?.layers, }), {} ), @@ -521,5 +513,6 @@ export const getMetricVisualization = ({ ...context.configuration, }, }; + return suggestion; }, }); diff --git a/x-pack/plugins/lens/public/visualizations/partition/suggestions.ts b/x-pack/plugins/lens/public/visualizations/partition/suggestions.ts index 25742f7cab033..961b6a68e745c 100644 --- a/x-pack/plugins/lens/public/visualizations/partition/suggestions.ts +++ b/x-pack/plugins/lens/public/visualizations/partition/suggestions.ts @@ -284,6 +284,7 @@ export function suggestions({ ...state.layers[0], layerId: table.layerId, primaryGroups: groups.map((col) => col.columnId), + secondaryGroups: [], metric: metricColumnId, categoryDisplay: CategoryDisplay.DEFAULT, layerType: LayerTypes.DATA, diff --git a/x-pack/plugins/lens/public/visualizations/partition/visualization.tsx b/x-pack/plugins/lens/public/visualizations/partition/visualization.tsx index 49a485debcf27..6bff536794e89 100644 --- a/x-pack/plugins/lens/public/visualizations/partition/visualization.tsx +++ b/x-pack/plugins/lens/public/visualizations/partition/visualization.tsx @@ -16,6 +16,7 @@ import { VIS_EVENT_TO_TRIGGER } from '@kbn/visualizations-plugin/public'; import { EuiSpacer } from '@elastic/eui'; import { PartitionVisConfiguration } from '@kbn/visualizations-plugin/common/convert_to_lens'; import { LayerTypes } from '@kbn/expression-xy-plugin/public'; +import type { FormBasedPersistedState } from '../../datasources/form_based/types'; import type { Visualization, OperationMetadata, @@ -37,17 +38,6 @@ import { suggestions } from './suggestions'; import { PartitionChartsMeta } from './partition_charts_meta'; import { DimensionEditor, PieToolbar } from './toolbar'; import { checkTableForContainsSmallValues } from './render_helpers'; -import type { IndexPatternLayer } from '../..'; - -interface DatatableDatasourceState { - [prop: string]: unknown; - layers: IndexPatternLayer[]; -} - -export interface PartitionSuggestion extends Suggestion { - datasourceState: DatatableDatasourceState; - visualizationState: PieVisualizationState; -} function newLayerState(layerId: string): PieLayerState { return { @@ -201,6 +191,7 @@ export const getPieVisualization = ({ supportsMoreColumns: totalNonCollapsedAccessors < PartitionChartsMeta.pie.maxBuckets, dimensionsTooMany: totalNonCollapsedAccessors - PartitionChartsMeta.pie.maxBuckets, dataTestSubj: 'lnsPie_sliceByDimensionPanel', + hideGrouping: true, }; case 'mosaic': return { @@ -229,6 +220,7 @@ export const getPieVisualization = ({ dimensionsTooMany: totalNonCollapsedAccessors - PartitionChartsMeta[state.shape].maxBuckets, dataTestSubj: 'lnsPie_groupByDimensionPanel', + hideGrouping: state.shape === 'treemap', }; } }; @@ -457,19 +449,20 @@ export const getPieVisualization = ({ if (!props.suggestions.length) { return; } - const suggestionByShape = (props.suggestions as PartitionSuggestion[]).find( - (suggestion) => suggestion.visualizationState.shape === context.configuration.shape - ); + const suggestionByShape = ( + props.suggestions as Array> + ).find((suggestion) => suggestion.visualizationState.shape === context.configuration.shape); if (!suggestionByShape) { return; } - return { + const suggestion: Suggestion = { ...suggestionByShape, visualizationState: { ...suggestionByShape.visualizationState, ...context.configuration, }, }; + return suggestion; }, getErrorMessages(state) { diff --git a/x-pack/plugins/lens/public/visualizations/xy/types.ts b/x-pack/plugins/lens/public/visualizations/xy/types.ts index 6a953ad452fc3..465c81ca2e3e5 100644 --- a/x-pack/plugins/lens/public/visualizations/xy/types.ts +++ b/x-pack/plugins/lens/public/visualizations/xy/types.ts @@ -36,7 +36,7 @@ import { } from '@kbn/chart-icons'; import { DistributiveOmit } from '@elastic/eui'; -import type { VisualizationType, Suggestion } from '../../types'; +import type { VisualizationType } from '../../types'; import type { ValueLabelConfig } from '../../../common/types'; export const YAxisModes = { @@ -274,12 +274,3 @@ export const visualizationTypes: VisualizationType[] = [ sortPriority: 2, }, ]; - -interface XYStateWithLayers { - [prop: string]: unknown; - layers: XYLayerConfig[]; -} -export interface XYSuggestion extends Suggestion { - datasourceState: XYStateWithLayers; - visualizationState: XYStateWithLayers; -} diff --git a/x-pack/plugins/lens/public/visualizations/xy/visualization.test.ts b/x-pack/plugins/lens/public/visualizations/xy/visualization.test.ts index 6c2d61d7bb869..8c6da8bf95a6b 100644 --- a/x-pack/plugins/lens/public/visualizations/xy/visualization.test.ts +++ b/x-pack/plugins/lens/public/visualizations/xy/visualization.test.ts @@ -28,7 +28,7 @@ import { EventAnnotationConfig } from '@kbn/event-annotation-plugin/common'; import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; import { IStorageWrapper } from '@kbn/kibana-utils-plugin/public'; import { DataViewsState } from '../../state_management'; -import { createMockedIndexPattern } from '../../indexpattern_datasource/mocks'; +import { createMockedIndexPattern } from '../../datasources/form_based/mocks'; import { createMockDataViewsState } from '../../data_views_service/mocks'; import { unifiedSearchPluginMock } from '@kbn/unified-search-plugin/public/mocks'; diff --git a/x-pack/plugins/lens/public/visualizations/xy/visualization.tsx b/x-pack/plugins/lens/public/visualizations/xy/visualization.tsx index 583f0f431610e..0b482b92be9ee 100644 --- a/x-pack/plugins/lens/public/visualizations/xy/visualization.tsx +++ b/x-pack/plugins/lens/public/visualizations/xy/visualization.tsx @@ -31,13 +31,13 @@ import { getSuggestions } from './xy_suggestions'; import { XyToolbar } from './xy_config_panel'; import { DimensionEditor } from './xy_config_panel/dimension_editor'; import { LayerHeader, LayerHeaderContent } from './xy_config_panel/layer_header'; -import type { Visualization, AccessorConfig, FramePublicAPI } from '../../types'; +import type { Visualization, AccessorConfig, FramePublicAPI, Suggestion } from '../../types'; +import type { FormBasedPersistedState } from '../../datasources/form_based/types'; import { type State, type XYLayerConfig, type XYDataLayerConfig, type SeriesType, - type XYSuggestion, type PersistedState, visualizationTypes, } from './types'; @@ -809,24 +809,25 @@ export const getXyVisualization = ({ }, getSuggestionFromConvertToLensContext({ suggestions, context }) { - const allSuggestions = suggestions as XYSuggestion[]; - return { + const allSuggestions = suggestions as Array>; + const suggestion: Suggestion = { ...allSuggestions[0], datasourceState: { ...allSuggestions[0].datasourceState, layers: allSuggestions.reduce( (acc, s) => ({ ...acc, - ...s.datasourceState.layers, + ...s.datasourceState?.layers, }), {} ), }, visualizationState: { ...allSuggestions[0].visualizationState, - ...context.configuration, + ...(context.configuration as XYState), }, }; + return suggestion; }, }); diff --git a/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/annotations_config_panel/index.test.tsx b/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/annotations_config_panel/index.test.tsx index 7d581d50d0859..185a73c64d4e6 100644 --- a/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/annotations_config_panel/index.test.tsx +++ b/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/annotations_config_panel/index.test.tsx @@ -18,7 +18,7 @@ import { chartPluginMock } from '@kbn/charts-plugin/public/mocks'; import moment from 'moment'; import { EventAnnotationConfig } from '@kbn/event-annotation-plugin/common'; import { createMockDataViewsState } from '../../../../data_views_service/mocks'; -import { createMockedIndexPattern } from '../../../../indexpattern_datasource/mocks'; +import { createMockedIndexPattern } from '../../../../datasources/form_based/mocks'; import { act } from 'react-dom/test-utils'; import { EuiButtonGroup } from '@elastic/eui'; diff --git a/x-pack/plugins/lens/readme.md b/x-pack/plugins/lens/readme.md index d8b80e864be58..d276a45eb00ac 100644 --- a/x-pack/plugins/lens/readme.md +++ b/x-pack/plugins/lens/readme.md @@ -82,7 +82,7 @@ References (`references`) are regular saved object references forming a graph of ### Datasource state -The data source state (`state.datasourceStates.indexPattern.layers`) contains the configuration state of the data fetching and processing part of Lens. It's not specific to a certain representation (xy, pie, gauge, ...), but instead it defines a data table per layer made out of columns with various properties. This data table is passed over to the visualization state which maps it to various dimensions of the specific visualization. Layer and columns have unique ids which are shared amongst visualization and datasource - it's important to make sure they are always in sync. The keys of the `state.datasourceStates.indexPattern.layers` object are the layer ids. Lens editor chooses uuids for these, but when programmatically generating Lens attributes, any string can be used for them. The `layers[].columns` object is constructed in a similar way (keys represent the column ids). The `operationType` property defines the type of the column, other properties depend on the specific operation. Types for individual parts of the datasource state are provided (check the `lens/public` export, e.g. there's the `MaxIndexPatternColumn` for a column of operation type `max`) +The data source state (`state.datasourceStates.formBased.layers`) contains the configuration state of the data fetching and processing part of Lens. It's not specific to a certain representation (xy, pie, gauge, ...), but instead it defines a data table per layer made out of columns with various properties. This data table is passed over to the visualization state which maps it to various dimensions of the specific visualization. Layer and columns have unique ids which are shared amongst visualization and datasource - it's important to make sure they are always in sync. The keys of the `state.datasourceStates.formBased.layers` object are the layer ids. Lens editor chooses uuids for these, but when programmatically generating Lens attributes, any string can be used for them. The `layers[].columns` object is constructed in a similar way (keys represent the column ids). The `operationType` property defines the type of the column, other properties depend on the specific operation. Types for individual parts of the datasource state are provided (check the `lens/public` export, e.g. there's the `MaxIndexPatternColumn` for a column of operation type `max`) ### Visualization state diff --git a/x-pack/plugins/lens/server/embeddable/make_lens_embeddable_factory.ts b/x-pack/plugins/lens/server/embeddable/make_lens_embeddable_factory.ts index 8b977fbce5742..42846e84377dd 100644 --- a/x-pack/plugins/lens/server/embeddable/make_lens_embeddable_factory.ts +++ b/x-pack/plugins/lens/server/embeddable/make_lens_embeddable_factory.ts @@ -7,6 +7,7 @@ import { EmbeddableRegistryDefinition } from '@kbn/embeddable-plugin/server'; import type { SerializableRecord } from '@kbn/utility-types'; +import type { SavedObject } from '@kbn/core-saved-objects-common'; import { mergeMigrationFunctionMaps, MigrateFunctionsObject, @@ -31,6 +32,7 @@ import { getLensDataViewMigrations, commonMigrateMetricIds, commonMigratePartitionChartGroups, + commonMigrateIndexPatternDatasource, } from '../migrations/common_migrations'; import { CustomVisualizationMigrations, @@ -155,6 +157,15 @@ export const makeLensEmbeddableFactory = attributes: migratedLensState, } as unknown as SerializableRecord; }, + '8.6.0': (state) => { + const lensState = state as unknown as SavedObject>; + + const migratedLensState = commonMigrateIndexPatternDatasource(lensState.attributes); + return { + ...lensState, + attributes: migratedLensState, + } as unknown as SerializableRecord; + }, }), getLensCustomVisualizationMigrations(customVisualizationMigrations) ), diff --git a/x-pack/plugins/lens/server/migrations/common_migrations.ts b/x-pack/plugins/lens/server/migrations/common_migrations.ts index 4afe60729920f..b56f4b691911b 100644 --- a/x-pack/plugins/lens/server/migrations/common_migrations.ts +++ b/x-pack/plugins/lens/server/migrations/common_migrations.ts @@ -34,6 +34,7 @@ import { XYVisStatePre850, VisState850, LensDocShape850, + LensDocShape860, } from './types'; import { DOCUMENT_FIELD_NAME, LegacyMetricState } from '../../common'; import { isPartitionShape } from '../../common/visualizations'; @@ -477,6 +478,22 @@ export const commonMigrateMetricIds = ( return newAttributes; }; +export const commonMigrateIndexPatternDatasource = ( + attributes: LensDocShape850 +): LensDocShape860 => { + const newAttrs = { + ...attributes, + state: { + ...attributes.state, + datasourceStates: { + formBased: attributes.state.datasourceStates.indexpattern, + }, + }, + }; + + return newAttrs; +}; + export const commonMigratePartitionChartGroups = ( attributes: LensDocShape850<{ shape: string; diff --git a/x-pack/plugins/lens/server/migrations/saved_object_migrations.test.ts b/x-pack/plugins/lens/server/migrations/saved_object_migrations.test.ts index fcb1e2a5722f1..54504b9201f67 100644 --- a/x-pack/plugins/lens/server/migrations/saved_object_migrations.test.ts +++ b/x-pack/plugins/lens/server/migrations/saved_object_migrations.test.ts @@ -2363,4 +2363,100 @@ describe('Lens migrations', () => { expect(result.attributes.visualizationType).toBe('lnsMetric'); }); }); + + describe('8.6.0 migrates indexpattern datasource', () => { + const context = { log: { warn: () => {} } } as unknown as SavedObjectMigrationContext; + const example = { + type: 'lens', + id: 'mock-saved-object-id', + attributes: { + state: { + datasourceMetaData: { + filterableIndexPatterns: [ + { + id: 'logstash-*', + title: 'logstash-*', + }, + ], + }, + datasourceStates: { + indexpattern: { + currentIndexPatternId: 'logstash-*', + layers: { + 'c61a8afb-a185-4fae-a064-fb3846f6c451': { + columnOrder: ['2cd09808-3915-49f4-b3b0-82767eba23f7'], + columns: { + '2cd09808-3915-49f4-b3b0-82767eba23f7': { + dataType: 'number', + isBucketed: false, + label: 'Maximum of bytes', + operationType: 'max', + scale: 'ratio', + sourceField: 'bytes', + }, + 'd3e62a7a-c259-4fff-a2fc-eebf20b7008a': { + dataType: 'number', + isBucketed: false, + label: 'Minimum of bytes', + operationType: 'min', + scale: 'ratio', + sourceField: 'bytes', + }, + 'd6e40cea-6299-43b4-9c9d-b4ee305a2ce8': { + dataType: 'date', + isBucketed: true, + label: 'Date Histogram of @timestamp', + operationType: 'date_histogram', + params: { + interval: 'auto', + }, + scale: 'interval', + sourceField: '@timestamp', + }, + }, + indexPatternId: 'logstash-*', + }, + }, + }, + }, + filters: [], + query: { + language: 'kuery', + query: '', + }, + visualization: { + accessor: '2cd09808-3915-49f4-b3b0-82767eba23f7', + isHorizontal: false, + layerId: 'c61a8afb-a185-4fae-a064-fb3846f6c451', + layers: [ + { + accessors: [ + 'd3e62a7a-c259-4fff-a2fc-eebf20b7008a', + '26ef70a9-c837-444c-886e-6bd905ee7335', + ], + layerId: 'c61a8afb-a185-4fae-a064-fb3846f6c451', + seriesType: 'area', + splitAccessor: '54cd64ed-2a44-4591-af84-b2624504569a', + xAccessor: 'd6e40cea-6299-43b4-9c9d-b4ee305a2ce8', + }, + ], + legend: { + isVisible: true, + position: 'right', + }, + preferredSeriesType: 'area', + }, + }, + title: 'Artistpreviouslyknownaslens', + visualizationType: 'lnsXY', + }, + }; + + it('migrates the indexpattern datasource to formBased', () => { + const result = migrations['8.6.0'](example, context); + expect(result.attributes.state.datasourceStates.formBased).toBe( + example.attributes.state.datasourceStates.indexpattern + ); + }); + }); }); diff --git a/x-pack/plugins/lens/server/migrations/saved_object_migrations.ts b/x-pack/plugins/lens/server/migrations/saved_object_migrations.ts index 2f02ca358fcc0..8e4914b94fe83 100644 --- a/x-pack/plugins/lens/server/migrations/saved_object_migrations.ts +++ b/x-pack/plugins/lens/server/migrations/saved_object_migrations.ts @@ -38,6 +38,7 @@ import { LensDocShape850, LensDocShape840, VisState850, + LensDocShape860, } from './types'; import { commonRenameOperationsForFormula, @@ -59,6 +60,7 @@ import { getLensDataViewMigrations, commonMigrateMetricIds, commonMigratePartitionChartGroups, + commonMigrateIndexPatternDatasource, } from './common_migrations'; interface LensDocShapePre710 { @@ -533,6 +535,13 @@ const migrateMetricIds: SavedObjectMigrationFn attributes: commonMigrateMetricIds(doc.attributes), }); +const migrateIndexPatternDatasource: SavedObjectMigrationFn = ( + doc +) => ({ + ...doc, + attributes: commonMigrateIndexPatternDatasource(doc.attributes), +}); + const migratePartitionChartGroups: SavedObjectMigrationFn = ( doc ) => ({ @@ -566,6 +575,7 @@ const lensMigrations: SavedObjectMigrationMap = { ), '8.3.0': flow(lockOldMetricVisSettings, preserveOldLegendSizeDefault, fixValueLabelsInXY), '8.5.0': flow(migrateMetricIds, enrichAnnotationLayers, migratePartitionChartGroups), + '8.6.0': flow(migrateIndexPatternDatasource), }; export const getAllMigrations = ( diff --git a/x-pack/plugins/lens/server/migrations/types.ts b/x-pack/plugins/lens/server/migrations/types.ts index 87c993a712e01..061ba113f734a 100644 --- a/x-pack/plugins/lens/server/migrations/types.ts +++ b/x-pack/plugins/lens/server/migrations/types.ts @@ -303,3 +303,24 @@ export type VisState840 = VisState830; export type LensDocShape840 = LensDocShape830; export type LensDocShape850 = LensDocShape840; + +export type LensDocShape860 = Omit< + LensDocShape850, + 'state' +> & { + state: Omit['state'], 'datasourceStates'> & { + datasourceStates: { + // This is hardcoded as our only datasource + formBased: { + currentIndexPatternId: string; + layers: Record< + string, + { + columnOrder: string[]; + columns: Record>; + } + >; + }; + }; + }; +}; diff --git a/x-pack/plugins/licensing/common/license_update.ts b/x-pack/plugins/licensing/common/license_update.ts index b674f4a066ce3..b344d8ce2d16a 100644 --- a/x-pack/plugins/licensing/common/license_update.ts +++ b/x-pack/plugins/licensing/common/license_update.ts @@ -39,11 +39,11 @@ export function createLicenseUpdate( const startWithArgs = initialValues ? [undefined, initialValues] : [undefined]; const license$: Observable = fetched$.pipe( - shareReplay(1), startWith(...startWithArgs), pairwise(), filter(([previous, next]) => hasLicenseInfoChanged(previous, next!)), - map(([, next]) => next!) + map(([, next]) => next!), + shareReplay(1) ); // start periodic license fetch right away diff --git a/x-pack/plugins/maps/common/constants.ts b/x-pack/plugins/maps/common/constants.ts index 96318890a2d94..94ae72a050e21 100644 --- a/x-pack/plugins/maps/common/constants.ts +++ b/x-pack/plugins/maps/common/constants.ts @@ -53,6 +53,7 @@ export enum LAYER_TYPE { HEATMAP = 'HEATMAP', BLENDED_VECTOR = 'BLENDED_VECTOR', MVT_VECTOR = 'MVT_VECTOR', + LAYER_GROUP = 'LAYER_GROUP', } export enum SOURCE_TYPES { diff --git a/x-pack/plugins/maps/common/descriptor_types/layer_descriptor_types.ts b/x-pack/plugins/maps/common/descriptor_types/layer_descriptor_types.ts index 160a34f8bcc0d..a547ef9c6d93a 100644 --- a/x-pack/plugins/maps/common/descriptor_types/layer_descriptor_types.ts +++ b/x-pack/plugins/maps/common/descriptor_types/layer_descriptor_types.ts @@ -71,6 +71,7 @@ export type LayerDescriptor = { style?: StyleDescriptor | null; query?: Query; includeInFitToBounds?: boolean; + parent?: string; }; export type VectorLayerDescriptor = LayerDescriptor & { @@ -89,3 +90,10 @@ export type EMSVectorTileLayerDescriptor = LayerDescriptor & { type: LAYER_TYPE.EMS_VECTOR_TILE; style: EMSVectorTileStyleDescriptor; }; + +export type LayerGroupDescriptor = LayerDescriptor & { + type: LAYER_TYPE.LAYER_GROUP; + label: string; + sourceDescriptor: null; + visible: boolean; +}; diff --git a/x-pack/plugins/maps/public/actions/data_request_actions.ts b/x-pack/plugins/maps/public/actions/data_request_actions.ts index b5ce42ebefc09..5e27b488065ab 100644 --- a/x-pack/plugins/maps/public/actions/data_request_actions.ts +++ b/x-pack/plugins/maps/public/actions/data_request_actions.ts @@ -9,9 +9,7 @@ import { AnyAction, Dispatch } from 'redux'; import { ThunkDispatch } from 'redux-thunk'; -import bbox from '@turf/bbox'; import uuid from 'uuid/v4'; -import { multiPoint } from '@turf/helpers'; import { FeatureCollection } from 'geojson'; import { Adapters } from '@kbn/inspector-plugin/common/adapters'; import { MapStoreState } from '../reducers/store'; @@ -49,7 +47,9 @@ import { ILayer } from '../classes/layers/layer'; import { IVectorLayer } from '../classes/layers/vector_layer'; import { DataRequestMeta, MapExtent, DataFilters } from '../../common/descriptor_types'; import { DataRequestAbortError } from '../classes/util/data_request'; -import { scaleBounds, turfBboxToBounds } from '../../common/elasticsearch_util'; +import { scaleBounds } from '../../common/elasticsearch_util'; +import { getLayersExtent } from './get_layers_extent'; +import { isLayerGroup } from '../classes/layers/layer_group'; const FIT_TO_BOUNDS_SCALE_FACTOR = 0.1; @@ -101,7 +101,7 @@ export function cancelAllInFlightRequests() { export function updateStyleMeta(layerId: string | null) { return async (dispatch: Dispatch, getState: () => MapStoreState) => { const layer = getLayerById(layerId, getState()); - if (!layer) { + if (!layer || isLayerGroup(layer)) { return; } @@ -378,8 +378,8 @@ export function fitToLayerExtent(layerId: string) { if (targetLayer) { try { - const bounds = await targetLayer.getBounds( - getDataRequestContext(dispatch, getState, layerId, false, false) + const bounds = await targetLayer.getBounds((boundsLayerId) => + getDataRequestContext(dispatch, getState, boundsLayerId, false, false) ); if (bounds) { await dispatch(setGotoWithBounds(scaleBounds(bounds, FIT_TO_BOUNDS_SCALE_FACTOR))); @@ -401,65 +401,22 @@ export function fitToLayerExtent(layerId: string) { export function fitToDataBounds(onNoBounds?: () => void) { return async (dispatch: Dispatch, getState: () => MapStoreState) => { - const layerList = getLayerList(getState()); - - if (!layerList.length) { - return; - } - - const boundsPromises = layerList.map(async (layer: ILayer) => { - if (!(await layer.isFittable())) { - return null; - } - return layer.getBounds( - getDataRequestContext(dispatch, getState, layer.getId(), false, false) - ); + const rootLayers = getLayerList(getState()).filter((layer) => { + return layer.getParent() === undefined; }); - let bounds; - try { - bounds = await Promise.all(boundsPromises); - } catch (error) { - if (!(error instanceof DataRequestAbortError)) { - // eslint-disable-next-line no-console - console.warn( - 'Unhandled getBounds error for layer. Only DataRequestAbortError should be surfaced', - error - ); - } - // new fitToDataBounds request has superseded this thread of execution. Results no longer needed. - return; - } - - const corners = []; - for (let i = 0; i < bounds.length; i++) { - const b = bounds[i]; - - // filter out undefined bounds (uses Infinity due to turf responses) - if ( - b === null || - b.minLon === Infinity || - b.maxLon === Infinity || - b.minLat === -Infinity || - b.maxLat === -Infinity - ) { - continue; - } - - corners.push([b.minLon, b.minLat]); - corners.push([b.maxLon, b.maxLat]); - } + const extent = await getLayersExtent(rootLayers, (boundsLayerId) => + getDataRequestContext(dispatch, getState, boundsLayerId, false, false) + ); - if (!corners.length) { + if (extent === null) { if (onNoBounds) { onNoBounds(); } return; } - const dataBounds = turfBboxToBounds(bbox(multiPoint(corners))); - - dispatch(setGotoWithBounds(scaleBounds(dataBounds, FIT_TO_BOUNDS_SCALE_FACTOR))); + dispatch(setGotoWithBounds(scaleBounds(extent, FIT_TO_BOUNDS_SCALE_FACTOR))); }; } diff --git a/x-pack/plugins/maps/public/actions/get_layers_extent.tsx b/x-pack/plugins/maps/public/actions/get_layers_extent.tsx new file mode 100644 index 0000000000000..81d8367bd2803 --- /dev/null +++ b/x-pack/plugins/maps/public/actions/get_layers_extent.tsx @@ -0,0 +1,66 @@ +/* + * 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 bbox from '@turf/bbox'; +import { multiPoint } from '@turf/helpers'; +import { MapExtent } from '../../common/descriptor_types'; +import { turfBboxToBounds } from '../../common/elasticsearch_util'; +import { ILayer } from '../classes/layers/layer'; +import type { DataRequestContext } from './data_request_actions'; +import { DataRequestAbortError } from '../classes/util/data_request'; + +export async function getLayersExtent( + layers: ILayer[], + getDataRequestContext: (layerId: string) => DataRequestContext +): Promise { + if (!layers.length) { + return null; + } + + const boundsPromises = layers.map(async (layer: ILayer) => { + if (!(await layer.isFittable())) { + return null; + } + return layer.getBounds(getDataRequestContext); + }); + + let bounds; + try { + bounds = await Promise.all(boundsPromises); + } catch (error) { + if (!(error instanceof DataRequestAbortError)) { + // eslint-disable-next-line no-console + console.warn( + 'Unhandled getBounds error for layer. Only DataRequestAbortError should be surfaced', + error + ); + } + // new fitToDataBounds request has superseded this thread of execution. Results no longer needed. + return null; + } + + const corners = []; + for (let i = 0; i < bounds.length; i++) { + const b = bounds[i]; + + // filter out undefined bounds (uses Infinity due to turf responses) + if ( + b === null || + b.minLon === Infinity || + b.maxLon === Infinity || + b.minLat === -Infinity || + b.maxLat === -Infinity + ) { + continue; + } + + corners.push([b.minLon, b.minLat]); + corners.push([b.maxLon, b.maxLat]); + } + + return corners.length ? turfBboxToBounds(bbox(multiPoint(corners))) : null; +} diff --git a/x-pack/plugins/maps/public/actions/index.ts b/x-pack/plugins/maps/public/actions/index.ts index 96db1cebe7d39..235f8d141411e 100644 --- a/x-pack/plugins/maps/public/actions/index.ts +++ b/x-pack/plugins/maps/public/actions/index.ts @@ -24,3 +24,4 @@ export { openOnHoverTooltip, updateOpenTooltips, } from './tooltip_actions'; +export { getLayersExtent } from './get_layers_extent'; diff --git a/x-pack/plugins/maps/public/actions/layer_actions.ts b/x-pack/plugins/maps/public/actions/layer_actions.ts index 317f6e09053e5..5ba9edaee58d0 100644 --- a/x-pack/plugins/maps/public/actions/layer_actions.ts +++ b/x-pack/plugins/maps/public/actions/layer_actions.ts @@ -75,6 +75,7 @@ import { IESAggField } from '../classes/fields/agg'; import { IField } from '../classes/fields/field'; import type { IESSource } from '../classes/sources/es_source'; import { getDrawMode, getOpenTOCDetails } from '../selectors/ui_selectors'; +import { isLayerGroup, LayerGroup } from '../classes/layers/layer_group'; export function trackCurrentLayerState(layerId: string) { return { @@ -160,8 +161,12 @@ export function cloneLayer(layerId: string) { return; } - const clonedDescriptor = await layer.cloneDescriptor(); - dispatch(addLayer(clonedDescriptor)); + (await layer.cloneDescriptor()).forEach((layerDescriptor) => { + dispatch(addLayer(layerDescriptor)); + if (layer.getParent()) { + dispatch(moveLayerToLeftOfTarget(layerDescriptor.id, layerId)); + } + }); }; } @@ -249,12 +254,19 @@ export function setLayerVisibility(layerId: string, makeVisible: boolean) { dispatch: ThunkDispatch, getState: () => MapStoreState ) => { - // if the current-state is invisible, we also want to sync data - // e.g. if a layer was invisible at start-up, it won't have any data loaded const layer = getLayerById(layerId, getState()); + if (!layer) { + return; + } + + if (isLayerGroup(layer)) { + (layer as LayerGroup).getChildren().forEach((childLayer) => { + dispatch(setLayerVisibility(childLayer.getId(), makeVisible)); + }); + } // If the layer visibility is already what we want it to be, do nothing - if (!layer || layer.isVisible() === makeVisible) { + if (layer.isVisible() === makeVisible) { return; } @@ -263,6 +275,9 @@ export function setLayerVisibility(layerId: string, makeVisible: boolean) { layerId, visibility: makeVisible, }); + + // if the current-state is invisible, we also want to sync data + // e.g. if a layer was invisible at start-up, it won't have any data loaded if (makeVisible) { dispatch(syncDataForLayerId(layerId, false)); } @@ -290,7 +305,7 @@ export function hideAllLayers() { getState: () => MapStoreState ) => { getLayerList(getState()).forEach((layer: ILayer, index: number) => { - if (layer.isVisible() && !layer.isBasemap(index)) { + if (!layer.isBasemap(index)) { dispatch(setLayerVisibility(layer.getId(), false)); } }); @@ -303,9 +318,7 @@ export function showAllLayers() { getState: () => MapStoreState ) => { getLayerList(getState()).forEach((layer: ILayer, index: number) => { - if (!layer.isVisible()) { - dispatch(setLayerVisibility(layer.getId(), true)); - } + dispatch(setLayerVisibility(layer.getId(), true)); }); }; } @@ -316,23 +329,20 @@ export function showThisLayerOnly(layerId: string) { getState: () => MapStoreState ) => { getLayerList(getState()).forEach((layer: ILayer, index: number) => { - if (layer.isBasemap(index)) { - return; - } - - // show target layer - if (layer.getId() === layerId) { - if (!layer.isVisible()) { - dispatch(setLayerVisibility(layerId, true)); - } + if (layer.isBasemap(index) || layer.getId() === layerId) { return; } // hide all other layers - if (layer.isVisible()) { - dispatch(setLayerVisibility(layer.getId(), false)); - } + dispatch(setLayerVisibility(layer.getId(), false)); }); + + // show target layer after hiding all other layers + // since hiding layer group will hide its children + const targetLayer = getLayerById(layerId, getState()); + if (targetLayer) { + dispatch(setLayerVisibility(layerId, true)); + } }; } @@ -602,6 +612,15 @@ export function setLayerQuery(id: string, query: Query) { }; } +export function setLayerParent(id: string, parent: string | undefined) { + return { + type: UPDATE_LAYER_PROP, + id, + propName: 'parent', + newValue: parent, + }; +} + export function removeSelectedLayer() { return ( dispatch: ThunkDispatch, @@ -657,6 +676,12 @@ function removeLayerFromLayerList(layerId: string) { if (openTOCDetails.includes(layerId)) { dispatch(hideTOCDetails(layerId)); } + + if (isLayerGroup(layerGettingRemoved)) { + (layerGettingRemoved as LayerGroup).getChildren().forEach((childLayer) => { + dispatch(removeLayerFromLayerList(childLayer.getId())); + }); + } }; } @@ -786,7 +811,7 @@ export function updateMetaFromTiles(layerId: string, mbMetaFeatures: TileMetaFea } function clearInspectorAdapters(layer: ILayer, adapters: Adapters) { - if (!layer.getSource().isESSource()) { + if (isLayerGroup(layer) || !layer.getSource().isESSource()) { return; } @@ -811,3 +836,93 @@ function hasByValueStyling(styleDescriptor: StyleDescriptor) { }) ); } + +export function createLayerGroup(draggedLayerId: string, combineLayerId: string) { + return ( + dispatch: ThunkDispatch, + getState: () => MapStoreState + ) => { + const group = LayerGroup.createDescriptor({}); + const combineLayerDescriptor = getLayerDescriptor(getState(), combineLayerId); + if (combineLayerDescriptor?.parent) { + group.parent = combineLayerDescriptor.parent; + } + dispatch({ + type: ADD_LAYER, + layer: group, + }); + // Move group to left of combine-layer + dispatch(moveLayerToLeftOfTarget(group.id, combineLayerId)); + + dispatch(showTOCDetails(group.id)); + dispatch(setLayerParent(draggedLayerId, group.id)); + dispatch(setLayerParent(combineLayerId, group.id)); + + // Move dragged-layer to left of combine-layer + dispatch(moveLayerToLeftOfTarget(draggedLayerId, combineLayerId)); + }; +} + +export function moveLayerToLeftOfTarget(moveLayerId: string, targetLayerId: string) { + return ( + dispatch: ThunkDispatch, + getState: () => MapStoreState + ) => { + const layers = getLayerList(getState()); + const moveLayerIndex = layers.findIndex((layer) => layer.getId() === moveLayerId); + const targetLayerIndex = layers.findIndex((layer) => layer.getId() === targetLayerId); + if (moveLayerIndex === -1 || targetLayerIndex === -1) { + return; + } + const moveLayer = layers[moveLayerIndex]; + + const newIndex = + moveLayerIndex > targetLayerIndex + ? // When layer is moved to the right, new left sibling index is to the left of destination + targetLayerIndex + 1 + : // When layer is moved to the left, new left sibling index is the destination index + targetLayerIndex; + const newOrder = []; + for (let i = 0; i < layers.length; i++) { + newOrder.push(i); + } + newOrder.splice(moveLayerIndex, 1); + newOrder.splice(newIndex, 0, moveLayerIndex); + dispatch(updateLayerOrder(newOrder)); + + if (isLayerGroup(moveLayer)) { + (moveLayer as LayerGroup).getChildren().forEach((childLayer) => { + dispatch(moveLayerToLeftOfTarget(childLayer.getId(), targetLayerId)); + }); + } + }; +} + +export function moveLayerToBottom(moveLayerId: string) { + return ( + dispatch: ThunkDispatch, + getState: () => MapStoreState + ) => { + const layers = getLayerList(getState()); + const moveLayerIndex = layers.findIndex((layer) => layer.getId() === moveLayerId); + if (moveLayerIndex === -1) { + return; + } + const moveLayer = layers[moveLayerIndex]; + + const newIndex = 0; + const newOrder = []; + for (let i = 0; i < layers.length; i++) { + newOrder.push(i); + } + newOrder.splice(moveLayerIndex, 1); + newOrder.splice(newIndex, 0, moveLayerIndex); + dispatch(updateLayerOrder(newOrder)); + + if (isLayerGroup(moveLayer)) { + (moveLayer as LayerGroup).getChildren().forEach((childLayer) => { + dispatch(moveLayerToBottom(childLayer.getId())); + }); + } + }; +} diff --git a/x-pack/plugins/maps/public/classes/layers/heatmap_layer/heatmap_layer.ts b/x-pack/plugins/maps/public/classes/layers/heatmap_layer/heatmap_layer.ts index ec9cec3a914ba..bc013cb958a4f 100644 --- a/x-pack/plugins/maps/public/classes/layers/heatmap_layer/heatmap_layer.ts +++ b/x-pack/plugins/maps/public/classes/layers/heatmap_layer/heatmap_layer.ts @@ -200,10 +200,10 @@ export class HeatmapLayer extends AbstractLayer { return this.getCurrentStyle().renderLegendDetails(metricFields[0]); } - async getBounds(syncContext: DataRequestContext) { + async getBounds(getDataRequestContext: (layerId: string) => DataRequestContext) { return await syncBoundsData({ layerId: this.getId(), - syncContext, + syncContext: getDataRequestContext(this.getId()), source: this.getSource(), sourceQuery: this.getQuery(), }); diff --git a/x-pack/plugins/maps/public/classes/layers/layer.test.ts b/x-pack/plugins/maps/public/classes/layers/layer.test.ts index 194b41680872c..908c38a2eef27 100644 --- a/x-pack/plugins/maps/public/classes/layers/layer.test.ts +++ b/x-pack/plugins/maps/public/classes/layers/layer.test.ts @@ -18,7 +18,7 @@ class MockSource { this._fitToBounds = fitToBounds; } cloneDescriptor() { - return {}; + return [{}]; } async supportsFitToBounds() { diff --git a/x-pack/plugins/maps/public/classes/layers/layer.tsx b/x-pack/plugins/maps/public/classes/layers/layer.tsx index b01f2b9b8ca04..ef1a72649bbf0 100644 --- a/x-pack/plugins/maps/public/classes/layers/layer.tsx +++ b/x-pack/plugins/maps/public/classes/layers/layer.tsx @@ -20,7 +20,6 @@ import { MAX_ZOOM, MB_SOURCE_ID_LAYER_ID_PREFIX_DELIMITER, MIN_ZOOM, - SOURCE_BOUNDS_DATA_REQUEST_ID, SOURCE_DATA_REQUEST_ID, } from '../../../common/constants'; import { copyPersistentState } from '../../reducers/copy_persistent_state'; @@ -41,7 +40,9 @@ import { LICENSED_FEATURES } from '../../licensed_features'; import { IESSource } from '../sources/es_source'; export interface ILayer { - getBounds(dataRequestContext: DataRequestContext): Promise; + getBounds( + getDataRequestContext: (layerId: string) => DataRequestContext + ): Promise; getDataRequest(id: string): DataRequest | undefined; getDisplayName(source?: ISource): Promise; getId(): string; @@ -68,7 +69,6 @@ export interface ILayer { getImmutableSourceProperties(): Promise; renderSourceSettingsEditor(sourceEditorArgs: SourceEditorArgs): ReactElement | null; isLayerLoading(): boolean; - isLoadingBounds(): boolean; isFilteredByGlobalTime(): Promise; hasErrors(): boolean; getErrors(): string; @@ -92,7 +92,7 @@ export interface ILayer { getQueryableIndexPatternIds(): string[]; getType(): LAYER_TYPE; isVisible(): boolean; - cloneDescriptor(): Promise; + cloneDescriptor(): Promise; renderStyleEditor( onStyleDescriptorChange: (styleDescriptor: StyleDescriptor) => void, onCustomIconsChange: (customIcons: CustomIcon[]) => void @@ -117,6 +117,7 @@ export interface ILayer { getGeoFieldNames(): string[]; getStyleMetaDescriptorFromLocalFeatures(): Promise; isBasemap(order: number): boolean; + getParent(): string | undefined; } export type LayerIcon = { @@ -174,14 +175,14 @@ export class AbstractLayer implements ILayer { return this._descriptor; } - async cloneDescriptor(): Promise { + async cloneDescriptor(): Promise { const clonedDescriptor = copyPersistentState(this._descriptor); // layer id is uuid used to track styles/layers in mapbox clonedDescriptor.id = uuid(); const displayName = await this.getDisplayName(); clonedDescriptor.label = `Clone of ${displayName}`; clonedDescriptor.sourceDescriptor = this.getSource().cloneDescriptor(); - return clonedDescriptor; + return [clonedDescriptor]; } makeMbLayerId(layerNameSuffix: string): string { @@ -383,11 +384,6 @@ export class AbstractLayer implements ILayer { return areTilesLoading || this._dataRequests.some((dataRequest) => dataRequest.isLoading()); } - isLoadingBounds() { - const boundsDataRequest = this.getDataRequest(SOURCE_BOUNDS_DATA_REQUEST_ID); - return !!boundsDataRequest && boundsDataRequest.isLoading(); - } - hasErrors(): boolean { return _.get(this._descriptor, '__isInErrorState', false); } @@ -427,7 +423,9 @@ export class AbstractLayer implements ILayer { return sourceDataRequest ? sourceDataRequest.hasData() : false; } - async getBounds(dataRequestContext: DataRequestContext): Promise { + async getBounds( + getDataRequestContext: (layerId: string) => DataRequestContext + ): Promise { return null; } @@ -488,6 +486,10 @@ export class AbstractLayer implements ILayer { return false; } + getParent(): string | undefined { + return this._descriptor.parent; + } + _getMetaFromTiles(): TileMetaFeature[] { return this._descriptor.__metaFromTiles || []; } diff --git a/x-pack/plugins/maps/public/classes/layers/layer_group/index.ts b/x-pack/plugins/maps/public/classes/layers/layer_group/index.ts new file mode 100644 index 0000000000000..3b2848d03f5ff --- /dev/null +++ b/x-pack/plugins/maps/public/classes/layers/layer_group/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 { isLayerGroup, LayerGroup } from './layer_group'; diff --git a/x-pack/plugins/maps/public/classes/layers/layer_group/layer_group.tsx b/x-pack/plugins/maps/public/classes/layers/layer_group/layer_group.tsx new file mode 100644 index 0000000000000..c0e3c4ee56402 --- /dev/null +++ b/x-pack/plugins/maps/public/classes/layers/layer_group/layer_group.tsx @@ -0,0 +1,385 @@ +/* + * 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 _ from 'lodash'; +import { i18n } from '@kbn/i18n'; +import type { Map as MbMap } from '@kbn/mapbox-gl'; +import type { Query } from '@kbn/es-query'; +import { asyncMap } from '@kbn/std'; +import React, { ReactElement } from 'react'; +import { EuiIcon } from '@elastic/eui'; +import uuid from 'uuid/v4'; +import { LAYER_TYPE, MAX_ZOOM, MIN_ZOOM } from '../../../../common/constants'; +import { DataRequest } from '../../util/data_request'; +import { copyPersistentState } from '../../../reducers/copy_persistent_state'; +import { + Attribution, + CustomIcon, + LayerDescriptor, + LayerGroupDescriptor, + MapExtent, + StyleDescriptor, + StyleMetaDescriptor, +} from '../../../../common/descriptor_types'; +import { ImmutableSourceProperty, ISource, SourceEditorArgs } from '../../sources/source'; +import { type DataRequestContext } from '../../../actions'; +import { getLayersExtent } from '../../../actions/get_layers_extent'; +import { ILayer, LayerIcon } from '../layer'; +import { IStyle } from '../../styles/style'; +import { LICENSED_FEATURES } from '../../../licensed_features'; + +export function isLayerGroup(layer: ILayer) { + return layer instanceof LayerGroup; +} + +export class LayerGroup implements ILayer { + protected readonly _descriptor: LayerGroupDescriptor; + private _children: ILayer[] = []; + + static createDescriptor(options: Partial): LayerGroupDescriptor { + return { + ...options, + type: LAYER_TYPE.LAYER_GROUP, + id: typeof options.id === 'string' && options.id.length ? options.id : uuid(), + label: + typeof options.label === 'string' && options.label.length + ? options.label + : i18n.translate('xpack.maps.layerGroup.defaultName', { + defaultMessage: 'Layer group', + }), + sourceDescriptor: null, + visible: typeof options.visible === 'boolean' ? options.visible : true, + }; + } + + constructor({ layerDescriptor }: { layerDescriptor: LayerGroupDescriptor }) { + this._descriptor = LayerGroup.createDescriptor(layerDescriptor); + } + + setChildren(children: ILayer[]) { + this._children = children; + } + + getChildren(): ILayer[] { + return [...this._children]; + } + + async _asyncSomeChildren(methodName: string) { + const promises = this.getChildren().map(async (child) => { + // @ts-ignore + return (child[methodName] as () => Promise)(); + }); + return ((await Promise.all(promises)) as boolean[]).some((result) => { + return result; + }); + } + + getDescriptor(): LayerGroupDescriptor { + return this._descriptor; + } + + async cloneDescriptor(): Promise { + const clonedDescriptor = copyPersistentState(this._descriptor); + clonedDescriptor.id = uuid(); + const displayName = await this.getDisplayName(); + clonedDescriptor.label = `Clone of ${displayName}`; + + const childrenDescriptors = await asyncMap(this.getChildren(), async (childLayer) => { + return (await childLayer.cloneDescriptor()).map((childLayerDescriptor) => { + if (childLayerDescriptor.parent === this.getId()) { + childLayerDescriptor.parent = clonedDescriptor.id; + } + return childLayerDescriptor; + }); + }); + + return [..._.flatten(childrenDescriptors), clonedDescriptor]; + } + + makeMbLayerId(layerNameSuffix: string): string { + throw new Error( + 'makeMbLayerId should not be called on LayerGroup, LayerGroup does not render to map' + ); + } + + isPreviewLayer(): boolean { + return !!this._descriptor.__isPreviewLayer; + } + + supportsElasticsearchFilters(): boolean { + return this.getChildren().some((child) => { + return child.supportsElasticsearchFilters(); + }); + } + + async supportsFitToBounds(): Promise { + return this._asyncSomeChildren('supportsFitToBounds'); + } + + async isFittable(): Promise { + return this._asyncSomeChildren('isFittable'); + } + + isIncludeInFitToBounds(): boolean { + return this.getChildren().some((child) => { + return child.isIncludeInFitToBounds(); + }); + } + + async isFilteredByGlobalTime(): Promise { + return this._asyncSomeChildren('isFilteredByGlobalTime'); + } + + async getDisplayName(source?: ISource): Promise { + return this.getLabel(); + } + + async getAttributions(): Promise { + return []; + } + + getStyleForEditing(): IStyle { + throw new Error( + 'getStyleForEditing should not be called on LayerGroup, LayerGroup does not render to map' + ); + } + + getStyle(): IStyle { + throw new Error( + 'getStyle should not be called on LayerGroup, LayerGroup does not render to map' + ); + } + + getCurrentStyle(): IStyle { + throw new Error( + 'getCurrentStyle should not be called on LayerGroup, LayerGroup does not render to map' + ); + } + + getLabel(): string { + return this._descriptor.label ? this._descriptor.label : ''; + } + + getLocale(): string | null { + return null; + } + + getLayerIcon(isTocIcon: boolean): LayerIcon { + return { + icon: , + tooltipContent: '', + }; + } + + async hasLegendDetails(): Promise { + return this._children.length > 0; + } + + renderLegendDetails(): ReactElement | null { + return null; + } + + getId(): string { + return this._descriptor.id; + } + + getSource(): ISource { + throw new Error( + 'getSource should not be called on LayerGroup, LayerGroup does not render to map' + ); + } + + getSourceForEditing(): ISource { + throw new Error( + 'getSourceForEditing should not be called on LayerGroup, LayerGroup does not render to map' + ); + } + + isVisible(): boolean { + return !!this._descriptor.visible; + } + + showAtZoomLevel(zoom: number): boolean { + return zoom >= this.getMinZoom() && zoom <= this.getMaxZoom(); + } + + getMinZoom(): number { + let min = MIN_ZOOM; + this._children.forEach((child) => { + min = Math.max(min, child.getMinZoom()); + }); + return min; + } + + getMaxZoom(): number { + let max = MAX_ZOOM; + this._children.forEach((child) => { + max = Math.min(max, child.getMaxZoom()); + }); + return max; + } + + getMinSourceZoom(): number { + let min = MIN_ZOOM; + this._children.forEach((child) => { + min = Math.max(min, child.getMinSourceZoom()); + }); + return min; + } + + getMbSourceId(): string { + throw new Error( + 'getMbSourceId should not be called on LayerGroup, LayerGroup does not render to map' + ); + } + + getAlpha(): number { + throw new Error( + 'getAlpha should not be called on LayerGroup, LayerGroup does not render to map' + ); + } + + getQuery(): Query | null { + return null; + } + + async getImmutableSourceProperties(): Promise { + return []; + } + + renderSourceSettingsEditor(sourceEditorArgs: SourceEditorArgs) { + return null; + } + + getPrevRequestToken(dataId: string): symbol | undefined { + return undefined; + } + + getInFlightRequestTokens(): symbol[] { + return []; + } + + getSourceDataRequest(): DataRequest | undefined { + return undefined; + } + + getDataRequest(id: string): DataRequest | undefined { + return undefined; + } + + isLayerLoading(): boolean { + return this._children.some((child) => { + return child.isLayerLoading(); + }); + } + + hasErrors(): boolean { + return this._children.some((child) => { + return child.hasErrors(); + }); + } + + getErrors(): string { + const firstChildWithError = this._children.find((child) => { + return child.hasErrors(); + }); + return firstChildWithError ? firstChildWithError.getErrors() : ''; + } + + async syncData(syncContext: DataRequestContext) { + // layer group does not render to map so there is never sync data request + } + + getMbLayerIds(): string[] { + return []; + } + + ownsMbLayerId(layerId: string): boolean { + return false; + } + + ownsMbSourceId(mbSourceId: string): boolean { + return false; + } + + syncLayerWithMB(mbMap: MbMap) { + // layer group does not render to map so there is never sync data request + } + + getLayerTypeIconName(): string { + return 'layers'; + } + + isInitialDataLoadComplete(): boolean { + return true; + } + + async getBounds( + getDataRequestContext: (layerId: string) => DataRequestContext + ): Promise { + return getLayersExtent(this.getChildren(), getDataRequestContext); + } + + renderStyleEditor( + onStyleDescriptorChange: (styleDescriptor: StyleDescriptor) => void, + onCustomIconsChange: (customIcons: CustomIcon[]) => void + ): ReactElement | null { + return null; + } + + getIndexPatternIds(): string[] { + return []; + } + + getQueryableIndexPatternIds(): string[] { + return []; + } + + syncVisibilityWithMb(mbMap: unknown, mbLayerId: string) { + throw new Error( + 'syncVisibilityWithMb should not be called on LayerGroup, LayerGroup does not render to map' + ); + } + + getType(): LAYER_TYPE { + return LAYER_TYPE.LAYER_GROUP; + } + + areLabelsOnTop(): boolean { + return false; + } + + supportsLabelsOnTop(): boolean { + return false; + } + + supportsLabelLocales(): boolean { + return false; + } + + async getLicensedFeatures(): Promise { + return []; + } + + getGeoFieldNames(): string[] { + return []; + } + + async getStyleMetaDescriptorFromLocalFeatures(): Promise { + throw new Error( + 'getStyleMetaDescriptorFromLocalFeatures should not be called on LayerGroup, LayerGroup does not render to map' + ); + } + + isBasemap(order: number): boolean { + return false; + } + + getParent(): string | undefined { + return this._descriptor.parent; + } +} diff --git a/x-pack/plugins/maps/public/classes/layers/vector_layer/blended_vector_layer/blended_vector_layer.test.tsx b/x-pack/plugins/maps/public/classes/layers/vector_layer/blended_vector_layer/blended_vector_layer.test.tsx index f2ef7ca9588be..03da177cddbd9 100644 --- a/x-pack/plugins/maps/public/classes/layers/vector_layer/blended_vector_layer/blended_vector_layer.test.tsx +++ b/x-pack/plugins/maps/public/classes/layers/vector_layer/blended_vector_layer/blended_vector_layer.test.tsx @@ -141,7 +141,9 @@ describe('cloneDescriptor', () => { customIcons, }); - const clonedLayerDescriptor = await blendedVectorLayer.cloneDescriptor(); + const clones = await blendedVectorLayer.cloneDescriptor(); + expect(clones.length).toBe(1); + const clonedLayerDescriptor = clones[0]; expect(clonedLayerDescriptor.sourceDescriptor!.type).toBe(SOURCE_TYPES.ES_SEARCH); expect(clonedLayerDescriptor.label).toBe('Clone of myIndexPattern'); }); @@ -161,7 +163,9 @@ describe('cloneDescriptor', () => { customIcons, }); - const clonedLayerDescriptor = await blendedVectorLayer.cloneDescriptor(); + const clones = await blendedVectorLayer.cloneDescriptor(); + expect(clones.length).toBe(1); + const clonedLayerDescriptor = clones[0]; expect(clonedLayerDescriptor.sourceDescriptor!.type).toBe(SOURCE_TYPES.ES_SEARCH); expect(clonedLayerDescriptor.label).toBe('Clone of myIndexPattern'); }); diff --git a/x-pack/plugins/maps/public/classes/layers/vector_layer/blended_vector_layer/blended_vector_layer.ts b/x-pack/plugins/maps/public/classes/layers/vector_layer/blended_vector_layer/blended_vector_layer.ts index a4b06fe043ff2..ee9fdaf410abb 100644 --- a/x-pack/plugins/maps/public/classes/layers/vector_layer/blended_vector_layer/blended_vector_layer.ts +++ b/x-pack/plugins/maps/public/classes/layers/vector_layer/blended_vector_layer/blended_vector_layer.ts @@ -250,8 +250,12 @@ export class BlendedVectorLayer extends GeoJsonVectorLayer implements IVectorLay return false; } - async cloneDescriptor(): Promise { - const clonedDescriptor = await super.cloneDescriptor(); + async cloneDescriptor(): Promise { + const clones = await super.cloneDescriptor(); + if (clones.length === 0) { + return []; + } + const clonedDescriptor = clones[0]; // Use super getDisplayName instead of instance getDisplayName to avoid getting 'Clustered Clone of Clustered' const displayName = await super.getDisplayName(); @@ -260,7 +264,7 @@ export class BlendedVectorLayer extends GeoJsonVectorLayer implements IVectorLay // sourceDescriptor must be document source descriptor clonedDescriptor.sourceDescriptor = this._documentSource.cloneDescriptor(); - return clonedDescriptor; + return [clonedDescriptor]; } getSource(): IVectorSource { diff --git a/x-pack/plugins/maps/public/classes/layers/vector_layer/geojson_vector_layer/geojson_vector_layer.tsx b/x-pack/plugins/maps/public/classes/layers/vector_layer/geojson_vector_layer/geojson_vector_layer.tsx index bc7ba78c84d98..14a5092606b4d 100644 --- a/x-pack/plugins/maps/public/classes/layers/vector_layer/geojson_vector_layer/geojson_vector_layer.tsx +++ b/x-pack/plugins/maps/public/classes/layers/vector_layer/geojson_vector_layer/geojson_vector_layer.tsx @@ -15,6 +15,7 @@ import { EMPTY_FEATURE_COLLECTION, FEATURE_VISIBLE_PROPERTY_NAME, LAYER_TYPE, + SOURCE_BOUNDS_DATA_REQUEST_ID, } from '../../../../../common/constants'; import { StyleMetaDescriptor, @@ -59,11 +60,11 @@ export class GeoJsonVectorLayer extends AbstractVectorLayer { return layerDescriptor; } - async getBounds(syncContext: DataRequestContext) { + async getBounds(getDataRequestContext: (layerId: string) => DataRequestContext) { const isStaticLayer = !this.getSource().isBoundsAware(); return isStaticLayer || this.hasJoins() ? getFeatureCollectionBounds(this._getSourceFeatureCollection(), this.hasJoins()) - : super.getBounds(syncContext); + : super.getBounds(getDataRequestContext); } getLayerIcon(isTocIcon: boolean): LayerIcon { @@ -211,6 +212,11 @@ export class GeoJsonVectorLayer extends AbstractVectorLayer { await this._syncData(syncContext, this.getSource(), this.getCurrentStyle()); } + _isLoadingBounds() { + const boundsDataRequest = this.getDataRequest(SOURCE_BOUNDS_DATA_REQUEST_ID); + return !!boundsDataRequest && boundsDataRequest.isLoading(); + } + // TLDR: Do not call getSource or getCurrentStyle in syncData flow. Use 'source' and 'style' arguments instead. // // 1) State is contained in the redux store. Layer instance state is readonly. @@ -222,7 +228,7 @@ export class GeoJsonVectorLayer extends AbstractVectorLayer { // Given 2 above, which source/style to use can not be pulled from data request state. // Therefore, source and style are provided as arugments and must be used instead of calling getSource or getCurrentStyle. async _syncData(syncContext: DataRequestContext, source: IVectorSource, style: IVectorStyle) { - if (this.isLoadingBounds()) { + if (this._isLoadingBounds()) { return; } diff --git a/x-pack/plugins/maps/public/classes/layers/vector_layer/mvt_vector_layer/mvt_vector_layer.tsx b/x-pack/plugins/maps/public/classes/layers/vector_layer/mvt_vector_layer/mvt_vector_layer.tsx index 7eaec94eac0a2..a16093af20426 100644 --- a/x-pack/plugins/maps/public/classes/layers/vector_layer/mvt_vector_layer/mvt_vector_layer.tsx +++ b/x-pack/plugins/maps/public/classes/layers/vector_layer/mvt_vector_layer/mvt_vector_layer.tsx @@ -45,6 +45,7 @@ import { getAggsMeta, getHitsMeta, } from '../../../util/tile_meta_feature_utils'; +import { syncBoundsData } from '../bounds_data'; const MAX_RESULT_WINDOW_DATA_REQUEST_ID = 'maxResultWindow'; @@ -77,7 +78,7 @@ export class MvtVectorLayer extends AbstractVectorLayer { : super.isInitialDataLoadComplete(); } - async getBounds(syncContext: DataRequestContext) { + async getBounds(getDataRequestContext: (layerId: string) => DataRequestContext) { // Add filter to narrow bounds to features with matching join keys let joinKeyFilter; if (this.getSource().isESSource()) { @@ -93,12 +94,18 @@ export class MvtVectorLayer extends AbstractVectorLayer { } } - return super.getBounds({ - ...syncContext, - dataFilters: { - ...syncContext.dataFilters, - joinKeyFilter, + const syncContext = getDataRequestContext(this.getId()); + return syncBoundsData({ + layerId: this.getId(), + syncContext: { + ...syncContext, + dataFilters: { + ...syncContext.dataFilters, + joinKeyFilter, + }, }, + source: this.getSource(), + sourceQuery: this.getQuery(), }); } diff --git a/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.test.tsx b/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.test.tsx index b71fef484de01..d450f92467e46 100644 --- a/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.test.tsx +++ b/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.test.tsx @@ -87,7 +87,9 @@ describe('cloneDescriptor', () => { source: new MockSource() as unknown as IVectorSource, customIcons: [], }); - const clonedDescriptor = await layer.cloneDescriptor(); + const clones = await layer.cloneDescriptor(); + expect(clones.length).toBe(1); + const clonedDescriptor = clones[0]; const clonedStyleProps = (clonedDescriptor.style as VectorStyleDescriptor).properties; // Should update style field belonging to join // @ts-expect-error @@ -124,7 +126,9 @@ describe('cloneDescriptor', () => { source: new MockSource() as unknown as IVectorSource, customIcons: [], }); - const clonedDescriptor = await layer.cloneDescriptor(); + const clones = await layer.cloneDescriptor(); + expect(clones.length).toBe(1); + const clonedDescriptor = clones[0]; const clonedStyleProps = (clonedDescriptor.style as VectorStyleDescriptor).properties; // Should update style field belonging to join // @ts-expect-error diff --git a/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx b/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx index 35a5caa7ff9b8..27768dc717bd7 100644 --- a/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx +++ b/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx @@ -162,8 +162,13 @@ export class AbstractVectorLayer extends AbstractLayer implements IVectorLayer { ); } - async cloneDescriptor(): Promise { - const clonedDescriptor = (await super.cloneDescriptor()) as VectorLayerDescriptor; + async cloneDescriptor(): Promise { + const clones = await super.cloneDescriptor(); + if (clones.length === 0) { + return []; + } + + const clonedDescriptor = clones[0] as VectorLayerDescriptor; if (clonedDescriptor.joins) { clonedDescriptor.joins.forEach((joinDescriptor: JoinDescriptor) => { if (joinDescriptor.right && joinDescriptor.right.type === SOURCE_TYPES.TABLE_SOURCE) { @@ -215,7 +220,7 @@ export class AbstractVectorLayer extends AbstractLayer implements IVectorLayer { } }); } - return clonedDescriptor; + return [clonedDescriptor]; } getSource(): IVectorSource { @@ -295,10 +300,10 @@ export class AbstractVectorLayer extends AbstractLayer implements IVectorLayer { return this.getCurrentStyle().renderLegendDetails(); } - async getBounds(syncContext: DataRequestContext) { + async getBounds(getDataRequestContext: (layerId: string) => DataRequestContext) { return syncBoundsData({ layerId: this.getId(), - syncContext, + syncContext: getDataRequestContext(this.getId()), source: this.getSource(), sourceQuery: this.getQuery(), }); diff --git a/x-pack/plugins/maps/public/components/remove_layer_confirm_modal.tsx b/x-pack/plugins/maps/public/components/remove_layer_confirm_modal.tsx new file mode 100644 index 0000000000000..8c35750265cd6 --- /dev/null +++ b/x-pack/plugins/maps/public/components/remove_layer_confirm_modal.tsx @@ -0,0 +1,74 @@ +/* + * 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 { i18n } from '@kbn/i18n'; +import { EuiConfirmModal, EuiText } from '@elastic/eui'; +import { ILayer } from '../classes/layers/layer'; +import { isLayerGroup, LayerGroup } from '../classes/layers/layer_group'; + +export interface Props { + layer: ILayer; + onCancel: () => void; + onConfirm: () => void; +} + +export function RemoveLayerConfirmModal(props: Props) { + function getChildrenCount(layerGroup: LayerGroup) { + let count = 0; + layerGroup.getChildren().forEach((childLayer) => { + count++; + if (isLayerGroup(childLayer)) { + count = count + getChildrenCount(childLayer as LayerGroup); + } + }); + return count; + } + + function renderMultiLayerWarning() { + if (!isLayerGroup(props.layer)) { + return null; + } + + const numChildren = getChildrenCount(props.layer as LayerGroup); + return numChildren > 0 ? ( +

+ {i18n.translate('xpack.maps.deleteLayerConfirmModal.multiLayerWarning', { + defaultMessage: `Removing this layer also removes {numChildren} nested {numChildren, plural, one {layer} other {layers}}.`, + values: { numChildren }, + })} +

+ ) : null; + } + + return ( + + + {renderMultiLayerWarning()} +

+ {i18n.translate('xpack.maps.deleteLayerConfirmModal.unrecoverableWarning', { + defaultMessage: `You can't recover removed layers.`, + })} +

+
+
+ ); +} diff --git a/x-pack/plugins/maps/public/connected_components/edit_layer_panel/edit_layer_panel.tsx b/x-pack/plugins/maps/public/connected_components/edit_layer_panel/edit_layer_panel.tsx index 906947562f940..8ef8319a82798 100644 --- a/x-pack/plugins/maps/public/connected_components/edit_layer_panel/edit_layer_panel.tsx +++ b/x-pack/plugins/maps/public/connected_components/edit_layer_panel/edit_layer_panel.tsx @@ -35,6 +35,7 @@ import { ILayer } from '../../classes/layers/layer'; import { isVectorLayer, IVectorLayer } from '../../classes/layers/vector_layer'; import { ImmutableSourceProperty, OnSourceChangeArgs } from '../../classes/sources/source'; import { IField } from '../../classes/fields/field'; +import { isLayerGroup } from '../../classes/layers/layer_group'; const localStorage = new Storage(window.localStorage); @@ -95,7 +96,7 @@ export class EditLayerPanel extends Component { }; _loadImmutableSourceProperties = async () => { - if (!this.props.selectedLayer) { + if (!this.props.selectedLayer || isLayerGroup(this.props.selectedLayer)) { return; } @@ -160,7 +161,11 @@ export class EditLayerPanel extends Component { } _renderFilterSection() { - if (!this.props.selectedLayer || !this.props.selectedLayer.supportsElasticsearchFilters()) { + if ( + !this.props.selectedLayer || + isLayerGroup(this.props.selectedLayer) || + !this.props.selectedLayer.supportsElasticsearchFilters() + ) { return null; } @@ -197,35 +202,70 @@ export class EditLayerPanel extends Component { ); } - _renderSourceProperties() { - return this.state.immutableSourceProps.map( - ({ label, value, link }: ImmutableSourceProperty) => { - function renderValue() { - if (link) { - return ( - - {value} - - ); - } - return {value}; - } - return ( -

- {label} {renderValue()} -

- ); - } + _renderSourceDetails() { + return !this.props.selectedLayer || isLayerGroup(this.props.selectedLayer) ? null : ( +
+ + + + {this.state.immutableSourceProps.map( + ({ label, value, link }: ImmutableSourceProperty) => { + function renderValue() { + if (link) { + return ( + + {value} + + ); + } + return {value}; + } + return ( +

+ {label} {renderValue()} +

+ ); + } + )} +
+
+
); } - render() { + _renderSourceEditor() { if (!this.props.selectedLayer) { return null; } const descriptor = this.props.selectedLayer.getDescriptor() as VectorLayerDescriptor; const numberOfJoins = descriptor.joins ? descriptor.joins.length : 0; + return isLayerGroup(this.props.selectedLayer) + ? null + : this.props.selectedLayer.renderSourceSettingsEditor({ + currentLayerType: this.props.selectedLayer.getType(), + numberOfJoins, + onChange: this._onSourceChange, + onStyleDescriptorChange: this.props.updateStyleDescriptor, + style: this.props.selectedLayer.getStyleForEditing(), + }); + } + + _renderStyleEditor() { + return !this.props.selectedLayer || isLayerGroup(this.props.selectedLayer) ? null : ( + + ); + } + + render() { + if (!this.props.selectedLayer) { + return null; + } return ( { -
- - - - {this._renderSourceProperties()} - - -
+ {this._renderSourceDetails()}
@@ -273,19 +301,13 @@ export class EditLayerPanel extends Component { supportsFitToBounds={this.state.supportsFitToBounds} /> - {this.props.selectedLayer.renderSourceSettingsEditor({ - currentLayerType: this.props.selectedLayer.getType(), - numberOfJoins, - onChange: this._onSourceChange, - onStyleDescriptorChange: this.props.updateStyleDescriptor, - style: this.props.selectedLayer.getStyleForEditing(), - })} + {this._renderSourceEditor()} {this._renderFilterSection()} {this._renderJoinSection()} - + {this._renderStyleEditor()}
diff --git a/x-pack/plugins/maps/public/connected_components/edit_layer_panel/flyout_footer/flyout_footer.tsx b/x-pack/plugins/maps/public/connected_components/edit_layer_panel/flyout_footer/flyout_footer.tsx index b9761f5d48430..614fbfcebe4e1 100644 --- a/x-pack/plugins/maps/public/connected_components/edit_layer_panel/flyout_footer/flyout_footer.tsx +++ b/x-pack/plugins/maps/public/connected_components/edit_layer_panel/flyout_footer/flyout_footer.tsx @@ -5,69 +5,102 @@ * 2.0. */ -import React from 'react'; +import React, { Component } from 'react'; import { EuiButton, EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiButtonEmpty } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; +import { ILayer } from '../../../classes/layers/layer'; +import { RemoveLayerConfirmModal } from '../../../components/remove_layer_confirm_modal'; export interface Props { + selectedLayer?: ILayer; cancelLayerPanel: () => void; saveLayerEdits: () => void; removeLayer: () => void; hasStateChanged: boolean; } -export const FlyoutFooter = ({ - cancelLayerPanel, - saveLayerEdits, - removeLayer, - hasStateChanged, -}: Props) => { - const removeBtn = ( - - - - - - ); +interface State { + showRemoveModal: boolean; +} + +export class FlyoutFooter extends Component { + state: State = { + showRemoveModal: false, + }; + + _showRemoveModal = () => { + this.setState({ showRemoveModal: true }); + }; - const cancelButtonLabel = hasStateChanged ? ( - - ) : ( - - ); + render() { + const cancelButtonLabel = this.props.hasStateChanged ? ( + + ) : ( + + ); - return ( - - - - {cancelButtonLabel} - - - - - - {removeBtn} - - - - - - - ); -}; + const removeModal = + this.props.selectedLayer && this.state.showRemoveModal ? ( + { + this.setState({ showRemoveModal: false }); + }} + onConfirm={() => { + this.setState({ showRemoveModal: false }); + this.props.removeLayer(); + }} + /> + ) : null; + + return ( + <> + {removeModal} + + + + {cancelButtonLabel} + + + + + + + + + + + + + + + + + + ); + } +} diff --git a/x-pack/plugins/maps/public/connected_components/edit_layer_panel/flyout_footer/index.ts b/x-pack/plugins/maps/public/connected_components/edit_layer_panel/flyout_footer/index.ts index 8546b8088d40a..093f0524b271b 100644 --- a/x-pack/plugins/maps/public/connected_components/edit_layer_panel/flyout_footer/index.ts +++ b/x-pack/plugins/maps/public/connected_components/edit_layer_panel/flyout_footer/index.ts @@ -11,7 +11,7 @@ import { connect } from 'react-redux'; import { FlyoutFooter } from './flyout_footer'; import { FLYOUT_STATE } from '../../../reducers/ui'; -import { hasDirtyState } from '../../../selectors/map_selectors'; +import { getSelectedLayer, hasDirtyState } from '../../../selectors/map_selectors'; import { setSelectedLayer, removeSelectedLayer, @@ -23,6 +23,7 @@ import { MapStoreState } from '../../../reducers/store'; function mapStateToProps(state: MapStoreState) { return { hasStateChanged: hasDirtyState(state), + selectedLayer: getSelectedLayer(state), }; } diff --git a/x-pack/plugins/maps/public/connected_components/edit_layer_panel/layer_settings/layer_settings.tsx b/x-pack/plugins/maps/public/connected_components/edit_layer_panel/layer_settings/layer_settings.tsx index 794064e09d3c6..6d63fc08ef85e 100644 --- a/x-pack/plugins/maps/public/connected_components/edit_layer_panel/layer_settings/layer_settings.tsx +++ b/x-pack/plugins/maps/public/connected_components/edit_layer_panel/layer_settings/layer_settings.tsx @@ -26,6 +26,7 @@ import { AlphaSlider } from '../../../components/alpha_slider'; import { ILayer } from '../../../classes/layers/layer'; import { isVectorLayer, IVectorLayer } from '../../../classes/layers/vector_layer'; import { AttributionFormRow } from './attribution_form_row'; +import { isLayerGroup } from '../../../classes/layers/layer_group'; export interface Props { layer: ILayer; @@ -87,7 +88,7 @@ export function LayerSettings(props: Props) { }; const renderIncludeInFitToBounds = () => { - if (!props.supportsFitToBounds) { + if (!props.supportsFitToBounds || isLayerGroup(props.layer)) { return null; } return ( @@ -113,7 +114,7 @@ export function LayerSettings(props: Props) { }; const renderZoomSliders = () => { - return ( + return isLayerGroup(props.layer) ? null : ( {renderLabel()} {renderZoomSliders()} - + {isLayerGroup(props.layer) ? null : ( + + )} {renderShowLabelsOnTop()} {renderShowLocaleSelector()} - + {isLayerGroup(props.layer) ? null : ( + + )} {renderIncludeInFitToBounds()} {renderDisableTooltips()} diff --git a/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/_index.scss b/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/_index.scss index 9a3e3a45d6c4e..9ca24d055432b 100644 --- a/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/_index.scss +++ b/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/_index.scss @@ -1,2 +1,3 @@ @import 'layer_control'; +@import 'layer_toc/layer_toc'; @import 'layer_toc/toc_entry/toc_entry'; diff --git a/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/__snapshots__/layer_toc.test.tsx.snap b/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/__snapshots__/layer_toc.test.tsx.snap index fbd83ed145a08..7b0741e4bc74a 100644 --- a/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/__snapshots__/layer_toc.test.tsx.snap +++ b/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/__snapshots__/layer_toc.test.tsx.snap @@ -6,9 +6,12 @@ exports[`LayerTOC is rendered 1`] = ` > @@ -22,19 +25,23 @@ exports[`LayerTOC props isReadOnly 1`] = ` data-test-subj="mapLayerTOC" > ) { return { - updateLayerOrder: (newOrder: number[]) => dispatch(updateLayerOrder(newOrder)), + createLayerGroup: (draggedLayerId: string, combineWithLayerId: string) => + dispatch(createLayerGroup(draggedLayerId, combineWithLayerId)), + moveLayerToBottom: (moveLayerId: string) => dispatch(moveLayerToBottom(moveLayerId)), + moveLayerToLeftOfTarget: (moveLayerId: string, targetLayerId: string) => + dispatch(moveLayerToLeftOfTarget(moveLayerId, targetLayerId)), + setLayerParent: (layerId: string, parent: string | undefined) => + dispatch(setLayerParent(layerId, parent)), }; } diff --git a/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/layer_toc.test.tsx b/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/layer_toc.test.tsx index 359794f1468f6..b7ee829b67368 100644 --- a/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/layer_toc.test.tsx +++ b/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/layer_toc.test.tsx @@ -22,6 +22,9 @@ const mockLayers = [ getId: () => { return '1'; }, + getParent: () => { + return undefined; + }, supportsFitToBounds: () => { return true; }, @@ -30,6 +33,9 @@ const mockLayers = [ getId: () => { return '2'; }, + getParent: () => { + return undefined; + }, supportsFitToBounds: () => { return false; }, @@ -39,7 +45,11 @@ const mockLayers = [ const defaultProps = { layerList: mockLayers, isReadOnly: false, - updateLayerOrder: () => {}, + openTOCDetails: [], + moveLayerToBottom: () => {}, + moveLayerToLeftOfTarget: () => {}, + setLayerParent: () => {}, + createLayerGroup: () => {}, }; describe('LayerTOC', () => { diff --git a/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/layer_toc.tsx b/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/layer_toc.tsx index 1800f2dc33618..f152d1686b3bd 100644 --- a/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/layer_toc.tsx +++ b/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/layer_toc.tsx @@ -9,15 +9,38 @@ import _ from 'lodash'; import React, { Component } from 'react'; import { DropResult, EuiDragDropContext, EuiDroppable, EuiDraggable } from '@elastic/eui'; import { TOCEntry } from './toc_entry'; +import { isLayerGroup } from '../../../../classes/layers/layer_group'; import { ILayer } from '../../../../classes/layers/layer'; export interface Props { isReadOnly: boolean; layerList: ILayer[]; - updateLayerOrder: (newOrder: number[]) => void; + openTOCDetails: string[]; + createLayerGroup: (draggedLayerId: string, combineWithLayerId: string) => void; + setLayerParent: (layerId: string, parent: string | undefined) => void; + moveLayerToBottom: (moveLayerId: string) => void; + moveLayerToLeftOfTarget: (moveLayerId: string, targetLayerId: string) => void; } +interface State { + combineLayer: ILayer | null; + isOwnAncestor: boolean; + newRightSiblingLayer: ILayer | null; + sourceLayer: ILayer | null; +} + +const CLEAR_DND_STATE = { + combineLayer: null, + isOwnAncestor: false, + newRightSiblingLayer: null, + sourceLayer: null, +}; + export class LayerTOC extends Component { + state: State = { + ...CLEAR_DND_STATE, + }; + componentWillUnmount() { this._updateDebounced.cancel(); } @@ -29,60 +52,201 @@ export class LayerTOC extends Component { _updateDebounced = _.debounce(this.forceUpdate, 100); - _onDragEnd = ({ source, destination }: DropResult) => { - // Dragging item out of EuiDroppable results in destination of null - if (!destination) { + _reverseIndex(index: number) { + return this.props.layerList.length - index - 1; + } + + _getForebearers(layer: ILayer): string[] { + const parentId = layer.getParent(); + if (!parentId) { + return []; + } + + const parentLayer = this.props.layerList.find((findLayer) => { + return findLayer.getId() === parentId; + }); + if (!parentLayer) { + return []; + } + + return [...this._getForebearers(parentLayer), parentId]; + } + + _onDragStart = ({ source }: DropResult) => { + const sourceIndex = this._reverseIndex(source.index); + const sourceLayer = this.props.layerList[sourceIndex]; + this.setState({ ...CLEAR_DND_STATE, sourceLayer }); + }; + + _onDragUpdate = ({ combine, destination, source }: DropResult) => { + const sourceIndex = this._reverseIndex(source.index); + const sourceLayer = this.props.layerList[sourceIndex]; + + if (combine) { + const combineIndex = this.props.layerList.findIndex((findLayer) => { + return findLayer.getId() === combine.draggableId; + }); + const combineLayer = combineIndex !== -1 ? this.props.layerList[combineIndex] : null; + + const newRightSiblingIndex = combineIndex - 1; + const newRightSiblingLayer = + newRightSiblingIndex < 0 ? null : this.props.layerList[newRightSiblingIndex]; + + const forebearers = combineLayer ? this._getForebearers(combineLayer) : []; + + this.setState({ + combineLayer, + newRightSiblingLayer, + sourceLayer, + isOwnAncestor: forebearers.includes(sourceLayer.getId()), + }); + return; + } + + if (!destination || source.index === destination.index) { + this.setState({ ...CLEAR_DND_STATE }); return; } - // Layer list is displayed in reverse order so index needs to reversed to get back to original reference. - const reverseIndex = (index: number) => { - return this.props.layerList.length - index - 1; - }; + const destinationIndex = this._reverseIndex(destination.index); + const newRightSiblingIndex = + sourceIndex > destinationIndex + ? // When layer is moved to the right, new right sibling is layer to the right of destination + destinationIndex - 1 + : // When layer is moved to the left, new right sibling is the destination + destinationIndex; + const newRightSiblingLayer = + newRightSiblingIndex < 0 ? null : this.props.layerList[newRightSiblingIndex]; + + const forebearers = newRightSiblingLayer ? this._getForebearers(newRightSiblingLayer) : []; - const prevIndex = reverseIndex(source.index); - const newIndex = reverseIndex(destination.index); - const newOrder = []; - for (let i = 0; i < this.props.layerList.length; i++) { - newOrder.push(i); + this.setState({ + combineLayer: null, + newRightSiblingLayer, + sourceLayer, + isOwnAncestor: forebearers.includes(sourceLayer.getId()), + }); + }; + + _onDragEnd = () => { + const { combineLayer, isOwnAncestor, sourceLayer, newRightSiblingLayer } = this.state; + this.setState({ ...CLEAR_DND_STATE }); + + if (isOwnAncestor || !sourceLayer) { + return; + } + + if (combineLayer) { + // add source to layer group when combine is layer group + if (isLayerGroup(combineLayer) && newRightSiblingLayer) { + this.props.setLayerParent(sourceLayer.getId(), combineLayer.getId()); + this.props.moveLayerToLeftOfTarget(sourceLayer.getId(), newRightSiblingLayer.getId()); + return; + } + + // creage layer group that contains source and combine + this.props.createLayerGroup(sourceLayer.getId(), combineLayer.getId()); + return; } - newOrder.splice(prevIndex, 1); - newOrder.splice(newIndex, 0, prevIndex); - this.props.updateLayerOrder(newOrder); + + if (newRightSiblingLayer) { + this.props.setLayerParent(sourceLayer.getId(), newRightSiblingLayer.getParent()); + this.props.moveLayerToLeftOfTarget(sourceLayer.getId(), newRightSiblingLayer.getId()); + return; + } + + this.props.moveLayerToBottom(sourceLayer.getId()); }; + _getDepth(layer: ILayer, depth: number): { depth: number; showInTOC: boolean } { + if (layer.getParent() === undefined) { + return { depth, showInTOC: true }; + } + + const parent = this.props.layerList.find((nextLayer) => { + return layer.getParent() === nextLayer.getId(); + }); + if (!parent) { + return { depth, showInTOC: false }; + } + + return this.props.openTOCDetails.includes(parent.getId()) + ? this._getDepth(parent, depth + 1) + : { depth, showInTOC: false }; + } + + _getDroppableClass() { + if (!this.state.sourceLayer) { + // nothing is dragged + return ''; + } + + if (this.state.isOwnAncestor) { + return 'mapLayerToc-droppable-dropNotAllowed'; + } + + if (this.state.combineLayer) { + return 'mapLayerToc-droppable-isCombining'; + } + + return 'mapLayerToc-droppable-isDragging'; + } + _renderLayers() { - // Reverse layer list so first layer drawn on map is at the bottom and - // last layer drawn on map is at the top. - const reverseLayerList = [...this.props.layerList].reverse(); + const tocEntryList = this.props.layerList + .map((layer, index) => { + return { + ...this._getDepth(layer, 0), + draggableIndex: this._reverseIndex(index), + layer, + }; + }) + .filter(({ showInTOC }) => { + return showInTOC; + }) + // Reverse layer list so first layer drawn on map is at the bottom and + // last layer drawn on map is at the top. + .reverse(); if (this.props.isReadOnly) { - return reverseLayerList.map((layer) => { - return ; + return tocEntryList.map(({ depth, layer }) => { + return ; }); } return ( - - - {(droppableProvided, snapshot) => { - const tocEntries = reverseLayerList.map((layer, idx: number) => ( + + + {(droppableProvided, droppableSnapshot) => { + const tocEntries = tocEntryList.map(({ draggableIndex, depth, layer }) => ( - {(provided, state) => ( - - )} + {(draggableProvided, draggableSnapshot) => { + return ( + + ); + }} )); return
{tocEntries}
; diff --git a/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/__snapshots__/toc_entry.test.tsx.snap b/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/__snapshots__/toc_entry.test.tsx.snap index cec85cb0e1cd6..0973bd4f24459 100644 --- a/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/__snapshots__/toc_entry.test.tsx.snap +++ b/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/__snapshots__/toc_entry.test.tsx.snap @@ -5,6 +5,94 @@ exports[`TOCEntry is rendered 1`] = ` className="mapTocEntry" data-layerid="1" id="1" + style={Object {}} +> +
+ +
+ + + + +
+
+ + + +
+`; + +exports[`TOCEntry props Should indent child layer 1`] = ` +
{}, @@ -93,6 +94,17 @@ describe('TOCEntry', () => { expect(component).toMatchSnapshot(); }); + test('Should indent child layer', async () => { + const component = shallow(); + + // Ensure all promises resolve + await new Promise((resolve) => process.nextTick(resolve)); + // Ensure the state changes are reflected + component.update(); + + expect(component).toMatchSnapshot(); + }); + test('should display layer details when isLegendDetailsOpen is true', async () => { const component = shallow(); diff --git a/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/toc_entry.tsx b/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/toc_entry.tsx index 65431432d8c6d..72eb38f07257e 100644 --- a/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/toc_entry.tsx +++ b/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/toc_entry.tsx @@ -44,6 +44,7 @@ export interface ReduxDispatchProps { } export interface OwnProps { + depth: number; layer: ILayer; dragHandleProps?: DraggableProvidedDragHandleProps; isDragging?: boolean; @@ -226,7 +227,7 @@ export class TOCEntry extends Component { } _renderDetailsToggle() { - if (!this.state.hasLegendDetails) { + if (this.props.isDragging || !this.state.hasLegendDetails) { return null; } @@ -319,8 +320,12 @@ export class TOCEntry extends Component { 'mapTocEntry-isInEditingMode': this.props.isFeatureEditorOpenForLayer, }); + const depthStyle = + this.props.depth > 0 ? { paddingLeft: `${8 + this.props.depth * 24}px` } : {}; + return (
+ + } + className="mapLayTocActions" + closePopover={[Function]} + display="inline-block" + hasArrow={true} + id="testLayer" + isOpen={false} + ownFocus={true} + panelPaddingSize="none" + > + , + "name": "Fit to data", + "onClick": [Function], + "toolTipContent": null, + }, + Object { + "data-test-subj": "layerVisibilityToggleButton", + "icon": , + "name": "Hide layer", + "onClick": [Function], + "toolTipContent": null, + }, + Object { + "data-test-subj": "layerSettingsButton", + "disabled": false, + "icon": , + "name": "Edit layer settings", + "onClick": [Function], + "toolTipContent": null, + }, + Object { + "data-test-subj": "cloneLayerButton", + "icon": , + "name": "Clone layer", + "onClick": [Function], + "toolTipContent": null, + }, + Object { + "data-test-subj": "removeLayerButton", + "icon": , + "name": "Remove layer", + "onClick": [Function], + "toolTipContent": null, + }, + ], + "title": "Layer actions", + }, + ] } - onClick={[Function]} + size="m" /> - } - className="mapLayTocActions" - closePopover={[Function]} - display="inline-block" - hasArrow={true} - id="testLayer" - isOpen={false} - ownFocus={true} - panelPaddingSize="none" -> - , - "name": "Fit to data", - "onClick": [Function], - "toolTipContent": null, - }, - Object { - "data-test-subj": "layerVisibilityToggleButton", - "icon": , - "name": "Hide layer", - "onClick": [Function], - "toolTipContent": null, - }, - Object { - "data-test-subj": "layerSettingsButton", - "disabled": false, - "icon": , - "name": "Edit layer settings", - "onClick": [Function], - "toolTipContent": null, - }, - Object { - "data-test-subj": "cloneLayerButton", - "icon": , - "name": "Clone layer", - "onClick": [Function], - "toolTipContent": null, - }, - Object { - "data-test-subj": "removeLayerButton", - "icon": , - "name": "Remove layer", - "onClick": [Function], - "toolTipContent": null, - }, - ], - "title": "Layer actions", - }, - ] - } - size="m" - /> - + + `; exports[`TOCEntryActionsPopover should disable Edit features when edit mode active for layer 1`] = ` - + + } + className="mapLayTocActions" + closePopover={[Function]} + display="inline-block" + hasArrow={true} + id="testLayer" + isOpen={false} + ownFocus={true} + panelPaddingSize="none" + > + , + "name": "Fit to data", + "onClick": [Function], + "toolTipContent": null, + }, + Object { + "data-test-subj": "layerVisibilityToggleButton", + "icon": , + "name": "Hide layer", + "onClick": [Function], + "toolTipContent": null, + }, + Object { + "data-test-subj": "layerSettingsButton", + "disabled": false, + "icon": , + "name": "Edit layer settings", + "onClick": [Function], + "toolTipContent": null, + }, + Object { + "data-test-subj": "cloneLayerButton", + "icon": , + "name": "Clone layer", + "onClick": [Function], + "toolTipContent": null, + }, + Object { + "data-test-subj": "removeLayerButton", + "icon": , + "name": "Remove layer", + "onClick": [Function], + "toolTipContent": null, + }, + ], + "title": "Layer actions", + }, + ] } - onClick={[Function]} + size="m" /> - } - className="mapLayTocActions" - closePopover={[Function]} - display="inline-block" - hasArrow={true} - id="testLayer" - isOpen={false} - ownFocus={true} - panelPaddingSize="none" -> - , - "name": "Fit to data", - "onClick": [Function], - "toolTipContent": null, - }, - Object { - "data-test-subj": "layerVisibilityToggleButton", - "icon": , - "name": "Hide layer", - "onClick": [Function], - "toolTipContent": null, - }, - Object { - "data-test-subj": "layerSettingsButton", - "disabled": false, - "icon": , - "name": "Edit layer settings", - "onClick": [Function], - "toolTipContent": null, - }, - Object { - "data-test-subj": "cloneLayerButton", - "icon": , - "name": "Clone layer", - "onClick": [Function], - "toolTipContent": null, - }, - Object { - "data-test-subj": "removeLayerButton", - "icon": , - "name": "Remove layer", - "onClick": [Function], - "toolTipContent": null, - }, - ], - "title": "Layer actions", - }, - ] - } - size="m" - /> - + + `; exports[`TOCEntryActionsPopover should disable fit to data when supportsFitToBounds is false 1`] = ` - + + } + className="mapLayTocActions" + closePopover={[Function]} + display="inline-block" + hasArrow={true} + id="testLayer" + isOpen={false} + ownFocus={true} + panelPaddingSize="none" + > + , + "name": "Fit to data", + "onClick": [Function], + "toolTipContent": "Layer does not support fit to data", + }, + Object { + "data-test-subj": "layerVisibilityToggleButton", + "icon": , + "name": "Hide layer", + "onClick": [Function], + "toolTipContent": null, + }, + Object { + "data-test-subj": "layerSettingsButton", + "disabled": false, + "icon": , + "name": "Edit layer settings", + "onClick": [Function], + "toolTipContent": null, + }, + Object { + "data-test-subj": "cloneLayerButton", + "icon": , + "name": "Clone layer", + "onClick": [Function], + "toolTipContent": null, + }, + Object { + "data-test-subj": "removeLayerButton", + "icon": , + "name": "Remove layer", + "onClick": [Function], + "toolTipContent": null, + }, + ], + "title": "Layer actions", + }, + ] } - onClick={[Function]} + size="m" /> - } - className="mapLayTocActions" - closePopover={[Function]} - display="inline-block" - hasArrow={true} - id="testLayer" - isOpen={false} - ownFocus={true} - panelPaddingSize="none" -> - , - "name": "Fit to data", - "onClick": [Function], - "toolTipContent": "Layer does not support fit to data", - }, - Object { - "data-test-subj": "layerVisibilityToggleButton", - "icon": , - "name": "Hide layer", - "onClick": [Function], - "toolTipContent": null, - }, - Object { - "data-test-subj": "layerSettingsButton", - "disabled": false, - "icon": , - "name": "Edit layer settings", - "onClick": [Function], - "toolTipContent": null, - }, - Object { - "data-test-subj": "cloneLayerButton", - "icon": , - "name": "Clone layer", - "onClick": [Function], - "toolTipContent": null, - }, - Object { - "data-test-subj": "removeLayerButton", - "icon": , - "name": "Remove layer", - "onClick": [Function], - "toolTipContent": null, - }, - ], - "title": "Layer actions", - }, - ] - } - size="m" - /> - + + `; exports[`TOCEntryActionsPopover should have "show layer" action when layer is not visible 1`] = ` - + + } + className="mapLayTocActions" + closePopover={[Function]} + display="inline-block" + hasArrow={true} + id="testLayer" + isOpen={false} + ownFocus={true} + panelPaddingSize="none" + > + , + "name": "Fit to data", + "onClick": [Function], + "toolTipContent": null, + }, + Object { + "data-test-subj": "layerVisibilityToggleButton", + "icon": , + "name": "Show layer", + "onClick": [Function], + "toolTipContent": null, + }, + Object { + "data-test-subj": "layerSettingsButton", + "disabled": false, + "icon": , + "name": "Edit layer settings", + "onClick": [Function], + "toolTipContent": null, + }, + Object { + "data-test-subj": "cloneLayerButton", + "icon": , + "name": "Clone layer", + "onClick": [Function], + "toolTipContent": null, + }, + Object { + "data-test-subj": "removeLayerButton", + "icon": , + "name": "Remove layer", + "onClick": [Function], + "toolTipContent": null, + }, + ], + "title": "Layer actions", + }, + ] } - onClick={[Function]} + size="m" /> - } - className="mapLayTocActions" - closePopover={[Function]} - display="inline-block" - hasArrow={true} - id="testLayer" - isOpen={false} - ownFocus={true} - panelPaddingSize="none" -> - , - "name": "Fit to data", - "onClick": [Function], - "toolTipContent": null, - }, - Object { - "data-test-subj": "layerVisibilityToggleButton", - "icon": , - "name": "Show layer", - "onClick": [Function], - "toolTipContent": null, - }, - Object { - "data-test-subj": "layerSettingsButton", - "disabled": false, - "icon": , - "name": "Edit layer settings", - "onClick": [Function], - "toolTipContent": null, - }, - Object { - "data-test-subj": "cloneLayerButton", - "icon": , - "name": "Clone layer", - "onClick": [Function], - "toolTipContent": null, - }, - Object { - "data-test-subj": "removeLayerButton", - "icon": , - "name": "Remove layer", - "onClick": [Function], - "toolTipContent": null, - }, - ], - "title": "Layer actions", - }, - ] - } - size="m" - /> - + + `; exports[`TOCEntryActionsPopover should not show edit actions in read only mode 1`] = ` - + + } + className="mapLayTocActions" + closePopover={[Function]} + display="inline-block" + hasArrow={true} + id="testLayer" + isOpen={false} + ownFocus={true} + panelPaddingSize="none" + > + , + "name": "Fit to data", + "onClick": [Function], + "toolTipContent": null, + }, + Object { + "data-test-subj": "layerVisibilityToggleButton", + "icon": , + "name": "Hide layer", + "onClick": [Function], + "toolTipContent": null, + }, + ], + "title": "Layer actions", + }, + ] } - onClick={[Function]} + size="m" /> - } - className="mapLayTocActions" - closePopover={[Function]} - display="inline-block" - hasArrow={true} - id="testLayer" - isOpen={false} - ownFocus={true} - panelPaddingSize="none" -> - , - "name": "Fit to data", - "onClick": [Function], - "toolTipContent": null, - }, - Object { - "data-test-subj": "layerVisibilityToggleButton", - "icon": , - "name": "Hide layer", - "onClick": [Function], - "toolTipContent": null, - }, - ], - "title": "Layer actions", - }, - ] - } - size="m" - /> - + + `; exports[`TOCEntryActionsPopover should show "show this layer only" action when there are more then 2 layers 1`] = ` - + + } + className="mapLayTocActions" + closePopover={[Function]} + display="inline-block" + hasArrow={true} + id="testLayer" + isOpen={false} + ownFocus={true} + panelPaddingSize="none" + > + , + "name": "Fit to data", + "onClick": [Function], + "toolTipContent": null, + }, + Object { + "data-test-subj": "layerVisibilityToggleButton", + "icon": , + "name": "Hide layer", + "onClick": [Function], + "toolTipContent": null, + }, + Object { + "data-test-subj": "showThisLayerOnlyButton", + "icon": , + "name": "Show this layer only", + "onClick": [Function], + "toolTipContent": null, + }, + Object { + "data-test-subj": "layerSettingsButton", + "disabled": false, + "icon": , + "name": "Edit layer settings", + "onClick": [Function], + "toolTipContent": null, + }, + Object { + "data-test-subj": "cloneLayerButton", + "icon": , + "name": "Clone layer", + "onClick": [Function], + "toolTipContent": null, + }, + Object { + "data-test-subj": "removeLayerButton", + "icon": , + "name": "Remove layer", + "onClick": [Function], + "toolTipContent": null, + }, + ], + "title": "Layer actions", + }, + ] } - onClick={[Function]} + size="m" /> - } - className="mapLayTocActions" - closePopover={[Function]} - display="inline-block" - hasArrow={true} - id="testLayer" - isOpen={false} - ownFocus={true} - panelPaddingSize="none" -> - , - "name": "Fit to data", - "onClick": [Function], - "toolTipContent": null, - }, - Object { - "data-test-subj": "layerVisibilityToggleButton", - "icon": , - "name": "Hide layer", - "onClick": [Function], - "toolTipContent": null, - }, - Object { - "data-test-subj": "showThisLayerOnlyButton", - "icon": , - "name": "Show this layer only", - "onClick": [Function], - "toolTipContent": null, - }, - Object { - "data-test-subj": "layerSettingsButton", - "disabled": false, - "icon": , - "name": "Edit layer settings", - "onClick": [Function], - "toolTipContent": null, - }, - Object { - "data-test-subj": "cloneLayerButton", - "icon": , - "name": "Clone layer", - "onClick": [Function], - "toolTipContent": null, - }, - Object { - "data-test-subj": "removeLayerButton", - "icon": , - "name": "Remove layer", - "onClick": [Function], - "toolTipContent": null, - }, - ], - "title": "Layer actions", - }, - ] - } - size="m" - /> - + + `; diff --git a/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/toc_entry_actions_popover/toc_entry_actions_popover.tsx b/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/toc_entry_actions_popover/toc_entry_actions_popover.tsx index 5e33931a8943e..a67c12d2928a4 100644 --- a/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/toc_entry_actions_popover/toc_entry_actions_popover.tsx +++ b/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/toc_entry_actions_popover/toc_entry_actions_popover.tsx @@ -20,6 +20,7 @@ import { import { ESSearchSource } from '../../../../../../classes/sources/es_search_source'; import { isVectorLayer, IVectorLayer } from '../../../../../../classes/layers/vector_layer'; import { SCALING_TYPES, VECTOR_SHAPE_TYPE } from '../../../../../../../common/constants'; +import { RemoveLayerConfirmModal } from '../../../../../../components/remove_layer_confirm_modal'; export interface Props { cloneLayer: (layerId: string) => void; @@ -41,6 +42,7 @@ export interface Props { interface State { isPopoverOpen: boolean; + showRemoveModal: boolean; supportsFeatureEditing: boolean; isFeatureEditingEnabled: boolean; } @@ -48,6 +50,7 @@ interface State { export class TOCEntryActionsPopover extends Component { state: State = { isPopoverOpen: false, + showRemoveModal: false, supportsFeatureEditing: false, isFeatureEditingEnabled: false, }; @@ -119,10 +122,6 @@ export class TOCEntryActionsPopover extends Component { this.props.fitToBounds(this.props.layer.getId()); } - _removeLayer() { - this.props.removeLayer(this.props.layer.getId()); - } - _toggleVisible() { this.props.toggleVisible(this.props.layer.getId()); } @@ -230,8 +229,7 @@ export class TOCEntryActionsPopover extends Component { toolTipContent: null, 'data-test-subj': 'removeLayerButton', onClick: () => { - this._closePopover(); - this._removeLayer(); + this.setState({ showRemoveModal: true }); }, }); } @@ -246,30 +244,46 @@ export class TOCEntryActionsPopover extends Component { } render() { + const removeModal = this.state.showRemoveModal ? ( + { + this.setState({ showRemoveModal: false }); + }} + onConfirm={() => { + this.setState({ showRemoveModal: false }); + this._closePopover(); + this.props.removeLayer(this.props.layer.getId()); + }} + /> + ) : null; return ( - + {removeModal} + + } + isOpen={this.state.isPopoverOpen} + closePopover={this._closePopover} + panelPaddingSize="none" + anchorPosition="leftUp" + anchorClassName="mapLayTocActions__popoverAnchor" + > + - } - isOpen={this.state.isPopoverOpen} - closePopover={this._closePopover} - panelPaddingSize="none" - anchorPosition="leftUp" - anchorClassName="mapLayTocActions__popoverAnchor" - > - - + + ); } } diff --git a/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/toc_entry_button/toc_entry_button.tsx b/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/toc_entry_button/toc_entry_button.tsx index c55821c522d14..7e35447d45e41 100644 --- a/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/toc_entry_button/toc_entry_button.tsx +++ b/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/toc_entry_button/toc_entry_button.tsx @@ -11,6 +11,7 @@ import { EuiButtonEmpty, EuiIcon, EuiToolTip, EuiLoadingSpinner } from '@elastic import { i18n } from '@kbn/i18n'; import { ILayer } from '../../../../../../classes/layers/layer'; import { IVectorSource } from '../../../../../../classes/sources/vector_source'; +import { isLayerGroup } from '../../../../../../classes/layers/layer_group'; interface Footnote { icon: ReactNode; @@ -69,72 +70,88 @@ export class TOCEntryButton extends Component { } getIconAndTooltipContent(): IconAndTooltipContent { - let icon; - let tooltipContent = null; - const footnotes = []; if (this.props.layer.hasErrors()) { - icon = ( - - ); - tooltipContent = this.props.layer.getErrors(); - } else if (!this.props.layer.isVisible()) { - icon = ; - tooltipContent = i18n.translate('xpack.maps.layer.layerHiddenTooltip', { - defaultMessage: `Layer is hidden.`, - }); - } else if (this.props.layer.isLayerLoading()) { - icon = ; - } else if (!this.props.layer.showAtZoomLevel(this.props.zoom)) { + return { + icon: ( + + ), + tooltipContent: this.props.layer.getErrors(), + footnotes: [], + }; + } + + if (!this.props.layer.isVisible()) { + return { + icon: , + tooltipContent: i18n.translate('xpack.maps.layer.layerHiddenTooltip', { + defaultMessage: `Layer is hidden.`, + }), + footnotes: [], + }; + } + + if (this.props.layer.isLayerLoading()) { + return { + icon: , + tooltipContent: '', + footnotes: [], + }; + } + + if (!this.props.layer.showAtZoomLevel(this.props.zoom)) { const minZoom = this.props.layer.getMinZoom(); const maxZoom = this.props.layer.getMaxZoom(); - icon = ; - tooltipContent = i18n.translate('xpack.maps.layer.zoomFeedbackTooltip', { - defaultMessage: `Layer is visible between zoom levels {minZoom} and {maxZoom}.`, - values: { minZoom, maxZoom }, + return { + icon: , + tooltipContent: i18n.translate('xpack.maps.layer.zoomFeedbackTooltip', { + defaultMessage: `Layer is visible between zoom levels {minZoom} and {maxZoom}.`, + values: { minZoom, maxZoom }, + }), + footnotes: [], + }; + } + + const { icon, tooltipContent } = this.props.layer.getLayerIcon(true); + + if (isLayerGroup(this.props.layer)) { + return { icon, tooltipContent, footnotes: [] }; + } + + const footnotes = []; + if (this.props.isUsingSearch && this.props.layer.getQueryableIndexPatternIds().length) { + footnotes.push({ + icon: , + message: i18n.translate('xpack.maps.layer.isUsingSearchMsg', { + defaultMessage: 'Results narrowed by global search', + }), + }); + } + if (this.state.isFilteredByGlobalTime) { + footnotes.push({ + icon: , + message: i18n.translate('xpack.maps.layer.isUsingTimeFilter', { + defaultMessage: 'Results narrowed by global time', + }), + }); + } + const source = this.props.layer.getSource(); + if ( + typeof source.isFilterByMapBounds === 'function' && + (source as IVectorSource).isFilterByMapBounds() + ) { + footnotes.push({ + icon: , + message: i18n.translate('xpack.maps.layer.isUsingBoundsFilter', { + defaultMessage: 'Results narrowed by visible map area', + }), }); - } else { - const { icon: layerIcon, tooltipContent: layerTooltipContent } = - this.props.layer.getLayerIcon(true); - icon = layerIcon; - if (layerTooltipContent) { - tooltipContent = layerTooltipContent; - } - - if (this.props.isUsingSearch && this.props.layer.getQueryableIndexPatternIds().length) { - footnotes.push({ - icon: , - message: i18n.translate('xpack.maps.layer.isUsingSearchMsg', { - defaultMessage: 'Results narrowed by global search', - }), - }); - } - if (this.state.isFilteredByGlobalTime) { - footnotes.push({ - icon: , - message: i18n.translate('xpack.maps.layer.isUsingTimeFilter', { - defaultMessage: 'Results narrowed by global time', - }), - }); - } - const source = this.props.layer.getSource(); - if ( - typeof source.isFilterByMapBounds === 'function' && - (source as IVectorSource).isFilterByMapBounds() - ) { - footnotes.push({ - icon: , - message: i18n.translate('xpack.maps.layer.isUsingBoundsFilter', { - defaultMessage: 'Results narrowed by visible map area', - }), - }); - } } return { diff --git a/x-pack/plugins/maps/public/reducers/map/layer_utils.ts b/x-pack/plugins/maps/public/reducers/map/layer_utils.ts index 206cc4a740192..bfe7b39fe2868 100644 --- a/x-pack/plugins/maps/public/reducers/map/layer_utils.ts +++ b/x-pack/plugins/maps/public/reducers/map/layer_utils.ts @@ -62,12 +62,7 @@ export function updateLayerInList( const updatedLayer = { ...layerList[layerIdx], - // Update layer w/ new value. If no value provided, toggle boolean value - // allow empty strings, 0-value - [attribute]: - newValue || newValue === '' || newValue === 0 - ? newValue - : !(layerList[layerIdx][attribute] as boolean), + [attribute]: newValue, }; const updatedList = [ ...layerList.slice(0, layerIdx), diff --git a/x-pack/plugins/maps/public/selectors/map_selectors.ts b/x-pack/plugins/maps/public/selectors/map_selectors.ts index 6ee55bd72e49d..1d46ef3015046 100644 --- a/x-pack/plugins/maps/public/selectors/map_selectors.ts +++ b/x-pack/plugins/maps/public/selectors/map_selectors.ts @@ -20,6 +20,7 @@ import { GeoJsonVectorLayer, } from '../classes/layers/vector_layer'; import { VectorStyle } from '../classes/styles/vector/vector_style'; +import { isLayerGroup, LayerGroup } from '../classes/layers/layer_group'; import { HeatmapLayer } from '../classes/layers/heatmap_layer'; import { getTimeFilter } from '../kibana_services'; import { getChartsPaletteServiceGetColor } from '../reducers/non_serializable_instances'; @@ -47,6 +48,7 @@ import { Goto, HeatmapLayerDescriptor, LayerDescriptor, + LayerGroupDescriptor, MapCenter, MapExtent, MapSettings, @@ -74,8 +76,11 @@ export function createLayerInstance( customIcons: CustomIcon[], chartsPaletteServiceGetColor?: (value: string) => string | null ): ILayer { - const source: ISource = createSourceInstance(layerDescriptor.sourceDescriptor); + if (layerDescriptor.type === LAYER_TYPE.LAYER_GROUP) { + return new LayerGroup({ layerDescriptor: layerDescriptor as LayerGroupDescriptor }); + } + const source: ISource = createSourceInstance(layerDescriptor.sourceDescriptor); switch (layerDescriptor.type) { case LAYER_TYPE.RASTER_TILE: return new RasterTileLayer({ layerDescriptor, source: source as IRasterSource }); @@ -324,9 +329,32 @@ export const getLayerList = createSelector( getChartsPaletteServiceGetColor, getCustomIcons, (layerDescriptorList, chartsPaletteServiceGetColor, customIcons) => { - return layerDescriptorList.map((layerDescriptor) => + const layers = layerDescriptorList.map((layerDescriptor) => createLayerInstance(layerDescriptor, customIcons, chartsPaletteServiceGetColor) ); + + const childrenMap = new Map(); + layers.forEach((layer) => { + const parent = layer.getParent(); + if (!parent) { + return; + } + + const children = childrenMap.has(parent) ? childrenMap.get(parent)! : []; + childrenMap.set(parent, [...children, layer]); + }); + + childrenMap.forEach((children, parent) => { + const parentLayer = layers.find((layer) => { + return layer.getId() === parent; + }); + if (!parentLayer || !isLayerGroup(parentLayer)) { + return; + } + (parentLayer as LayerGroup).setChildren(children); + }); + + return layers; } ); diff --git a/x-pack/plugins/ml/common/util/job_utils.test.ts b/x-pack/plugins/ml/common/util/job_utils.test.ts index 5c651fb10f2f1..3318001a6f3d2 100644 --- a/x-pack/plugins/ml/common/util/job_utils.test.ts +++ b/x-pack/plugins/ml/common/util/job_utils.test.ts @@ -21,8 +21,12 @@ import { getLatestDataOrBucketTimestamp, getEarliestDatafeedStartTime, resolveMaxTimeInterval, + getFiltersForDSLQuery, + isKnownEmptyQuery, } from './job_utils'; import { CombinedJob, Job } from '../types/anomaly_detection_jobs'; +import { FilterStateStore } from '@kbn/es-query'; + import moment from 'moment'; describe('ML - job utils', () => { @@ -613,3 +617,178 @@ describe('ML - job utils', () => { }); }); }); + +describe('getFiltersForDSLQuery', () => { + describe('when DSL query contains match_all', () => { + test('returns empty array when query contains a must clause that contains match_all', () => { + const actual = getFiltersForDSLQuery( + { bool: { must: [{ match_all: {} }] } }, + 'dataview-id', + 'test-alias' + ); + expect(actual).toEqual([]); + }); + }); + + describe('when DSL query is valid', () => { + const query = { + bool: { + must: [], + filter: [ + { + range: { + '@timestamp': { + format: 'strict_date_optional_time', + gte: '2007-09-29T15:05:14.509Z', + lte: '2022-09-29T15:05:14.509Z', + }, + }, + }, + { + match_phrase: { + response_code: '200', + }, + }, + ], + should: [], + must_not: [], + }, + }; + + test('returns filters with alias', () => { + const actual = getFiltersForDSLQuery(query, 'dataview-id', 'test-alias'); + expect(actual).toEqual([ + { + $state: { store: 'appState' }, + meta: { + alias: 'test-alias', + disabled: false, + index: 'dataview-id', + negate: false, + type: 'custom', + value: + '{"bool":{"must":[],"filter":[{"range":{"@timestamp":{"format":"strict_date_optional_time","gte":"2007-09-29T15:05:14.509Z","lte":"2022-09-29T15:05:14.509Z"}}},{"match_phrase":{"response_code":"200"}}],"should":[],"must_not":[]}}', + }, + query, + }, + ]); + }); + + test('returns filter with no alias if alias is not provided', () => { + const actual = getFiltersForDSLQuery(query, 'dataview-id'); + expect(actual).toEqual([ + { + $state: { store: 'appState' }, + meta: { + disabled: false, + index: 'dataview-id', + negate: false, + type: 'custom', + value: + '{"bool":{"must":[],"filter":[{"range":{"@timestamp":{"format":"strict_date_optional_time","gte":"2007-09-29T15:05:14.509Z","lte":"2022-09-29T15:05:14.509Z"}}},{"match_phrase":{"response_code":"200"}}],"should":[],"must_not":[]}}', + }, + query, + }, + ]); + }); + + test('returns global state filter when GLOBAL_STATE is specified', () => { + const actual = getFiltersForDSLQuery( + query, + 'dataview-id', + undefined, + FilterStateStore.GLOBAL_STATE + ); + expect(actual).toEqual([ + { + $state: { store: 'globalState' }, + meta: { + disabled: false, + index: 'dataview-id', + negate: false, + type: 'custom', + value: + '{"bool":{"must":[],"filter":[{"range":{"@timestamp":{"format":"strict_date_optional_time","gte":"2007-09-29T15:05:14.509Z","lte":"2022-09-29T15:05:14.509Z"}}},{"match_phrase":{"response_code":"200"}}],"should":[],"must_not":[]}}', + }, + query, + }, + ]); + }); + }); + + describe('isKnownEmptyQuery', () => { + test('returns true for default lens created query', () => { + const result = isKnownEmptyQuery({ + bool: { + filter: [], + must: [ + { + match_all: {}, + }, + ], + must_not: [], + }, + }); + expect(result).toBe(true); + }); + + test('returns true for default lens created query variation 1', () => { + const result = isKnownEmptyQuery({ + bool: { + must: [ + { + match_all: {}, + }, + ], + must_not: [], + }, + }); + expect(result).toBe(true); + }); + + test('returns true for default lens created query variation 2', () => { + const result = isKnownEmptyQuery({ + bool: { + must: [ + { + match_all: {}, + }, + ], + }, + }); + expect(result).toBe(true); + }); + + test('returns true for QA framework created query4', () => { + const result = isKnownEmptyQuery({ + match_all: {}, + }); + expect(result).toBe(true); + }); + + test('returns false for query with match_phrase', () => { + const result = isKnownEmptyQuery({ + match_phrase: { + region: 'us-east-1', + }, + }); + expect(result).toBe(false); + }); + + test('returns false for query with match_phrase in should', () => { + const result = isKnownEmptyQuery({ + bool: { + should: [ + { + match_phrase: { + region: 'us-east-1', + }, + }, + ], + minimum_should_match: 1, + }, + }); + expect(result).toBe(false); + }); + }); +}); diff --git a/x-pack/plugins/ml/common/util/job_utils.ts b/x-pack/plugins/ml/common/util/job_utils.ts index fc600afaa233a..51cdb7f7f1908 100644 --- a/x-pack/plugins/ml/common/util/job_utils.ts +++ b/x-pack/plugins/ml/common/util/job_utils.ts @@ -11,15 +11,25 @@ import moment, { Duration } from 'moment'; import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import numeral from '@elastic/numeral'; import { i18n } from '@kbn/i18n'; +import type { Filter } from '@kbn/es-query'; import { isPopulatedObject } from '@kbn/ml-is-populated-object'; +import type { SerializableRecord } from '@kbn/utility-types'; +import { FilterStateStore } from '@kbn/es-query'; +import type { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { ALLOWED_DATA_UNITS, JOB_ID_MAX_LENGTH } from '../constants/validation'; import { parseInterval } from './parse_interval'; import { maxLengthValidator } from './validators'; import { CREATED_BY_LABEL } from '../constants/new_job'; -import { CombinedJob, CustomSettings, Datafeed, Job, JobId } from '../types/anomaly_detection_jobs'; -import { EntityField } from './anomaly_utils'; -import { MlServerLimits } from '../types/ml_server_info'; -import { JobValidationMessage, JobValidationMessageId } from '../constants/messages'; +import type { + CombinedJob, + CustomSettings, + Datafeed, + Job, + JobId, +} from '../types/anomaly_detection_jobs'; +import type { EntityField } from './anomaly_utils'; +import type { MlServerLimits } from '../types/ml_server_info'; +import type { JobValidationMessage, JobValidationMessageId } from '../constants/messages'; import { ES_AGGREGATION, ML_JOB_AGGREGATION } from '../constants/aggregation_types'; import { MLCATEGORY } from '../constants/field_types'; import { getAggregations, getDatafeedAggregations } from './datafeed_utils'; @@ -866,3 +876,51 @@ export function resolveMaxTimeInterval(timeIntervals: string[]): number | undefi return Number.isFinite(result) ? result : undefined; } + +export function getFiltersForDSLQuery( + datafeedQuery: QueryDslQueryContainer, + dataViewId: string | undefined, + alias?: string, + store = FilterStateStore.APP_STATE +): Filter[] { + if (isKnownEmptyQuery(datafeedQuery)) { + return []; + } + + return [ + { + meta: { + ...(dataViewId !== undefined ? { index: dataViewId } : {}), + ...(alias !== undefined ? { alias } : {}), + negate: false, + disabled: false, + type: 'custom', + value: JSON.stringify(datafeedQuery), + }, + query: datafeedQuery as SerializableRecord, + $state: { + store, + }, + }, + ]; +} + +// check to see if the query is a known "empty" shape +export function isKnownEmptyQuery(query: QueryDslQueryContainer) { + const queries = [ + // the default query used by the job wizards + { bool: { must: [{ match_all: {} }] } }, + // the default query used created by lens created jobs + { bool: { filter: [], must: [{ match_all: {} }], must_not: [] } }, + // variations on the two previous queries + { bool: { filter: [], must: [{ match_all: {} }] } }, + { bool: { must: [{ match_all: {} }], must_not: [] } }, + // the query generated by QA Framework created jobs + { match_all: {} }, + ]; + if (queries.some((q) => isEqual(q, query))) { + return true; + } + + return false; +} diff --git a/x-pack/plugins/ml/public/application/app.tsx b/x-pack/plugins/ml/public/application/app.tsx index 1014b4e3a08b3..1ef553eae92f7 100644 --- a/x-pack/plugins/ml/public/application/app.tsx +++ b/x-pack/plugins/ml/public/application/app.tsx @@ -145,6 +145,7 @@ export const renderApp = ( maps: deps.maps, dataVisualizer: deps.dataVisualizer, dataViews: deps.data.dataViews, + share: deps.share, }); appMountParams.onAppLeave((actions) => actions.default()); diff --git a/x-pack/plugins/ml/public/application/components/anomalies_table/get_filters_for_datafeed_query.test.ts b/x-pack/plugins/ml/public/application/components/anomalies_table/get_filters_for_datafeed_query.test.ts deleted file mode 100644 index 20b52a773d032..0000000000000 --- a/x-pack/plugins/ml/public/application/components/anomalies_table/get_filters_for_datafeed_query.test.ts +++ /dev/null @@ -1,94 +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 { getFiltersForDSLQuery } from './get_filters_for_datafeed_query'; - -describe('getFiltersForDSLQuery', () => { - describe('when DSL query contains match_all', () => { - test('returns empty array when query contains a must clause that contains match_all', () => { - const actual = getFiltersForDSLQuery( - { bool: { must: [{ match_all: {} }] } }, - 'dataview-id', - 'test-alias' - ); - expect(actual).toEqual([]); - }); - - test('returns empty array when query contains match_all', () => { - const actual = getFiltersForDSLQuery({ match_all: {} }, 'dataview-id', 'test-alias'); - expect(actual).toEqual([]); - }); - }); - - describe('when DSL query is valid', () => { - const query = { - bool: { - must: [], - filter: [ - { - range: { - '@timestamp': { - format: 'strict_date_optional_time', - gte: '2007-09-29T15:05:14.509Z', - lte: '2022-09-29T15:05:14.509Z', - }, - }, - }, - { - match_phrase: { - response_code: '200', - }, - }, - ], - should: [], - must_not: [], - }, - }; - - test('returns filters with alias', () => { - const actual = getFiltersForDSLQuery(query, 'dataview-id', 'test-alias'); - expect(actual).toEqual([ - { - $state: { store: 'appState' }, - meta: { - alias: 'test-alias', - disabled: false, - index: 'dataview-id', - negate: false, - type: 'custom', - value: - '{"bool":{"must":[],"filter":[{"range":{"@timestamp":{"format":"strict_date_optional_time","gte":"2007-09-29T15:05:14.509Z","lte":"2022-09-29T15:05:14.509Z"}}},{"match_phrase":{"response_code":"200"}}],"should":[],"must_not":[]}}', - }, - query, - }, - ]); - }); - - test('returns empty array when dataViewId is invalid', () => { - const actual = getFiltersForDSLQuery(query, null, 'test-alias'); - expect(actual).toEqual([]); - }); - - test('returns filter with no alias if alias is not provided', () => { - const actual = getFiltersForDSLQuery(query, 'dataview-id'); - expect(actual).toEqual([ - { - $state: { store: 'appState' }, - meta: { - disabled: false, - index: 'dataview-id', - negate: false, - type: 'custom', - value: - '{"bool":{"must":[],"filter":[{"range":{"@timestamp":{"format":"strict_date_optional_time","gte":"2007-09-29T15:05:14.509Z","lte":"2022-09-29T15:05:14.509Z"}}},{"match_phrase":{"response_code":"200"}}],"should":[],"must_not":[]}}', - }, - query, - }, - ]); - }); - }); -}); diff --git a/x-pack/plugins/ml/public/application/components/anomalies_table/get_filters_for_datafeed_query.ts b/x-pack/plugins/ml/public/application/components/anomalies_table/get_filters_for_datafeed_query.ts deleted file mode 100644 index 08ff962449d2d..0000000000000 --- a/x-pack/plugins/ml/public/application/components/anomalies_table/get_filters_for_datafeed_query.ts +++ /dev/null @@ -1,45 +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 { isPopulatedObject } from '@kbn/ml-is-populated-object'; -import type { SerializableRecord } from '@kbn/utility-types'; -import { FilterStateStore } from '@kbn/es-query'; -import type { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; -import { isEqual } from 'lodash'; - -const defaultEmptyQuery = { bool: { must: [{ match_all: {} }] } }; - -export const getFiltersForDSLQuery = ( - datafeedQuery: QueryDslQueryContainer, - dataViewId: string | null, - alias?: string -) => { - if ( - datafeedQuery && - !isPopulatedObject(datafeedQuery, ['match_all']) && - !isEqual(datafeedQuery, defaultEmptyQuery) && - dataViewId !== null - ) { - return [ - { - meta: { - index: dataViewId, - ...(!!alias ? { alias } : {}), - negate: false, - disabled: false, - type: 'custom', - value: JSON.stringify(datafeedQuery), - }, - query: datafeedQuery as SerializableRecord, - $state: { - store: FilterStateStore.APP_STATE, - }, - }, - ]; - } - return []; -}; diff --git a/x-pack/plugins/ml/public/application/components/anomalies_table/links_menu.tsx b/x-pack/plugins/ml/public/application/components/anomalies_table/links_menu.tsx index 6ad828bc39661..fcc2a6abcba1f 100644 --- a/x-pack/plugins/ml/public/application/components/anomalies_table/links_menu.tsx +++ b/x-pack/plugins/ml/public/application/components/anomalies_table/links_menu.tsx @@ -53,7 +53,7 @@ import { useMlKibana } from '../../contexts/kibana'; import { getFieldTypeFromMapping } from '../../services/mapping_service'; import type { AnomaliesTableRecord } from '../../../../common/types/anomalies'; import { getQueryStringForInfluencers } from './get_query_string_for_influencers'; -import { getFiltersForDSLQuery } from './get_filters_for_datafeed_query'; +import { getFiltersForDSLQuery } from '../../../../common/util/job_utils'; interface LinksMenuProps { anomaly: AnomaliesTableRecord; bounds: TimeRangeBounds; @@ -112,7 +112,10 @@ export const LinksMenuUI = (props: LinksMenuProps) => { }, } : {}), - filters: getFiltersForDSLQuery(job.datafeed_config.query, dataViewId, job.job_id), + filters: + dataViewId === null + ? [] + : getFiltersForDSLQuery(job.datafeed_config.query, dataViewId, job.job_id), }); return location; }; @@ -150,11 +153,10 @@ export const LinksMenuUI = (props: LinksMenuProps) => { ); const locator = share.url.locators.get(MAPS_APP_LOCATOR); - const filtersFromDatafeedQuery = getFiltersForDSLQuery( - job.datafeed_config.query, - dataViewId, - job.job_id - ); + const filtersFromDatafeedQuery = + dataViewId === null + ? [] + : getFiltersForDSLQuery(job.datafeed_config.query, dataViewId, job.job_id); const location = await locator?.getLocation({ initialLayers, timeRange, @@ -265,7 +267,10 @@ export const LinksMenuUI = (props: LinksMenuProps) => { language: 'kuery', query: kqlQuery, }, - filters: getFiltersForDSLQuery(job.datafeed_config.query, dataViewId, job.job_id), + filters: + dataViewId === null + ? [] + : getFiltersForDSLQuery(job.datafeed_config.query, dataViewId, job.job_id), sort: [['timestamp, asc']], }); diff --git a/x-pack/plugins/ml/public/application/components/ml_entity_selector/index.ts b/x-pack/plugins/ml/public/application/components/ml_entity_selector/index.ts new file mode 100644 index 0000000000000..4caa8db2deb83 --- /dev/null +++ b/x-pack/plugins/ml/public/application/components/ml_entity_selector/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 { MlEntitySelector, type MlEntitySelectorProps } from './ml_entity_selector'; diff --git a/x-pack/plugins/ml/public/application/components/ml_entity_selector/ml_entity_selector.test.tsx b/x-pack/plugins/ml/public/application/components/ml_entity_selector/ml_entity_selector.test.tsx new file mode 100644 index 0000000000000..8ae78666f2afb --- /dev/null +++ b/x-pack/plugins/ml/public/application/components/ml_entity_selector/ml_entity_selector.test.tsx @@ -0,0 +1,210 @@ +/* + * 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 { render, waitFor, screen } from '@testing-library/react'; +import { MlEntitySelector } from './ml_entity_selector'; +import { useMlApiContext } from '../../contexts/kibana'; +import { MlApiServices } from '../../services/ml_api_service'; +import { useToastNotificationService } from '../../services/toast_notification_service'; + +jest.mock('../../contexts/kibana'); +jest.mock('../../services/toast_notification_service'); + +describe('MlEntitySelector', () => { + const getAllJobAndGroupIds = jest.fn(() => { + return Promise.resolve({ jobIds: ['ad_01', 'ad_02'] }); + }); + + const getDataFrameAnalytics = jest.fn(() => { + return Promise.resolve({ + count: 2, + data_frame_analytics: [{ id: 'dfa_01' }, { id: 'dfa_02' }], + }); + }); + + const getTrainedModels = jest.fn(() => { + return Promise.resolve([{ model_id: 'model_01' }]); + }); + + (useMlApiContext as jest.MockedFunction).mockImplementation(() => { + return { + jobs: { + getAllJobAndGroupIds, + }, + dataFrameAnalytics: { + getDataFrameAnalytics, + }, + trainedModels: { + getTrainedModels, + }, + } as unknown as jest.Mocked; + }); + + beforeEach(() => {}); + + afterEach(() => { + jest.clearAllMocks(); + }); + + test('fetches all available options on mount by default', async () => { + const { getByTestId } = render(); + + await waitFor(() => { + expect(getByTestId('mlEntitySelector_loaded')).toBeInTheDocument(); + }); + + expect(getTrainedModels).toHaveBeenCalledTimes(1); + expect(getAllJobAndGroupIds).toHaveBeenCalledTimes(1); + expect(getDataFrameAnalytics).toHaveBeenCalledTimes(1); + }); + + test('fetches requested entity types on mount', async () => { + const { getByTestId } = render(); + + await waitFor(() => { + expect(getByTestId('mlEntitySelector_loaded')).toBeInTheDocument(); + }); + + expect(getTrainedModels).not.toHaveBeenCalled(); + expect(getDataFrameAnalytics).not.toHaveBeenCalled(); + expect(getAllJobAndGroupIds).toHaveBeenCalledTimes(1); + }); + + test('marks selected entities', async () => { + const { getByTestId } = render( + + ); + + await waitFor(() => { + expect(getByTestId('mlEntitySelector_loaded')).toBeInTheDocument(); + }); + + // Assert available options to select + const optionsContainer = await screen.findByTestId( + 'comboBoxOptionsList mlEntitySelector_loaded-optionsList' + ); + const optionElements = optionsContainer.querySelectorAll('[data-test-subj="mlAdJobOption"]'); + expect(optionElements).toHaveLength(1); + expect(optionElements[0]).toHaveAttribute('id', 'anomaly_detector:ad_02'); + expect(optionsContainer.querySelectorAll('[data-test-subj="mlDfaJobOption"]')).toHaveLength(2); + expect( + optionsContainer.querySelectorAll('[data-test-subj="mlTrainedModelOption"]') + ).toHaveLength(1); + + // Assert selected + const comboBoxInput = getByTestId('comboBoxInput'); + expect(comboBoxInput.querySelectorAll('[data-test-subj="mlAdJobOption"]')).toHaveLength(1); + }); + + test('provide current selection update on change', async () => { + const onChangeSpy = jest.fn(); + + const { getByTestId } = render( + + ); + + await waitFor(() => { + expect(getByTestId('mlEntitySelector_loaded')).toBeInTheDocument(); + }); + + // Assert available options to select + const optionsContainer = await screen.findByTestId( + 'comboBoxOptionsList mlEntitySelector_loaded-optionsList' + ); + + optionsContainer + .querySelector('[id="data_frame_analytics:dfa_01"]')! + .click(); + + expect(onChangeSpy).toHaveBeenCalledWith([ + { id: 'ad_01', type: 'anomaly_detector' }, + { id: 'dfa_01', type: 'data_frame_analytics' }, + ]); + }); + + test('provide current selection update on change with duplicates handling', async () => { + (useMlApiContext as jest.MockedFunction).mockImplementationOnce(() => { + return { + jobs: { + getAllJobAndGroupIds, + }, + dataFrameAnalytics: { + getDataFrameAnalytics: jest.fn(() => { + return Promise.resolve({ + count: 2, + // same ID as the anomaly detection job + data_frame_analytics: [{ id: 'ad_01' }, { id: 'dfa_02' }], + }); + }), + }, + trainedModels: { + getTrainedModels, + }, + } as unknown as jest.Mocked; + }); + + const onChangeSpy = jest.fn(); + + const { getByTestId } = render( + + ); + + await waitFor(() => { + expect(getByTestId('mlEntitySelector_loaded')).toBeInTheDocument(); + }); + + // Assert selected + const comboBoxInput = getByTestId('comboBoxInput'); + const selectedOptions = comboBoxInput.querySelectorAll('.euiComboBoxPill'); + expect(selectedOptions).toHaveLength(3); + expect(selectedOptions[0]).toHaveAttribute('id', 'anomaly_detector:ad_01'); + expect(selectedOptions[1]).toHaveAttribute('id', 'data_frame_analytics:ad_01'); + + // Assert removal + selectedOptions[0].getElementsByTagName('button')[0].click(); + expect(onChangeSpy).toHaveBeenCalledWith([{ id: 'keep_it', type: 'unknown' }]); + }); + + test('display a toast on error', async () => { + const displayErrorToast = jest.fn(); + const sampleError = new Error('try a bit later'); + + (useMlApiContext as jest.MockedFunction).mockImplementationOnce(() => { + return { + jobs: { + getAllJobAndGroupIds: jest.fn(() => { + throw sampleError; + }), + }, + } as unknown as jest.Mocked; + }); + ( + useToastNotificationService as jest.MockedFunction + ).mockImplementationOnce(() => { + return { displayErrorToast } as unknown as ReturnType; + }); + + const { getByTestId } = render( + + ); + + await waitFor(() => { + expect(getByTestId('mlEntitySelector_loaded')).toBeInTheDocument(); + }); + + expect(displayErrorToast).toHaveBeenCalledTimes(1); + expect(displayErrorToast).toHaveBeenCalledWith(sampleError, 'Failed to fetch ML entities'); + }); +}); diff --git a/x-pack/plugins/ml/public/application/components/ml_entity_selector/ml_entity_selector.tsx b/x-pack/plugins/ml/public/application/components/ml_entity_selector/ml_entity_selector.tsx new file mode 100644 index 0000000000000..c31d091fdf67c --- /dev/null +++ b/x-pack/plugins/ml/public/application/components/ml_entity_selector/ml_entity_selector.tsx @@ -0,0 +1,212 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { FC, useCallback, useState, useMemo } from 'react'; +import { + EuiComboBox, + type EuiComboBoxOptionOption, + type EuiComboBoxProps, + euiPaletteColorBlindBehindText, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { countBy } from 'lodash'; +import useMount from 'react-use/lib/useMount'; +import { useMlApiContext } from '../../contexts/kibana'; +import { useToastNotificationService } from '../../services/toast_notification_service'; + +type EntityType = 'anomaly_detector' | 'data_frame_analytics' | 'trained_models'; + +type EntitiesSelection = Array<{ id: string; type: EntityType }>; + +export interface MlEntitySelectorProps { + entityTypes?: Partial<{ [key in EntityType]: boolean }>; + multiSelect?: boolean; + /** + * Array of selected ids + */ + selectedOptions?: Array<{ id: string; type?: EntityType }>; + onSelectionChange?: (jobSelection: EntitiesSelection) => void; + /** + * In case the there are duplicated IDs across different ML entity types, + * they should be de-selected simultaneously if this setting is enabled. + */ + handleDuplicates?: boolean; +} + +const defaultEntities = { + anomaly_detector: true, + data_frame_analytics: true, + trained_models: true, +}; + +/** + * Reusable component for picking ML entities. + * + * @param entityTypes + * @param multiSelect + * @param selectedOptions + * @param onSelectionChange + * @param handleDuplicates + * @constructor + */ +export const MlEntitySelector: FC = ({ + entityTypes = defaultEntities, + multiSelect = true, + selectedOptions, + onSelectionChange, + handleDuplicates = false, +}) => { + const { jobs: jobsApi, trainedModels, dataFrameAnalytics } = useMlApiContext(); + const { displayErrorToast } = useToastNotificationService(); + const visColorsBehindText = euiPaletteColorBlindBehindText(); + + const [isLoading, setIsLoading] = useState(true); + const [options, setOptions] = useState>>([]); + + const fetchOptions = useCallback(async () => { + try { + const newOptions: Array> = []; + if (entityTypes?.anomaly_detector) { + const { jobIds: jobIdOptions } = await jobsApi.getAllJobAndGroupIds(); + + newOptions.push({ + label: i18n.translate('xpack.ml.mlEntitySelector.adOptionsLabel', { + defaultMessage: 'Anomaly detection jobs', + }), + isGroupLabelOption: true, + color: visColorsBehindText[0], + options: jobIdOptions.map((adId) => ({ + label: adId, + value: adId, + id: `anomaly_detector:${adId}`, + key: `anomaly_detector:${adId}`, + color: visColorsBehindText[0], + 'data-test-subj': `mlAdJobOption`, + })), + }); + } + + if (entityTypes?.data_frame_analytics) { + const dfa = await dataFrameAnalytics.getDataFrameAnalytics(); + if (dfa.count > 0) { + newOptions.push({ + label: i18n.translate('xpack.ml.mlEntitySelector.dfaOptionsLabel', { + defaultMessage: 'Data frame analytics', + }), + isGroupLabelOption: true, + options: dfa.data_frame_analytics.map(({ id: dfaId }) => ({ + label: dfaId, + value: dfaId, + id: `data_frame_analytics:${dfaId}`, + key: `data_frame_analytics:${dfaId}`, + color: visColorsBehindText[2], + 'data-test-subj': `mlDfaJobOption`, + })), + }); + } + } + + if (entityTypes?.trained_models) { + const models = await trainedModels.getTrainedModels(); + if (models.length > 0) { + newOptions.push({ + label: i18n.translate('xpack.ml.mlEntitySelector.trainedModelsLabel', { + defaultMessage: 'Trained models', + }), + isGroupLabelOption: true, + options: models.map(({ model_id: modelId }) => ({ + label: modelId, + value: modelId, + id: `trained_models:${modelId}`, + key: `trained_models:${modelId}`, + color: visColorsBehindText[3], + 'data-test-subj': `mlTrainedModelOption`, + })), + }); + } + } + + setOptions(newOptions); + } catch (error) { + displayErrorToast( + error, + i18n.translate('xpack.ml.mlEntitySelector.fetchError', { + defaultMessage: 'Failed to fetch ML entities', + }) + ); + } + setIsLoading(false); + }, [ + jobsApi, + trainedModels, + dataFrameAnalytics, + entityTypes, + visColorsBehindText, + displayErrorToast, + ]); + + useMount(function fetchOptionsOnMount() { + fetchOptions(); + }); + + const selectedEntities = useMemo>>(() => { + return (selectedOptions ?? []).flatMap((o) => { + const fromOptions = options + .flatMap((g) => g.options) + .filter((op): op is EuiComboBoxOptionOption => op!.value === o.id); + return fromOptions.length > 0 + ? fromOptions + : [ + { + value: o.id, + label: o.id, + key: `unknown:${o.id}`, + 'data-test-subj': `mlUnknownOption ${o.id}`, + }, + ]; + }); + }, [options, selectedOptions]); + + const onChange = useCallback['onChange'], undefined>>( + (selection) => { + if (!onSelectionChange) return; + + let resultSelection = selection; + + if (handleDuplicates) { + const prevCounts = countBy(selectedEntities, 'value'); + const currentCounts = countBy(selection, 'value'); + resultSelection = resultSelection.filter(({ value }) => { + // If an ID with duplicates has been removed, delete all of them. + return !(prevCounts[value!] > 1 && currentCounts[value!] < prevCounts[value!]); + }); + } + + onSelectionChange( + resultSelection.map((s) => { + const [type] = s.key!.split(':'); + return { id: s.value!, type: type as EntityType }; + }) + ); + }, + [onSelectionChange, selectedEntities, handleDuplicates] + ); + + return ( + + autoFocus={true} + isLoading={isLoading} + singleSelection={!multiSelect} + selectedOptions={selectedEntities} + options={options} + onChange={onChange} + fullWidth + data-test-subj={`mlEntitySelector_${isLoading ? 'loading' : 'loaded'}`} + isInvalid={false} + /> + ); +}; diff --git a/x-pack/plugins/ml/public/application/components/ml_page/side_nav.tsx b/x-pack/plugins/ml/public/application/components/ml_page/side_nav.tsx index 4dbc2400aa7cf..6959f5cf17a53 100644 --- a/x-pack/plugins/ml/public/application/components/ml_page/side_nav.tsx +++ b/x-pack/plugins/ml/public/application/components/ml_page/side_nav.tsx @@ -84,7 +84,13 @@ export function useSideNavItems(activeRoute: MlRoute | undefined) { { id: 'notifications', pathId: ML_PAGES.NOTIFICATIONS, - name: , + name: disableLinks ? ( + i18n.translate('xpack.ml.navMenu.notificationsTabLinkText', { + defaultMessage: 'Notifications', + }) + ) : ( + + ), disabled: disableLinks, testSubj: 'mlMainTab notifications', }, diff --git a/x-pack/plugins/ml/public/application/components/saved_objects_warning/__mocks__/index.ts b/x-pack/plugins/ml/public/application/components/saved_objects_warning/__mocks__/index.ts new file mode 100644 index 0000000000000..f7f39c66ae293 --- /dev/null +++ b/x-pack/plugins/ml/public/application/components/saved_objects_warning/__mocks__/index.ts @@ -0,0 +1,10 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export const SavedObjectsWarning = jest.fn(() => { + return null; +}); diff --git a/x-pack/plugins/ml/public/application/contexts/kibana/__mocks__/index.ts b/x-pack/plugins/ml/public/application/contexts/kibana/__mocks__/index.ts index df9e3c12c69d7..65ce9c9288d4e 100644 --- a/x-pack/plugins/ml/public/application/contexts/kibana/__mocks__/index.ts +++ b/x-pack/plugins/ml/public/application/contexts/kibana/__mocks__/index.ts @@ -7,3 +7,4 @@ export { useMlKibana } from './kibana_context'; export { useTimefilter } from './use_timefilter'; +export { useMlApiContext } from './use_ml_api_context'; diff --git a/x-pack/plugins/ml/public/application/contexts/kibana/__mocks__/kibana_context.ts b/x-pack/plugins/ml/public/application/contexts/kibana/__mocks__/kibana_context.ts index fb9b48f218b7c..fe71841719639 100644 --- a/x-pack/plugins/ml/public/application/contexts/kibana/__mocks__/kibana_context.ts +++ b/x-pack/plugins/ml/public/application/contexts/kibana/__mocks__/kibana_context.ts @@ -6,7 +6,9 @@ */ import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; +import { fieldFormatsServiceMock } from '@kbn/field-formats-plugin/public/mocks'; import { BehaviorSubject } from 'rxjs'; +import { mlApiServicesMock } from '../../../services/__mocks__/ml_api_services'; export const chartsServiceMock = { theme: { @@ -30,6 +32,7 @@ export const chartsServiceMock = { }), }, }; + export const kibanaContextMock = { services: { uiSettings: { get: jest.fn() }, @@ -45,6 +48,10 @@ export const kibanaContextMock = { }, data: dataPluginMock.createStartContract(), charts: chartsServiceMock, + fieldFormats: fieldFormatsServiceMock.createStartContract(), + mlServices: { + mlApiServices: mlApiServicesMock, + }, }, }; diff --git a/x-pack/plugins/ml/public/application/contexts/kibana/__mocks__/use_field_formatter.ts b/x-pack/plugins/ml/public/application/contexts/kibana/__mocks__/use_field_formatter.ts new file mode 100644 index 0000000000000..83ff20394b6bc --- /dev/null +++ b/x-pack/plugins/ml/public/application/contexts/kibana/__mocks__/use_field_formatter.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +jest.mock('./kibana_context'); + +export const useFieldFormatter = jest.fn(); diff --git a/x-pack/plugins/ml/public/application/contexts/kibana/__mocks__/use_ml_api_context.ts b/x-pack/plugins/ml/public/application/contexts/kibana/__mocks__/use_ml_api_context.ts new file mode 100644 index 0000000000000..a690cd0d26384 --- /dev/null +++ b/x-pack/plugins/ml/public/application/contexts/kibana/__mocks__/use_ml_api_context.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 { MlApiServices } from '../../../services/ml_api_service'; + +export const useMlApiContext: () => jest.Mocked = jest.fn(() => { + return { + jobs: { + getAllJobAndGroupIds: jest.fn(), + }, + trainedModels: { + getTrainedModels: jest.fn(), + }, + dataFrameAnalytics: { + getDataFrameAnalytics: jest.fn(), + }, + } as unknown as jest.Mocked; +}); diff --git a/x-pack/plugins/ml/public/application/contexts/kibana/__mocks__/use_timefilter.ts b/x-pack/plugins/ml/public/application/contexts/kibana/__mocks__/use_timefilter.ts index b53137aec1838..f302de4fb1ae9 100644 --- a/x-pack/plugins/ml/public/application/contexts/kibana/__mocks__/use_timefilter.ts +++ b/x-pack/plugins/ml/public/application/contexts/kibana/__mocks__/use_timefilter.ts @@ -8,6 +8,8 @@ import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; import { TimefilterContract } from '@kbn/data-plugin/public'; +jest.mock('./kibana_context'); + export const timefilterMock = dataPluginMock.createStartContract().query.timefilter .timefilter as jest.Mocked; diff --git a/x-pack/plugins/ml/public/application/contexts/kibana/index.ts b/x-pack/plugins/ml/public/application/contexts/kibana/index.ts index 0873d395f0b79..5db1956cd8400 100644 --- a/x-pack/plugins/ml/public/application/contexts/kibana/index.ts +++ b/x-pack/plugins/ml/public/application/contexts/kibana/index.ts @@ -14,3 +14,4 @@ export { useTimefilter } from './use_timefilter'; export { useNotifications } from './use_notifications_context'; export { useMlLocator, useMlLink } from './use_create_url'; export { useMlApiContext } from './use_ml_api_context'; +export { useFieldFormatter } from './use_field_formatter'; diff --git a/x-pack/plugins/ml/public/application/contexts/ml/__mocks__/ml_notifications_context.tsx b/x-pack/plugins/ml/public/application/contexts/ml/__mocks__/ml_notifications_context.tsx new file mode 100644 index 0000000000000..d7d7c36178228 --- /dev/null +++ b/x-pack/plugins/ml/public/application/contexts/ml/__mocks__/ml_notifications_context.tsx @@ -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. + */ + +export const useMlNotifications = jest.fn(() => { + return { + lastCheckedAt: undefined, + setLastCheckedAt: jest.fn(), + notificationsCounts: { info: 0, error: 0, warning: 0 }, + latestRequestedAt: null, + }; +}); diff --git a/x-pack/plugins/ml/public/application/contexts/ml/ml_notifications_context.test.tsx b/x-pack/plugins/ml/public/application/contexts/ml/ml_notifications_context.test.tsx index 4076966942cd8..eceec43ecfcd5 100644 --- a/x-pack/plugins/ml/public/application/contexts/ml/ml_notifications_context.test.tsx +++ b/x-pack/plugins/ml/public/application/contexts/ml/ml_notifications_context.test.tsx @@ -6,28 +6,40 @@ */ import { renderHook, act } from '@testing-library/react-hooks'; -import { of } from 'rxjs'; +import { of, throwError } from 'rxjs'; import { useMlNotifications, MlNotificationsContextProvider } from './ml_notifications_context'; import { useStorage } from '../storage'; +import { useMlKibana } from '../kibana'; const mockCountMessages = jest.fn(() => { return of({ info: 1, error: 0, warning: 0 }); }); -jest.mock('../kibana', () => ({ - useMlKibana: () => { - return { - services: { - mlServices: { - mlApiServices: { - notifications: { - countMessages$: mockCountMessages, - }, - }, +const mockKibana = { + services: { + mlServices: { + mlApiServices: { + notifications: { + countMessages$: mockCountMessages, }, }, - }; + }, + application: { + capabilities: { + ml: { + canGetJobs: true, + canGetDataFrameAnalytics: true, + canGetTrainedModels: true, + }, + }, + }, }, +}; + +jest.mock('../kibana', () => ({ + useMlKibana: jest.fn(() => { + return mockKibana; + }), })); const mockSetStorageValue = jest.fn(); @@ -39,6 +51,11 @@ jest.mock('../storage', () => ({ describe('useMlNotifications', () => { beforeEach(() => { + // Set mocks to the default values + (useMlKibana as jest.MockedFunction).mockReturnValue( + mockKibana as unknown as ReturnType + ); + jest.useFakeTimers('modern'); jest.setSystemTime(1663945337063); }); @@ -49,6 +66,39 @@ describe('useMlNotifications', () => { jest.useRealTimers(); }); + test('retries polling on error with 1m delay', () => { + mockKibana.services.mlServices.mlApiServices.notifications.countMessages$.mockReturnValueOnce( + throwError(() => new Error('Cluster is down')) + ); + + renderHook(useMlNotifications, { + wrapper: MlNotificationsContextProvider, + }); + + act(() => { + jest.advanceTimersByTime(0); + }); + + expect( + mockKibana.services.mlServices.mlApiServices.notifications.countMessages$ + ).toHaveBeenCalledTimes(1); + expect( + mockKibana.services.mlServices.mlApiServices.notifications.countMessages$ + ).toHaveBeenCalledWith({ lastCheckedAt: 1663340537063 }); + + act(() => { + // ticks 4 minutes + jest.advanceTimersByTime(60000 * 4); + }); + + expect( + mockKibana.services.mlServices.mlApiServices.notifications.countMessages$ + ).toHaveBeenCalledTimes(4); + expect( + mockKibana.services.mlServices.mlApiServices.notifications.countMessages$ + ).toHaveBeenCalledWith({ lastCheckedAt: 1663340537063 }); + }); + test('returns the default values', () => { const { result } = renderHook(useMlNotifications, { wrapper: MlNotificationsContextProvider }); expect(result.current.notificationsCounts).toEqual({ info: 0, error: 0, warning: 0 }); @@ -56,6 +106,27 @@ describe('useMlNotifications', () => { expect(result.current.lastCheckedAt).toEqual(undefined); }); + test('starts only one subscription on mount', () => { + const { rerender } = renderHook(useMlNotifications, { + wrapper: MlNotificationsContextProvider, + }); + + act(() => { + jest.advanceTimersByTime(0); + }); + + expect(mockCountMessages).toHaveBeenCalledTimes(1); + + rerender(); + rerender(); + + act(() => { + jest.advanceTimersByTime(10000); + }); + + expect(mockCountMessages).toHaveBeenCalledTimes(1); + }); + test('starts polling for notifications with a 1 minute interval during the last week by default ', () => { const { result } = renderHook(useMlNotifications, { wrapper: MlNotificationsContextProvider, @@ -137,4 +208,24 @@ describe('useMlNotifications', () => { expect(result.current.latestRequestedAt).toEqual(1664551009292); expect(result.current.lastCheckedAt).toEqual(1664551009292); }); + + test('does not start polling if requires capabilities are missing', () => { + mockKibana.services.application.capabilities.ml = { + canGetJobs: true, + canGetDataFrameAnalytics: false, + canGetTrainedModels: true, + }; + + renderHook(useMlNotifications, { + wrapper: MlNotificationsContextProvider, + }); + + act(() => { + jest.advanceTimersByTime(0); + }); + + expect( + mockKibana.services.mlServices.mlApiServices.notifications.countMessages$ + ).not.toHaveBeenCalled(); + }); }); diff --git a/x-pack/plugins/ml/public/application/contexts/ml/ml_notifications_context.tsx b/x-pack/plugins/ml/public/application/contexts/ml/ml_notifications_context.tsx index fef04e9366671..71fbcdbb27cdc 100644 --- a/x-pack/plugins/ml/public/application/contexts/ml/ml_notifications_context.tsx +++ b/x-pack/plugins/ml/public/application/contexts/ml/ml_notifications_context.tsx @@ -5,10 +5,12 @@ * 2.0. */ -import React, { FC, useContext, useEffect, useState } from 'react'; -import { combineLatest, of, timer } from 'rxjs'; -import { catchError, switchMap, map, tap } from 'rxjs/operators'; +import React, { FC, useContext, useState } from 'react'; +import { combineLatest, timer } from 'rxjs'; +import { switchMap, map, tap, retry } from 'rxjs/operators'; import moment from 'moment'; +import { isPopulatedObject } from '@kbn/ml-is-populated-object'; +import useMount from 'react-use/lib/useMount'; import { useMlKibana } from '../kibana'; import { useStorage } from '../storage'; import { ML_NOTIFICATIONS_LAST_CHECKED_AT } from '../../../../common/types/storage'; @@ -17,6 +19,8 @@ import type { NotificationsCountResponse } from '../../../../common/types/notifi const NOTIFICATIONS_CHECK_INTERVAL = 60000; +const defaultCounts = { info: 0, error: 0, warning: 0 }; + export const MlNotificationsContext = React.createContext<{ notificationsCounts: NotificationsCountResponse; /** Timestamp of the latest notification checked by the user */ @@ -25,7 +29,7 @@ export const MlNotificationsContext = React.createContext<{ latestRequestedAt: number | null; setLastCheckedAt: (v: number) => void; }>({ - notificationsCounts: { info: 0, error: 0, warning: 0 }, + notificationsCounts: defaultCounts, lastCheckedAt: null, latestRequestedAt: null, setLastCheckedAt: () => {}, @@ -35,21 +39,26 @@ export const MlNotificationsContextProvider: FC = ({ children }) => { const { services: { mlServices: { mlApiServices }, + application: { capabilities }, }, } = useMlKibana(); + const canGetJobs = capabilities.ml.canGetJobs as boolean; + const canGetDataFrameAnalytics = capabilities.ml.canGetDataFrameAnalytics as boolean; + const canGetTrainedModels = capabilities.ml.canGetTrainedModels as boolean; + + const canGetNotifications = canGetJobs && canGetDataFrameAnalytics && canGetTrainedModels; const [lastCheckedAt, setLastCheckedAt] = useStorage(ML_NOTIFICATIONS_LAST_CHECKED_AT); const lastCheckedAt$ = useAsObservable(lastCheckedAt); /** Holds the value used for the actual request */ const [latestRequestedAt, setLatestRequestedAt] = useState(null); - const [notificationsCounts, setNotificationsCounts] = useState({ - info: 0, - error: 0, - warning: 0, - }); + const [notificationsCounts, setNotificationsCounts] = + useState(defaultCounts); + + useMount(function startPollingNotifications() { + if (!canGetNotifications) return; - useEffect(function startPollingNotifications() { const subscription = combineLatest([lastCheckedAt$, timer(0, NOTIFICATIONS_CHECK_INTERVAL)]) .pipe( // Use the latest check time or 7 days ago by default. @@ -62,20 +71,16 @@ export const MlNotificationsContextProvider: FC = ({ children }) => { lastCheckedAt: lastCheckedAtQuery, }) ), - catchError((error) => { - // Fail silently for now - return of({} as NotificationsCountResponse); - }) + retry({ delay: NOTIFICATIONS_CHECK_INTERVAL }) ) .subscribe((response) => { - setNotificationsCounts(response); + setNotificationsCounts(isPopulatedObject(response) ? response : defaultCounts); }); return () => { subscription.unsubscribe(); }; - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); + }); return ( { + afterEach(() => { + jest.clearAllMocks(); + }); + + test('provides and observable preserving a reference', () => { + const { result, rerender } = renderHook(useAsObservable, { initialProps: 1 }); + + let observableValue; + const subscriptionMock = jest.fn((v) => (observableValue = v)); + + result.current.subscribe(subscriptionMock); + + expect(subscriptionMock).toHaveBeenCalledWith(1); + expect(subscriptionMock).toHaveBeenCalledTimes(1); + expect(observableValue).toEqual(1); + + act(() => rerender(1)); + + expect(result.all[0]).toStrictEqual(result.all[1]); + + expect(subscriptionMock).toHaveBeenCalledWith(1); + expect(subscriptionMock).toHaveBeenCalledTimes(1); + expect(observableValue).toEqual(1); + }); + + test('updates the subject with a new value', async () => { + const { result, rerender, waitForNextUpdate } = renderHook(useAsObservable, { + initialProps: 'test', + }); + + let observableValue; + const subscriptionMock = jest.fn((v) => { + observableValue = v; + }); + result.current.subscribe(subscriptionMock); + + expect(subscriptionMock).toHaveBeenCalledWith('test'); + expect(observableValue).toEqual('test'); + + await act(async () => { + rerender('test update'); + await waitForNextUpdate(); + }); + + expect(subscriptionMock).toHaveBeenCalledTimes(2); + expect(subscriptionMock).toHaveBeenCalledWith('test update'); + expect(observableValue).toEqual('test update'); + }); +}); diff --git a/x-pack/plugins/ml/public/application/hooks/use_as_observable.ts b/x-pack/plugins/ml/public/application/hooks/use_as_observable.ts index 986b8387f0b37..534790cc2508d 100644 --- a/x-pack/plugins/ml/public/application/hooks/use_as_observable.ts +++ b/x-pack/plugins/ml/public/application/hooks/use_as_observable.ts @@ -6,7 +6,7 @@ */ import { useMemo, useEffect } from 'react'; -import { BehaviorSubject, Observable } from 'rxjs'; +import { BehaviorSubject, type Observable } from 'rxjs'; /** * Provides an observable based on the input @@ -25,5 +25,5 @@ export function useAsObservable(value: T): Observable { [subject, value] ); - return subject.asObservable(); + return useMemo(() => subject.asObservable(), [subject]); } diff --git a/x-pack/plugins/ml/public/application/jobs/components/custom_url_editor/utils.js b/x-pack/plugins/ml/public/application/jobs/components/custom_url_editor/utils.js index 9c2fa8383b7a5..1c61985dfe951 100644 --- a/x-pack/plugins/ml/public/application/jobs/components/custom_url_editor/utils.js +++ b/x-pack/plugins/ml/public/application/jobs/components/custom_url_editor/utils.js @@ -10,7 +10,10 @@ import { TIME_RANGE_TYPE, URL_TYPE } from './constants'; import rison from 'rison-node'; import url from 'url'; -import { getPartitioningFieldNames } from '../../../../../common/util/job_utils'; +import { + getPartitioningFieldNames, + getFiltersForDSLQuery, +} from '../../../../../common/util/job_utils'; import { parseInterval } from '../../../../../common/util/parse_interval'; import { replaceTokensInUrlValue, isValidLabel } from '../../../util/custom_url_utils'; import { ml } from '../../../services/ml_api_service'; @@ -20,7 +23,6 @@ import { getSavedObjectsClient, getDashboard } from '../../../util/dependency_ca import { setStateToKbnUrl } from '@kbn/kibana-utils-plugin/public'; import { cleanEmptyKeys } from '@kbn/dashboard-plugin/public'; import { isFilterPinned } from '@kbn/es-query'; -import { getFiltersForDSLQuery } from '../../../components/anomalies_table/get_filters_for_datafeed_query'; export function getNewCustomUrlDefaults(job, dashboards, dataViews) { // Returns the settings object in the format used by the custom URL editor @@ -51,11 +53,10 @@ export function getNewCustomUrlDefaults(job, dashboards, dataViews) { const indicesName = datafeedConfig.indices.join(); const defaultDataViewId = dataViews.find((dv) => dv.title === indicesName)?.id; kibanaSettings.discoverIndexPatternId = defaultDataViewId; - kibanaSettings.filters = getFiltersForDSLQuery( - job.datafeed_config.query, - defaultDataViewId, - job.job_id - ); + kibanaSettings.filters = + defaultDataViewId === null + ? [] + : getFiltersForDSLQuery(job.datafeed_config.query, defaultDataViewId, job.job_id); } return { diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/quick_create_job.ts b/x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/quick_create_job.ts index a9585fe617365..4faf650e5aca1 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/quick_create_job.ts +++ b/x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/quick_create_job.ts @@ -5,18 +5,21 @@ * 2.0. */ +import { i18n } from '@kbn/i18n'; import { mergeWith, uniqBy, isEqual } from 'lodash'; import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; -import type { Embeddable } from '@kbn/lens-plugin/public'; +import type { + Embeddable, + LensSavedObjectAttributes, + XYDataLayerConfig, +} from '@kbn/lens-plugin/public'; import type { IUiSettingsClient } from '@kbn/core/public'; import type { DataViewsContract } from '@kbn/data-views-plugin/public'; import type { TimefilterContract } from '@kbn/data-plugin/public'; - -import { Filter, Query, DataViewBase } from '@kbn/es-query'; - -import type { LensSavedObjectAttributes, XYDataLayerConfig } from '@kbn/lens-plugin/public'; - -import { i18n } from '@kbn/i18n'; +import type { SharePluginStart } from '@kbn/share-plugin/public'; +import type { DashboardAppLocatorParams } from '@kbn/dashboard-plugin/public'; +import type { Filter, Query, DataViewBase } from '@kbn/es-query'; +import { FilterStateStore } from '@kbn/es-query'; import type { JobCreatorType } from '../common/job_creator'; import { createEmptyJob, createEmptyDatafeed } from '../common/job_creator/util/default_configs'; @@ -24,6 +27,7 @@ import { stashJobForCloning } from '../common/job_creator/util/general'; import type { ErrorType } from '../../../../../common/util/errors'; import { createDatafeedId } from '../../../../../common/util/job_utils'; import type { MlApiServices } from '../../../services/ml_api_service'; +import { getFiltersForDSLQuery } from '../../../../../common/util/job_utils'; import { CREATED_BY_LABEL, DEFAULT_BUCKET_SPAN, @@ -33,6 +37,8 @@ import { createQueries } from '../utils/new_job_utils'; import { isCompatibleLayer, createDetectors, getJobsItemsFromEmbeddable } from './utils'; import { VisualizationExtractor } from './visualization_extractor'; +type Dashboard = Embeddable['parent']; + interface CreationState { success: boolean; error?: ErrorType; @@ -47,10 +53,11 @@ interface CreateState { export class QuickJobCreator { constructor( - private dataViewClient: DataViewsContract, - private kibanaConfig: IUiSettingsClient, - private timeFilter: TimefilterContract, - private mlApiServices: MlApiServices + private readonly dataViewClient: DataViewsContract, + private readonly kibanaConfig: IUiSettingsClient, + private readonly timeFilter: TimefilterContract, + private readonly share: SharePluginStart, + private readonly mlApiServices: MlApiServices ) {} public async createAndSaveJob( @@ -61,7 +68,7 @@ export class QuickJobCreator { runInRealTime: boolean, layerIndex: number ): Promise { - const { query, filters, to, from, vis } = getJobsItemsFromEmbeddable(embeddable); + const { query, filters, to, from, vis, dashboard } = getJobsItemsFromEmbeddable(embeddable); if (query === undefined || filters === undefined) { throw new Error('Cannot create job, query and filters are undefined'); } @@ -73,10 +80,13 @@ export class QuickJobCreator { query, filters, bucketSpan, - layerIndex ); - const job = { + + const datafeedId = createDatafeedId(jobId); + const datafeed = { ...datafeedConfig, job_id: jobId, datafeed_id: datafeedId }; + + const job: estypes.MlJob = { ...jobConfig, job_id: jobId, custom_settings: { @@ -84,12 +94,10 @@ export class QuickJobCreator { jobType === JOB_TYPE.SINGLE_METRIC ? CREATED_BY_LABEL.SINGLE_METRIC_FROM_LENS : CREATED_BY_LABEL.MULTI_METRIC_FROM_LENS, + ...(await this.getCustomUrls(dashboard, datafeed)), }, }; - const datafeedId = createDatafeedId(jobId); - const datafeed = { ...datafeedConfig, job_id: jobId, datafeed_id: datafeedId }; - const result: CreateState = { jobCreated: { success: false }, datafeedCreated: { success: false }, @@ -330,4 +338,49 @@ export class QuickJobCreator { return mergedQueries; } + + private async createDashboardLink(dashboard: Dashboard, datafeedConfig: estypes.MlDatafeed) { + if (dashboard === undefined) { + // embeddable may have not been in a dashboard + return null; + } + + const params: DashboardAppLocatorParams = { + dashboardId: dashboard.id, + timeRange: { + from: '$earliest$', + to: '$latest$', + mode: 'absolute', + }, + filters: getFiltersForDSLQuery( + datafeedConfig.query, + undefined, + datafeedConfig.job_id, + FilterStateStore.GLOBAL_STATE + ), + }; + const dashboardLocator = this.share.url.locators.get('DASHBOARD_APP_LOCATOR'); + const encodedUrl = dashboardLocator ? await dashboardLocator.getUrl(params) : ''; + const url = decodeURIComponent(encodedUrl).replace(/^.+dashboards/, 'dashboards'); + + const dashboardName = dashboard.getOutput().title; + + const urlName = + dashboardName === undefined + ? i18n.translate('xpack.ml.newJob.fromLens.createJob.defaultUrlDashboard', { + defaultMessage: 'Original dashboard', + }) + : i18n.translate('xpack.ml.newJob.fromLens.createJob.namedUrlDashboard', { + defaultMessage: 'Open {dashboardName}', + values: { dashboardName }, + }); + + return { url_name: urlName, url_value: url, time_range: 'auto' }; + } + + private async getCustomUrls(dashboard: Dashboard, datafeedConfig: estypes.MlDatafeed) { + return dashboard !== undefined + ? { custom_urls: [await this.createDashboardLink(dashboard, datafeedConfig)] } + : {}; + } } diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/route_resolver.ts b/x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/route_resolver.ts index df487380044ae..a16a4320ee222 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/route_resolver.ts +++ b/x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/route_resolver.ts @@ -17,6 +17,7 @@ import { getDataViews, getSavedObjectsClient, getTimefilter, + getShare, } from '../../../util/dependency_cache'; import { getDefaultQuery } from '../utils/new_job_utils'; @@ -70,7 +71,13 @@ export async function resolver( layerIndex = undefined; } - const jobCreator = new QuickJobCreator(getDataViews(), getUiSettings(), getTimefilter(), ml); + const jobCreator = new QuickJobCreator( + getDataViews(), + getUiSettings(), + getTimefilter(), + getShare(), + ml + ); await jobCreator.createAndStashADJob(vis, from, to, query, filters, layerIndex); } diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/utils.ts b/x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/utils.ts index cec998e1262bc..95f9a847cb837 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/utils.ts +++ b/x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/utils.ts @@ -92,12 +92,15 @@ export function getJobsItemsFromEmbeddable(embeddable: Embeddable) { ); } + const dashboard = embeddable.parent?.type === 'dashboard' ? embeddable.parent : undefined; + return { vis, from, to, query, filters, + dashboard, }; } diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/visualization_extractor.ts b/x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/visualization_extractor.ts index d3fe88a390c1e..31cec1635968f 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/visualization_extractor.ts +++ b/x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/visualization_extractor.ts @@ -14,8 +14,8 @@ import type { LensSavedObjectAttributes, FieldBasedIndexPatternColumn, XYDataLayerConfig, - IndexPatternPersistedState, - IndexPatternLayer, + FormBasedPersistedState, + FormBasedLayer, XYLayerConfig, } from '@kbn/lens-plugin/public'; import { layerTypes } from '@kbn/lens-plugin/public'; @@ -68,7 +68,7 @@ export class VisualizationExtractor { ); } - const indexpattern = vis.state.datasourceStates.indexpattern as IndexPatternPersistedState; + const indexpattern = vis.state.datasourceStates.formBased as FormBasedPersistedState; const compatibleIndexPatternLayer = Object.entries(indexpattern.layers).find( ([id]) => layer.layerId === id ); @@ -192,10 +192,7 @@ export class VisualizationExtractor { } } -function getColumns( - { columns }: Omit, - layer: XYDataLayerConfig -) { +function getColumns({ columns }: Omit, layer: XYDataLayerConfig) { layer.accessors.forEach((a) => { const col = columns[a]; // fail early if any of the cols being used as accessors diff --git a/x-pack/plugins/ml/public/application/management/index.ts b/x-pack/plugins/ml/public/application/management/index.ts index 86f7fa0ff92ab..f64d7cbb5bb64 100644 --- a/x-pack/plugins/ml/public/application/management/index.ts +++ b/x-pack/plugins/ml/public/application/management/index.ts @@ -23,7 +23,7 @@ export function registerManagementSection( title: i18n.translate('xpack.ml.management.jobsListTitle', { defaultMessage: 'Machine Learning', }), - order: 2, + order: 4, async mount(params: ManagementAppMountParams) { const { mountApp } = await import('./jobs_list'); return mountApp(core, params, deps); diff --git a/x-pack/plugins/ml/public/application/notifications/components/entity_filter.tsx b/x-pack/plugins/ml/public/application/notifications/components/entity_filter.tsx new file mode 100644 index 0000000000000..01159b7491c25 --- /dev/null +++ b/x-pack/plugins/ml/public/application/notifications/components/entity_filter.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, { type FC, useState, useCallback, useMemo } from 'react'; +import { uniqBy } from 'lodash'; +import { EuiFilterButton, EuiPanel, EuiPopover } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n-react'; +import type { CustomComponentProps } from '@elastic/eui/src/components/search_bar/filters/custom_component_filter'; +import { MlEntitySelector, type MlEntitySelectorProps } from '../../components/ml_entity_selector'; + +/** + * Custom filter component to use with {@link EuiInMemoryTable} + */ +export const EntityFilter: FC = React.memo(({ query, onChange }) => { + const [isOpen, setIsOpen] = useState(false); + + const hasActiveFilters = query.hasOrFieldClause('job_id') || query.hasSimpleFieldClause('job_id'); + const orFieldClause = query.getOrFieldClause('job_id'); + const simpleFieldClause = query.getSimpleFieldClause('job_id'); + + const closePopover = setIsOpen.bind(null, false); + + const selectedOptions = useMemo(() => { + let options: Exclude = []; + + if (orFieldClause && Array.isArray(orFieldClause.value)) { + options = orFieldClause.value.map((v) => ({ id: v as string })); + } + if (simpleFieldClause && simpleFieldClause.value) { + options.push({ id: simpleFieldClause.value as string }); + } + return options; + }, [orFieldClause, simpleFieldClause]); + + const onSelectionChange = useCallback< + Exclude + >( + (entitiesSelection) => { + // first clean up + let newQuery = query.removeOrFieldClauses('job_id'); + newQuery = newQuery.removeSimpleFieldClauses('job_id'); + + if (entitiesSelection.length > 0) { + newQuery = uniqBy(entitiesSelection, 'id').reduce((acc, curr) => { + return acc.addOrFieldValue('job_id', curr.id, true, 'eq'); + }, newQuery); + } + + onChange!(newQuery); + }, + [onChange, query] + ); + + const button = ( + !prev)} + hasActiveFilters={hasActiveFilters} + numActiveFilters={hasActiveFilters ? selectedOptions.length : undefined} + grow + > + + + ); + + return ( + + + + + + ); +}); diff --git a/x-pack/plugins/ml/public/application/notifications/components/notifications_list.test.tsx b/x-pack/plugins/ml/public/application/notifications/components/notifications_list.test.tsx new file mode 100644 index 0000000000000..a40f7dc51352c --- /dev/null +++ b/x-pack/plugins/ml/public/application/notifications/components/notifications_list.test.tsx @@ -0,0 +1,51 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { I18nProvider } from '@kbn/i18n-react'; +import { render, waitFor } from '@testing-library/react'; +import { NotificationsList } from './notifications_list'; +import { useMlKibana } from '../../contexts/kibana'; + +jest.mock('../../contexts/kibana'); +jest.mock('../../services/toast_notification_service'); +jest.mock('../../contexts/ml/ml_notifications_context'); +jest.mock('../../contexts/kibana/use_timefilter'); +jest.mock('../../contexts/kibana/use_field_formatter'); +jest.mock('../../components/saved_objects_warning'); + +describe('NotificationsList', () => { + beforeEach(() => { + jest.useFakeTimers('modern'); + }); + + afterEach(() => { + jest.clearAllMocks(); + jest.useRealTimers(); + }); + + test('starts fetching notification on mount with default params', async () => { + const {} = render(, { wrapper: I18nProvider }); + + jest.advanceTimersByTime(500); + + await waitFor(() => { + expect( + useMlKibana().services.mlServices.mlApiServices.notifications.findMessages + ).toHaveBeenCalledTimes(1); + expect( + useMlKibana().services.mlServices.mlApiServices.notifications.findMessages + ).toHaveBeenCalledWith({ + earliest: '', + latest: '', + queryString: '*', + sortDirection: 'desc', + sortField: 'timestamp', + }); + }); + }); +}); diff --git a/x-pack/plugins/ml/public/application/notifications/components/notifications_list.tsx b/x-pack/plugins/ml/public/application/notifications/components/notifications_list.tsx index cd68f366b57a6..21b52fa374abd 100644 --- a/x-pack/plugins/ml/public/application/notifications/components/notifications_list.tsx +++ b/x-pack/plugins/ml/public/application/notifications/components/notifications_list.tsx @@ -22,6 +22,7 @@ import { import { EuiBasicTableColumn } from '@elastic/eui/src/components/basic_table/basic_table'; import { FIELD_FORMAT_IDS } from '@kbn/field-formats-plugin/common'; import useDebounce from 'react-use/lib/useDebounce'; +import { EntityFilter } from './entity_filter'; import { useMlNotifications } from '../../contexts/ml/ml_notifications_context'; import { ML_NOTIFICATIONS_MESSAGE_LEVEL } from '../../../../common/constants/notifications'; import { SavedObjectsWarning } from '../../components/saved_objects_warning'; @@ -77,7 +78,7 @@ export const NotificationsList: FC = () => { // eslint-disable-next-line react-hooks/exhaustive-deps }, []); - const [isLoading, setIsLoading] = useState(false); + const [isLoading, setIsLoading] = useState(true); const [items, setItems] = useState([]); const [totalCount, setTotalCount] = useState(0); const [queryError, setQueryError] = useState(''); @@ -277,6 +278,10 @@ export const NotificationsList: FC = () => { }, ], }, + { + type: 'custom_component', + component: EntityFilter, + }, ]; }, []); @@ -286,7 +291,7 @@ export const NotificationsList: FC = () => { <> - {newNotificationsCount ? ( + {newNotificationsCount && !isLoading ? ( <> { return { displayWarningToast: jest.fn(() => {}), + displayErrorToast: jest.fn(() => {}), }; }); diff --git a/x-pack/plugins/ml/public/application/util/dependency_cache.ts b/x-pack/plugins/ml/public/application/util/dependency_cache.ts index 0b78fb460ed85..6f42ab0ff7847 100644 --- a/x-pack/plugins/ml/public/application/util/dependency_cache.ts +++ b/x-pack/plugins/ml/public/application/util/dependency_cache.ts @@ -27,6 +27,7 @@ import type { DataViewsContract } from '@kbn/data-views-plugin/public'; import type { SecurityPluginStart } from '@kbn/security-plugin/public'; import type { MapsStartApi } from '@kbn/maps-plugin/public'; import type { DataVisualizerPluginStart } from '@kbn/data-visualizer-plugin/public'; +import type { SharePluginStart } from '@kbn/share-plugin/public'; export interface DependencyCache { timefilter: DataPublicPluginSetup['query']['timefilter'] | null; @@ -49,6 +50,7 @@ export interface DependencyCache { maps: MapsStartApi | null; dataVisualizer: DataVisualizerPluginStart | null; dataViews: DataViewsContract | null; + share: SharePluginStart | null; } const cache: DependencyCache = { @@ -72,6 +74,7 @@ const cache: DependencyCache = { maps: null, dataVisualizer: null, dataViews: null, + share: null, }; export function setDependencyCache(deps: Partial) { @@ -94,6 +97,7 @@ export function setDependencyCache(deps: Partial) { cache.dashboard = deps.dashboard || null; cache.dataVisualizer = deps.dataVisualizer || null; cache.dataViews = deps.dataViews || null; + cache.share = deps.share || null; } export function getTimefilter() { @@ -228,15 +232,22 @@ export function getDataViews() { return cache.dataViews; } -export function clearCache() { - Object.keys(cache).forEach((k) => { - cache[k as keyof DependencyCache] = null; - }); -} - export function getFileDataVisualizer() { if (cache.dataVisualizer === null) { throw new Error("dataVisualizer hasn't been initialized"); } return cache.dataVisualizer; } + +export function getShare() { + if (cache.share === null) { + throw new Error("share hasn't been initialized"); + } + return cache.share; +} + +export function clearCache() { + Object.keys(cache).forEach((k) => { + cache[k as keyof DependencyCache] = null; + }); +} diff --git a/x-pack/plugins/ml/public/embeddables/lens/lens_vis_layer_selection_flyout/layer/compatible_layer.tsx b/x-pack/plugins/ml/public/embeddables/lens/lens_vis_layer_selection_flyout/layer/compatible_layer.tsx index 0e163f207edfb..a5bea9c41be40 100644 --- a/x-pack/plugins/ml/public/embeddables/lens/lens_vis_layer_selection_flyout/layer/compatible_layer.tsx +++ b/x-pack/plugins/ml/public/embeddables/lens/lens_vis_layer_selection_flyout/layer/compatible_layer.tsx @@ -82,6 +82,7 @@ export const CompatibleLayer: FC = ({ layer, layerIndex, embeddable }) => data.dataViews, uiSettings, data.query.timefilter.timefilter, + share, mlApiServices ), // eslint-disable-next-line react-hooks/exhaustive-deps diff --git a/x-pack/plugins/ml/server/models/notifications_service/notifications_service_provider.ts b/x-pack/plugins/ml/server/models/notifications_service/notifications_service_provider.ts index 959de0e3cc805..5505687525db1 100644 --- a/x-pack/plugins/ml/server/models/notifications_service/notifications_service_provider.ts +++ b/x-pack/plugins/ml/server/models/notifications_service/notifications_service_provider.ts @@ -28,6 +28,14 @@ export class NotificationsService { private readonly mlSavedObjectService: MLSavedObjectService ) {} + private getDefaultCountResponse() { + return { + error: 0, + warning: 0, + info: 0, + } as NotificationsCountResponse; + } + /** * Provides entity IDs per type for the current space. * @private @@ -217,7 +225,11 @@ export class NotificationsService { }, }); - const byLevel = responseBody.aggregations! + if (!responseBody.aggregations) { + return this.getDefaultCountResponse(); + } + + const byLevel = responseBody.aggregations .by_level as estypes.AggregationsMultiBucketAggregateBase; return Array.isArray(byLevel.buckets) @@ -229,17 +241,14 @@ export class NotificationsService { }) ); - return res.reduce( - (acc, curr) => { - for (const levelKey in curr) { - if (curr.hasOwnProperty(levelKey)) { - acc[levelKey as MlNotificationMessageLevel] += - curr[levelKey as MlNotificationMessageLevel]; - } + return res.reduce((acc, curr) => { + for (const levelKey in curr) { + if (curr.hasOwnProperty(levelKey)) { + acc[levelKey as MlNotificationMessageLevel] += + curr[levelKey as MlNotificationMessageLevel]; } - return acc; - }, - { error: 0, warning: 0, info: 0 } as NotificationsCountResponse - ); + } + return acc; + }, this.getDefaultCountResponse()); } } diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_attributes.test.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_attributes.test.ts index 8f2953a45834e..a21684bd0d08c 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_attributes.test.ts +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_attributes.test.ts @@ -118,7 +118,7 @@ describe('Lens Attribute', () => { ReportTypes.KPI ); - expect(lnsAttrKpi.getJSON().state.datasourceStates.indexpattern.layers.layer0.columns).toEqual({ + expect(lnsAttrKpi.getJSON().state.datasourceStates.formBased.layers.layer0.columns).toEqual({ 'x-axis-column-layer0': { dataType: 'date', isBucketed: true, @@ -352,7 +352,7 @@ describe('Lens Attribute', () => { }); it('should return first layer', function () { - expect(lnsAttr.getLayers()).toEqual(sampleAttribute.state.datasourceStates.indexpattern.layers); + expect(lnsAttr.getLayers()).toEqual(sampleAttribute.state.datasourceStates.formBased.layers); }); it('should return expected XYState', function () { diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_attributes.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_attributes.ts index 3c8c2e5d4bffb..50701e12f94be 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_attributes.ts +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_attributes.ts @@ -1100,7 +1100,7 @@ export class LensAttributes { references: this.getReferences(), state: { datasourceStates: { - indexpattern: { + formBased: { layers: this.layers, }, }, diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_attributes/sample_formula_metric_attribute.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_attributes/sample_formula_metric_attribute.ts index d6f572fcacde6..c70d0ee031451 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_attributes/sample_formula_metric_attribute.ts +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_attributes/sample_formula_metric_attribute.ts @@ -21,7 +21,7 @@ export const sampleMetricFormulaAttribute = { ], state: { datasourceStates: { - indexpattern: { + formBased: { layers: { layer0: { columnOrder: [ diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_attributes/single_metric_attributes.test.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_attributes/single_metric_attributes.test.ts index 2f06db3ae144a..d6c5bfea5f1d6 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_attributes/single_metric_attributes.test.ts +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_attributes/single_metric_attributes.test.ts @@ -74,7 +74,7 @@ describe('SingleMetricAttributes', () => { ], state: { datasourceStates: { - indexpattern: { + formBased: { layers: { layer0: { columnOrder: ['layer-0-column-1'], @@ -136,7 +136,7 @@ describe('SingleMetricAttributes', () => { ], state: { datasourceStates: { - indexpattern: { + formBased: { layers: { layer0: { columnOrder: ['layer-0-column-1'], diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_attributes/single_metric_attributes.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_attributes/single_metric_attributes.ts index fd53d9025d4dc..f674ab1f9914f 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_attributes/single_metric_attributes.ts +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_attributes/single_metric_attributes.ts @@ -49,13 +49,20 @@ export class SingleMetricLensAttributes extends LensAttributes { getSingleMetricLayer() { const { seriesConfig, selectedMetricField, operationType, indexPattern } = this.layerConfigs[0]; - const { columnFilter, columnField, columnLabel, columnType, formula, metricStateOptions } = - parseCustomFieldName(seriesConfig, selectedMetricField); + const { + columnFilter, + columnField, + columnLabel, + columnType, + formula, + metricStateOptions, + format, + } = parseCustomFieldName(seriesConfig, selectedMetricField); this.metricStateOptions = metricStateOptions; if (columnType === FORMULA_COLUMN && formula) { - return this.getFormulaLayer({ formula, label: columnLabel, dataView: indexPattern }); + return this.getFormulaLayer({ formula, label: columnLabel, dataView: indexPattern, format }); } const getSourceField = () => { @@ -99,9 +106,11 @@ export class SingleMetricLensAttributes extends LensAttributes { formula, label, dataView, + format, }: { formula: string; label?: string; + format?: string; dataView: DataView; }) { const layer = this.lensFormulaHelper?.insertOrReplaceFormulaColumn( @@ -109,12 +118,15 @@ export class SingleMetricLensAttributes extends LensAttributes { { formula, label, - format: { - id: 'percent', - params: { - decimals: 1, - }, - }, + format: + format === 'percent' || !format + ? { + id: 'percent', + params: { + decimals: 1, + }, + } + : undefined, }, { columns: {}, columnOrder: [] }, dataView @@ -176,7 +188,7 @@ export class SingleMetricLensAttributes extends LensAttributes { state: { visualization, datasourceStates: { - indexpattern: { + formBased: { layers: this.layers, }, }, diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/synthetics/single_metric_config.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/synthetics/single_metric_config.ts index 173b92cf6ba42..b9efbd865b3ed 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/synthetics/single_metric_config.ts +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/synthetics/single_metric_config.ts @@ -76,6 +76,36 @@ export function getSyntheticsSingleMetricConfig({ dataView }: ConfigProps): Seri titlePosition: 'bottom', }, }, + { + id: 'monitor_errors', + field: 'state.id', + label: i18n.translate('xpack.observability.expView.errors', { + defaultMessage: 'Errors', + }), + metricStateOptions: { + titlePosition: 'bottom', + colorMode: 'Labels', + palette: { + name: 'custom', + type: 'palette', + params: { + steps: 3, + name: 'custom', + reverse: false, + rangeType: 'number', + rangeMin: 0, + progression: 'fixed', + stops: [{ color: '#E7664C', stop: 100 }], + colorStops: [{ color: '#E7664C', stop: 0 }], + continuity: 'above', + maxSteps: 5, + }, + }, + }, + columnType: FORMULA_COLUMN, + formula: 'unique_count(state.id, kql=\'monitor.status: "down"\')', + format: 'number', + }, ], labels: FieldLabels, }; diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/mobile_test_attribute.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/mobile_test_attribute.ts index 02678ad91ba12..874d6e45b2234 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/mobile_test_attribute.ts +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/mobile_test_attribute.ts @@ -23,7 +23,7 @@ export const testMobileKPIAttr = { visualizationType: 'lnsXY', state: { datasourceStates: { - indexpattern: { + formBased: { layers: { layer0: { columnOrder: ['x-axis-column-layer0', 'y-axis-column-layer0'], diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/sample_attribute.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/sample_attribute.ts index dcc2775a54871..5302078d372ce 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/sample_attribute.ts +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/sample_attribute.ts @@ -27,7 +27,7 @@ export const sampleAttribute = { ], state: { datasourceStates: { - indexpattern: { + formBased: { layers: { layer0: { columnOrder: [ diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/sample_attribute_cwv.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/sample_attribute_cwv.ts index a688962459a24..108112e43ae35 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/sample_attribute_cwv.ts +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/sample_attribute_cwv.ts @@ -22,7 +22,7 @@ export const sampleAttributeCoreWebVital = { ], state: { datasourceStates: { - indexpattern: { + formBased: { layers: { layer0: { columnOrder: [ diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/sample_attribute_kpi.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/sample_attribute_kpi.ts index c5b62ce3f14b4..c1bd53c85b760 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/sample_attribute_kpi.ts +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/sample_attribute_kpi.ts @@ -22,7 +22,7 @@ export const sampleAttributeKpi = { ], state: { datasourceStates: { - indexpattern: { + formBased: { layers: { layer0: { columnOrder: ['x-axis-column-layer0', 'y-axis-column-layer0'], diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/sample_attribute_with_reference_lines.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/sample_attribute_with_reference_lines.ts index 32d3d480e777d..2cf6cdc8a6054 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/sample_attribute_with_reference_lines.ts +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/sample_attribute_with_reference_lines.ts @@ -27,7 +27,7 @@ export const sampleAttributeWithReferenceLines = { ], state: { datasourceStates: { - indexpattern: { + formBased: { layers: { layer0: { columnOrder: [ diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/embeddable/embeddable.test.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/embeddable/embeddable.test.tsx index fecb9e7172cc6..a6c3cd1777ec5 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/embeddable/embeddable.test.tsx +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/embeddable/embeddable.test.tsx @@ -32,7 +32,7 @@ const mockLensAttrs = { }, filters: [], datasourceStates: { - indexpattern: { + formBased: { layers: { '416b6fad-1923-4f6a-a2df-b223bb287e30': { columnOrder: ['b00c65ea-32be-4163-bfc8-f795b1ef9d06'], diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/types.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/types.ts index a30a146aaf844..11f6ad624fcbe 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/types.ts +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/types.ts @@ -69,6 +69,7 @@ export interface MetricOption { formula?: string; metricStateOptions?: Pick; palette?: PaletteOutput; + format?: 'percent' | 'number'; } export interface SeriesConfig { diff --git a/x-pack/plugins/observability/server/domain/services/compute_error_budget.test.ts b/x-pack/plugins/observability/server/domain/services/compute_error_budget.test.ts new file mode 100644 index 0000000000000..66bffb39ca91e --- /dev/null +++ b/x-pack/plugins/observability/server/domain/services/compute_error_budget.test.ts @@ -0,0 +1,77 @@ +/* + * 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 { createAPMTransactionErrorRateIndicator, createSLO } from '../../services/slo/fixtures/slo'; +import { computeErrorBudget } from './compute_error_budget'; + +describe('computeErrorBudget', () => { + it("returns default values when total events is '0'", () => { + const slo = createSLO(createAPMTransactionErrorRateIndicator()); + const errorBudget = computeErrorBudget(slo, { good: 100, total: 0 }); + + expect(errorBudget).toEqual({ + initial: 0.001, // 0.1% + consumed: 0, // 0% consumed + remaining: 1, // 100% remaining + }); + }); + + it("computes the error budget when 'good > total' events", () => { + const slo = createSLO(createAPMTransactionErrorRateIndicator()); + const errorBudget = computeErrorBudget(slo, { good: 9999, total: 9 }); + + expect(errorBudget).toEqual({ + initial: 0.001, + consumed: 0, + remaining: 1, + }); + }); + + it('computes the error budget with all good events', () => { + const slo = createSLO(createAPMTransactionErrorRateIndicator()); + const errorBudget = computeErrorBudget(slo, { good: 100, total: 100 }); + + expect(errorBudget).toEqual({ + initial: 0.001, + consumed: 0, + remaining: 1, + }); + }); + + it('computes the error budget when exactly consumed', () => { + const slo = createSLO(createAPMTransactionErrorRateIndicator()); + const errorBudget = computeErrorBudget(slo, { good: 999, total: 1000 }); + + expect(errorBudget).toEqual({ + initial: 0.001, + consumed: 1, + remaining: 0, + }); + }); + + it('computes the error budget with rounded values', () => { + const slo = createSLO(createAPMTransactionErrorRateIndicator()); + const errorBudget = computeErrorBudget(slo, { good: 333, total: 777 }); + + expect(errorBudget).toEqual({ + initial: 0.001, + consumed: 571.428571, // i.e. 57142% consumed + remaining: 0, + }); + }); + + it('computes the error budget with no good events', () => { + const slo = createSLO(createAPMTransactionErrorRateIndicator()); + const errorBudget = computeErrorBudget(slo, { good: 0, total: 100 }); + + expect(errorBudget).toEqual({ + initial: 0.001, + consumed: 1000, // i.e. 100000% consumed + remaining: 0, + }); + }); +}); diff --git a/x-pack/plugins/observability/server/domain/services/compute_error_budget.ts b/x-pack/plugins/observability/server/domain/services/compute_error_budget.ts new file mode 100644 index 0000000000000..98ee17962b818 --- /dev/null +++ b/x-pack/plugins/observability/server/domain/services/compute_error_budget.ts @@ -0,0 +1,34 @@ +/* + * 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 { ErrorBudget, IndicatorData, SLO } from '../../types/models'; +import { toHighPrecision } from '../../utils/number'; + +export function computeErrorBudget(slo: SLO, sliData: IndicatorData): ErrorBudget { + const goodEvents = sliData.good; + const totalEvents = sliData.total; + const initialErrorBudget = toHighPrecision(1 - slo.objective.target); + if (totalEvents === 0 || goodEvents >= totalEvents) { + return { + initial: initialErrorBudget, + consumed: 0, + remaining: 1, + }; + } + + const consumedErrorBudget = toHighPrecision( + (totalEvents - goodEvents) / (totalEvents * initialErrorBudget) + ); + + const remainingErrorBudget = Math.max(toHighPrecision(1 - consumedErrorBudget), 0); + + return { + initial: initialErrorBudget, + consumed: consumedErrorBudget, + remaining: remainingErrorBudget, + }; +} diff --git a/x-pack/plugins/observability/server/domain/services/compute_sli.test.ts b/x-pack/plugins/observability/server/domain/services/compute_sli.test.ts new file mode 100644 index 0000000000000..ba864fc1fea19 --- /dev/null +++ b/x-pack/plugins/observability/server/domain/services/compute_sli.test.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 { computeSLI } from './compute_sli'; + +describe('computeSLI', () => { + it('returns 0 when no total events', () => { + expect(computeSLI({ good: 100, total: 0 })).toEqual(0); + }); + + it('returns the sli value', () => { + expect(computeSLI({ good: 100, total: 1000 })).toEqual(0.1); + }); + + it('returns 1 when good is greater than total events', () => { + expect(computeSLI({ good: 9999, total: 9 })).toEqual(1); + }); + + it('returns rounds the value to 6 digits', () => { + expect(computeSLI({ good: 33, total: 90 })).toEqual(0.366667); + }); +}); diff --git a/x-pack/plugins/observability/server/domain/services/compute_sli.ts b/x-pack/plugins/observability/server/domain/services/compute_sli.ts new file mode 100644 index 0000000000000..2def35dc37329 --- /dev/null +++ b/x-pack/plugins/observability/server/domain/services/compute_sli.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { IndicatorData } from '../../types/models'; +import { toHighPrecision } from '../../utils/number'; + +export function computeSLI(sliData: IndicatorData): number { + const goodEvents = sliData.good; + const totalEvents = sliData.total; + if (totalEvents === 0) { + return 0; + } + + if (goodEvents >= totalEvents) { + return 1; + } + + return toHighPrecision(goodEvents / totalEvents); +} diff --git a/x-pack/plugins/observability/server/domain/services/index.ts b/x-pack/plugins/observability/server/domain/services/index.ts new file mode 100644 index 0000000000000..07c67b59da9d7 --- /dev/null +++ b/x-pack/plugins/observability/server/domain/services/index.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export * from './compute_error_budget'; +export * from './compute_sli'; diff --git a/x-pack/plugins/observability/server/errors/errors.ts b/x-pack/plugins/observability/server/errors/errors.ts index 2e00a8cc22bfe..a83a0c31610e9 100644 --- a/x-pack/plugins/observability/server/errors/errors.ts +++ b/x-pack/plugins/observability/server/errors/errors.ts @@ -15,3 +15,5 @@ export class ObservabilityError extends Error { } export class SLONotFound extends ObservabilityError {} +export class InternalQueryError extends ObservabilityError {} +export class NotSupportedError extends ObservabilityError {} diff --git a/x-pack/plugins/observability/server/routes/slo/route.ts b/x-pack/plugins/observability/server/routes/slo/route.ts index c80abf6b60b5f..58b8a3f346044 100644 --- a/x-pack/plugins/observability/server/routes/slo/route.ts +++ b/x-pack/plugins/observability/server/routes/slo/route.ts @@ -13,6 +13,7 @@ import { KibanaSavedObjectsSLORepository, GetSLO, UpdateSLO, + DefaultSLIClient, } from '../../services/slo'; import { ApmTransactionDurationTransformGenerator, @@ -101,8 +102,10 @@ const getSLORoute = createObservabilityServerRoute({ params: getSLOParamsSchema, handler: async ({ context, params }) => { const soClient = (await context.core).savedObjects.client; + const esClient = (await context.core).elasticsearch.client.asCurrentUser; const repository = new KibanaSavedObjectsSLORepository(soClient); - const getSLO = new GetSLO(repository); + const sliClient = new DefaultSLIClient(esClient); + const getSLO = new GetSLO(repository, sliClient); const response = await getSLO.execute(params.path.id); diff --git a/x-pack/plugins/observability/server/services/slo/get_slo.test.ts b/x-pack/plugins/observability/server/services/slo/get_slo.test.ts index dac1b7aa8ca28..bc209c24c8098 100644 --- a/x-pack/plugins/observability/server/services/slo/get_slo.test.ts +++ b/x-pack/plugins/observability/server/services/slo/get_slo.test.ts @@ -7,22 +7,26 @@ import { createAPMTransactionErrorRateIndicator, createSLO } from './fixtures/slo'; import { GetSLO } from './get_slo'; -import { createSLORepositoryMock } from './mocks'; +import { createSLIClientMock, createSLORepositoryMock } from './mocks'; +import { SLIClient } from './sli_client'; import { SLORepository } from './slo_repository'; describe('GetSLO', () => { let mockRepository: jest.Mocked; + let mockSLIClient: jest.Mocked; let getSLO: GetSLO; beforeEach(() => { mockRepository = createSLORepositoryMock(); - getSLO = new GetSLO(mockRepository); + mockSLIClient = createSLIClientMock(); + getSLO = new GetSLO(mockRepository, mockSLIClient); }); describe('happy path', () => { it('retrieves the SLO from the repository', async () => { const slo = createSLO(createAPMTransactionErrorRateIndicator()); mockRepository.findById.mockResolvedValueOnce(slo); + mockSLIClient.fetchDataForSLOTimeWindow.mockResolvedValueOnce({ good: 9999, total: 10000 }); const result = await getSLO.execute(slo.id); @@ -49,6 +53,14 @@ describe('GetSLO', () => { duration: '7d', is_rolling: true, }, + summary: { + sli_value: 0.9999, + error_budget: { + initial: 0.001, + consumed: 0.1, + remaining: 0.9, + }, + }, created_at: slo.created_at, updated_at: slo.updated_at, revision: slo.revision, diff --git a/x-pack/plugins/observability/server/services/slo/get_slo.ts b/x-pack/plugins/observability/server/services/slo/get_slo.ts index 26ae0ee511842..d217c36965a04 100644 --- a/x-pack/plugins/observability/server/services/slo/get_slo.ts +++ b/x-pack/plugins/observability/server/services/slo/get_slo.ts @@ -5,19 +5,24 @@ * 2.0. */ -import { SLO } from '../../types/models'; +import { ErrorBudget, SLO } from '../../types/models'; import { GetSLOResponse } from '../../types/rest_specs'; import { SLORepository } from './slo_repository'; +import { SLIClient } from './sli_client'; +import { computeSLI, computeErrorBudget } from '../../domain/services'; export class GetSLO { - constructor(private repository: SLORepository) {} + constructor(private repository: SLORepository, private sliClient: SLIClient) {} public async execute(sloId: string): Promise { const slo = await this.repository.findById(sloId); - return this.toResponse(slo); + const sliData = await this.sliClient.fetchDataForSLOTimeWindow(slo); + const sliValue = computeSLI(sliData); + const errorBudget = computeErrorBudget(slo, sliData); + return this.toResponse(slo, sliValue, errorBudget); } - private toResponse(slo: SLO): GetSLOResponse { + private toResponse(slo: SLO, sliValue: number, errorBudget: ErrorBudget): GetSLOResponse { return { id: slo.id, name: slo.name, @@ -26,6 +31,12 @@ export class GetSLO { time_window: slo.time_window, budgeting_method: slo.budgeting_method, objective: slo.objective, + summary: { + sli_value: sliValue, + error_budget: { + ...errorBudget, + }, + }, revision: slo.revision, created_at: slo.created_at, updated_at: slo.updated_at, diff --git a/x-pack/plugins/observability/server/services/slo/index.ts b/x-pack/plugins/observability/server/services/slo/index.ts index 58b31e424842b..64081dcc9d125 100644 --- a/x-pack/plugins/observability/server/services/slo/index.ts +++ b/x-pack/plugins/observability/server/services/slo/index.ts @@ -12,3 +12,4 @@ export * from './create_slo'; export * from './delete_slo'; export * from './get_slo'; export * from './update_slo'; +export * from './sli_client'; diff --git a/x-pack/plugins/observability/server/services/slo/mocks/index.ts b/x-pack/plugins/observability/server/services/slo/mocks/index.ts index 3a9a918fc6480..b05c2c289edee 100644 --- a/x-pack/plugins/observability/server/services/slo/mocks/index.ts +++ b/x-pack/plugins/observability/server/services/slo/mocks/index.ts @@ -6,6 +6,7 @@ */ import { ResourceInstaller } from '../resource_installer'; +import { SLIClient } from '../sli_client'; import { SLORepository } from '../slo_repository'; import { TransformManager } from '../transform_manager'; @@ -32,4 +33,15 @@ const createSLORepositoryMock = (): jest.Mocked => { }; }; -export { createResourceInstallerMock, createTransformManagerMock, createSLORepositoryMock }; +const createSLIClientMock = (): jest.Mocked => { + return { + fetchDataForSLOTimeWindow: jest.fn(), + }; +}; + +export { + createResourceInstallerMock, + createTransformManagerMock, + createSLORepositoryMock, + createSLIClientMock, +}; diff --git a/x-pack/plugins/observability/server/services/slo/sli_client.test.ts b/x-pack/plugins/observability/server/services/slo/sli_client.test.ts new file mode 100644 index 0000000000000..a31edbf1712e2 --- /dev/null +++ b/x-pack/plugins/observability/server/services/slo/sli_client.test.ts @@ -0,0 +1,92 @@ +/* + * 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 { ElasticsearchClientMock, elasticsearchServiceMock } from '@kbn/core/server/mocks'; +import { SLO_DESTINATION_INDEX_NAME } from '../../assets/constants'; +import { InternalQueryError } from '../../errors'; +import { createAPMTransactionErrorRateIndicator, createSLO } from './fixtures/slo'; +import { DefaultSLIClient } from './sli_client'; + +describe('SLIClient', () => { + let esClientMock: ElasticsearchClientMock; + + beforeEach(() => { + esClientMock = elasticsearchServiceMock.createElasticsearchClient(); + }); + + describe('fetchDataForSLOTimeWindow', () => { + it('throws when aggregations failed', async () => { + const slo = createSLO(createAPMTransactionErrorRateIndicator()); + esClientMock.search.mockResolvedValueOnce({ + took: 100, + timed_out: false, + _shards: { + total: 0, + successful: 0, + skipped: 0, + failed: 0, + }, + hits: { + hits: [], + }, + aggregations: {}, + }); + const sliClient = new DefaultSLIClient(esClientMock); + + await expect(sliClient.fetchDataForSLOTimeWindow(slo)).rejects.toThrowError( + new InternalQueryError('SLI aggregation query') + ); + }); + + it('returns the aggregated good and total values for the SLO time window date range', async () => { + const slo = createSLO(createAPMTransactionErrorRateIndicator()); + esClientMock.search.mockResolvedValueOnce({ + took: 100, + timed_out: false, + _shards: { + total: 0, + successful: 0, + skipped: 0, + failed: 0, + }, + hits: { + hits: [], + }, + aggregations: { + full_window: { buckets: [{ good: { value: 90 }, total: { value: 100 } }] }, + }, + }); + const sliClient = new DefaultSLIClient(esClientMock); + + const result = await sliClient.fetchDataForSLOTimeWindow(slo); + + expect(result).toEqual({ good: 90, total: 100 }); + expect(esClientMock.search).toHaveBeenCalledWith( + expect.objectContaining({ + index: `${SLO_DESTINATION_INDEX_NAME}*`, + query: { + bool: { + filter: [{ term: { 'slo.id': slo.id } }, { term: { 'slo.revision': slo.revision } }], + }, + }, + aggs: { + full_window: { + date_range: { + field: '@timestamp', + ranges: [{ from: 'now-7d/m', to: 'now/m' }], + }, + aggs: { + good: { sum: { field: 'slo.numerator' } }, + total: { sum: { field: 'slo.denominator' } }, + }, + }, + }, + }) + ); + }); + }); +}); diff --git a/x-pack/plugins/observability/server/services/slo/sli_client.ts b/x-pack/plugins/observability/server/services/slo/sli_client.ts new file mode 100644 index 0000000000000..9c37c923fa4c9 --- /dev/null +++ b/x-pack/plugins/observability/server/services/slo/sli_client.ts @@ -0,0 +1,69 @@ +/* + * 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 { ElasticsearchClient } from '@kbn/core/server'; +import { SLO_DESTINATION_INDEX_NAME } from '../../assets/constants'; +import { InternalQueryError, NotSupportedError } from '../../errors'; +import { IndicatorData, SLO } from '../../types/models'; + +export interface SLIClient { + fetchDataForSLOTimeWindow(slo: SLO): Promise; +} + +export class DefaultSLIClient implements SLIClient { + constructor(private esClient: ElasticsearchClient) {} + + async fetchDataForSLOTimeWindow(slo: SLO): Promise { + if (slo.budgeting_method !== 'occurrences') { + throw new NotSupportedError(`Budgeting method: ${slo.budgeting_method}`); + } + + const result = await this.esClient.search({ + size: 0, + index: `${SLO_DESTINATION_INDEX_NAME}*`, + query: { + bool: { + filter: [{ term: { 'slo.id': slo.id } }, { term: { 'slo.revision': slo.revision } }], + }, + }, + aggs: { + full_window: { + date_range: { + field: '@timestamp', + ranges: [fromSLOTimeWindowToRange(slo)], + }, + aggs: { + good: { sum: { field: 'slo.numerator' } }, + total: { sum: { field: 'slo.denominator' } }, + }, + }, + }, + }); + + // @ts-ignore buckets is not recognized + const aggs = result.aggregations?.full_window?.buckets[0]; + if (aggs === undefined) { + throw new InternalQueryError('SLI aggregation query'); + } + + return { + good: aggs.good.value, + total: aggs.total.value, + }; + } +} + +function fromSLOTimeWindowToRange(slo: SLO): { from: string; to: string } { + if (!slo.time_window.is_rolling) { + throw new NotSupportedError(`Time window: ${slo.time_window.is_rolling}`); + } + + return { + from: `now-${slo.time_window.duration}/m`, + to: 'now/m', + }; +} diff --git a/x-pack/plugins/observability/server/types/models/error_budget.ts b/x-pack/plugins/observability/server/types/models/error_budget.ts new file mode 100644 index 0000000000000..bc3b36af654b5 --- /dev/null +++ b/x-pack/plugins/observability/server/types/models/error_budget.ts @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import * as t from 'io-ts'; +import { errorBudgetSchema } from '../schema'; + +type ErrorBudget = t.TypeOf; + +export type { ErrorBudget }; diff --git a/x-pack/plugins/observability/server/types/models/index.ts b/x-pack/plugins/observability/server/types/models/index.ts index 78f557bdcbc7d..0f83e97aee6fd 100644 --- a/x-pack/plugins/observability/server/types/models/index.ts +++ b/x-pack/plugins/observability/server/types/models/index.ts @@ -6,3 +6,5 @@ */ export * from './slo'; +export * from './indicators'; +export * from './error_budget'; diff --git a/x-pack/plugins/observability/server/types/models/indicators.ts b/x-pack/plugins/observability/server/types/models/indicators.ts new file mode 100644 index 0000000000000..768d483380eeb --- /dev/null +++ b/x-pack/plugins/observability/server/types/models/indicators.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 * as t from 'io-ts'; +import { + apmTransactionDurationIndicatorSchema, + apmTransactionErrorRateIndicatorSchema, + indicatorSchema, + indicatorTypesSchema, +} from '../schema'; + +const indicatorDataSchema = t.type({ good: t.number, total: t.number }); + +type APMTransactionErrorRateIndicator = t.TypeOf; +type APMTransactionDurationIndicator = t.TypeOf; +type Indicator = t.TypeOf; +type IndicatorTypes = t.TypeOf; +type IndicatorData = t.TypeOf; + +export type { + Indicator, + IndicatorTypes, + APMTransactionErrorRateIndicator, + APMTransactionDurationIndicator, + IndicatorData, +}; diff --git a/x-pack/plugins/observability/server/types/models/slo.ts b/x-pack/plugins/observability/server/types/models/slo.ts index 2c4e1ad64f60b..8435c60f1f8f8 100644 --- a/x-pack/plugins/observability/server/types/models/slo.ts +++ b/x-pack/plugins/observability/server/types/models/slo.ts @@ -7,12 +7,9 @@ import * as t from 'io-ts'; import { - apmTransactionDurationIndicatorSchema, - apmTransactionErrorRateIndicatorSchema, budgetingMethodSchema, dateType, indicatorSchema, - indicatorTypesSchema, objectiveSchema, rollingTimeWindowSchema, } from '../schema'; @@ -35,19 +32,6 @@ const storedSLOSchema = sloSchema; export { sloSchema, storedSLOSchema }; type SLO = t.TypeOf; - -type APMTransactionErrorRateIndicator = t.TypeOf; -type APMTransactionDurationIndicator = t.TypeOf; -type Indicator = t.TypeOf; -type IndicatorTypes = t.TypeOf; - type StoredSLO = t.TypeOf; -export type { - SLO, - Indicator, - IndicatorTypes, - APMTransactionErrorRateIndicator, - APMTransactionDurationIndicator, - StoredSLO, -}; +export type { SLO, StoredSLO }; diff --git a/x-pack/plugins/observability/server/types/rest_specs/slo.ts b/x-pack/plugins/observability/server/types/rest_specs/slo.ts index fe8905f41e9ac..3688a3fe2d515 100644 --- a/x-pack/plugins/observability/server/types/rest_specs/slo.ts +++ b/x-pack/plugins/observability/server/types/rest_specs/slo.ts @@ -6,7 +6,7 @@ */ import * as t from 'io-ts'; -import { dateType, indicatorSchema } from '../schema'; +import { dateType, errorBudgetSchema, indicatorSchema } from '../schema'; import { budgetingMethodSchema, objectiveSchema, rollingTimeWindowSchema } from '../schema/slo'; const createSLOParamsSchema = t.type({ @@ -44,6 +44,10 @@ const getSLOResponseSchema = t.type({ time_window: rollingTimeWindowSchema, budgeting_method: budgetingMethodSchema, objective: objectiveSchema, + summary: t.type({ + sli_value: t.number, + error_budget: errorBudgetSchema, + }), revision: t.number, created_at: dateType, updated_at: dateType, diff --git a/x-pack/plugins/observability/server/types/schema/common.ts b/x-pack/plugins/observability/server/types/schema/common.ts index 521b729f6678d..22a93274b87c4 100644 --- a/x-pack/plugins/observability/server/types/schema/common.ts +++ b/x-pack/plugins/observability/server/types/schema/common.ts @@ -23,4 +23,10 @@ const dateType = new t.Type( (date: Date): string => date.toISOString() ); -export { allOrAnyString, ALL_VALUE, dateType }; +const errorBudgetSchema = t.type({ + initial: t.number, + consumed: t.number, + remaining: t.number, +}); + +export { allOrAnyString, ALL_VALUE, dateType, errorBudgetSchema }; diff --git a/x-pack/plugins/observability/server/utils/number.ts b/x-pack/plugins/observability/server/utils/number.ts new file mode 100644 index 0000000000000..bfec2d6200f19 --- /dev/null +++ b/x-pack/plugins/observability/server/utils/number.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. + */ + +const SIX_DIGITS = 1000000; + +export function toHighPrecision(value: number): number { + return Math.round(value * SIX_DIGITS) / SIX_DIGITS; +} diff --git a/x-pack/plugins/osquery/public/lens/view_results_in_lens.tsx b/x-pack/plugins/osquery/public/lens/view_results_in_lens.tsx index 080c078f6a290..a61e986fd1201 100644 --- a/x-pack/plugins/osquery/public/lens/view_results_in_lens.tsx +++ b/x-pack/plugins/osquery/public/lens/view_results_in_lens.tsx @@ -174,7 +174,7 @@ function getLensAttributes( ], state: { datasourceStates: { - indexpattern: { + formBased: { layers: { layer1: dataLayer, }, diff --git a/x-pack/plugins/osquery/public/packs/pack_queries_status_table.tsx b/x-pack/plugins/osquery/public/packs/pack_queries_status_table.tsx index 2ba4a76c48515..df08fa6d1bf9b 100644 --- a/x-pack/plugins/osquery/public/packs/pack_queries_status_table.tsx +++ b/x-pack/plugins/osquery/public/packs/pack_queries_status_table.tsx @@ -151,7 +151,7 @@ function getLensAttributes( ], state: { datasourceStates: { - indexpattern: { + formBased: { layers: { layer1: dataLayer, }, diff --git a/x-pack/plugins/profiling/server/routes/stacktrace.ts b/x-pack/plugins/profiling/server/routes/stacktrace.ts index 6dbe063e2c4f9..aee9b61694e21 100644 --- a/x-pack/plugins/profiling/server/routes/stacktrace.ts +++ b/x-pack/plugins/profiling/server/routes/stacktrace.ts @@ -283,34 +283,38 @@ export async function mgetStackTraces({ const executableDocIDs = new Set(); const t0 = Date.now(); - // 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; - } - // 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); + 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 fileID of stackTrace.FileIDs) { - executableDocIDs.add(fileID); + // 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); + } } } } - } + }); + logger.info(`processing data took ${Date.now() - t0} ms`); if (stackTraces.size !== 0) { diff --git a/x-pack/plugins/reporting/public/plugin.ts b/x-pack/plugins/reporting/public/plugin.ts index df47c6f28a6e3..d8f4132a59541 100644 --- a/x-pack/plugins/reporting/public/plugin.ts +++ b/x-pack/plugins/reporting/public/plugin.ts @@ -172,7 +172,7 @@ export class ReportingPublicPlugin management.sections.section.insightsAndAlerting.registerApp({ id: 'reporting', title: this.title, - order: 1, + order: 3, mount: async (params) => { params.setBreadcrumbs([{ text: this.breadcrumbText }]); const [[start, startDeps], { mountManagementSection }] = await Promise.all([ diff --git a/x-pack/plugins/security/public/analytics/analytics_service.test.ts b/x-pack/plugins/security/public/analytics/analytics_service.test.ts index 28a272c12f9ec..be13fa25c1c8d 100644 --- a/x-pack/plugins/security/public/analytics/analytics_service.test.ts +++ b/x-pack/plugins/security/public/analytics/analytics_service.test.ts @@ -34,9 +34,12 @@ describe('AnalyticsService', () => { const authc = authenticationMock.createSetup(); authc.getCurrentUser.mockResolvedValue(securityMock.createMockAuthenticatedUser()); + const { analytics, http } = coreMock.createSetup(); + analyticsService.setup({ authc, - analytics: coreMock.createSetup().analytics, + analytics, + http, securityLicense: licenseMock.create({ allowLogin: true }), }); analyticsService.start({ http: mockCore.http }); @@ -63,9 +66,12 @@ describe('AnalyticsService', () => { const authc = authenticationMock.createSetup(); authc.getCurrentUser.mockResolvedValue(securityMock.createMockAuthenticatedUser()); + const { analytics, http } = coreMock.createSetup(); + analyticsService.setup({ authc, - analytics: coreMock.createSetup().analytics, + analytics, + http, securityLicense: licenseMock.create(licenseFeatures$.asObservable()), }); analyticsService.start({ http: mockCore.http }); @@ -116,9 +122,12 @@ describe('AnalyticsService', () => { const authc = authenticationMock.createSetup(); authc.getCurrentUser.mockResolvedValue(securityMock.createMockAuthenticatedUser()); + const { analytics, http } = coreMock.createSetup(); + analyticsService.setup({ authc, - analytics: coreMock.createSetup().analytics, + analytics, + http, securityLicense: licenseMock.create({ allowLogin: true }), }); analyticsService.start({ http: mockCore.http }); @@ -141,9 +150,12 @@ describe('AnalyticsService', () => { const authc = authenticationMock.createSetup(); authc.getCurrentUser.mockResolvedValue(securityMock.createMockAuthenticatedUser()); + const { analytics, http } = coreMock.createSetup(); + analyticsService.setup({ authc, - analytics: coreMock.createSetup().analytics, + analytics, + http, securityLicense: licenseMock.create({ allowLogin: false }), }); analyticsService.start({ http: mockCore.http }); @@ -167,9 +179,12 @@ describe('AnalyticsService', () => { const authc = authenticationMock.createSetup(); authc.getCurrentUser.mockResolvedValue(securityMock.createMockAuthenticatedUser()); + const { analytics, http } = coreMock.createSetup(); + analyticsService.setup({ authc, - analytics: coreMock.createSetup().analytics, + analytics, + http, securityLicense: licenseMock.create({ allowLogin: true }), }); analyticsService.start({ http: mockCore.http }); @@ -185,4 +200,42 @@ describe('AnalyticsService', () => { mockCurrentAuthTypeInfo ); }); + + it('does not register the analytics context provider if the page is anonymous', () => { + const authc = authenticationMock.createSetup(); + const { analytics, http } = coreMock.createSetup(); + + http.anonymousPaths.isAnonymous.mockReturnValue(true); + + analyticsService.setup({ + authc, + analytics, + http, + securityLicense: licenseMock.create({ allowLogin: false }), + }); + + expect(analytics.registerContextProvider).not.toHaveBeenCalled(); + }); + + it('registers the user_id analytics context provider if the page is not anonymous', () => { + const authc = authenticationMock.createSetup(); + authc.getCurrentUser.mockResolvedValue(securityMock.createMockAuthenticatedUser()); + + const { analytics, http } = coreMock.createSetup(); + + http.anonymousPaths.isAnonymous.mockReturnValue(false); + + analyticsService.setup({ + authc, + analytics, + http, + securityLicense: licenseMock.create({ allowLogin: false }), + }); + + expect(analytics.registerContextProvider).toHaveBeenCalledWith( + expect.objectContaining({ + name: 'user_id', + }) + ); + }); }); diff --git a/x-pack/plugins/security/public/analytics/analytics_service.ts b/x-pack/plugins/security/public/analytics/analytics_service.ts index 87c402e9983a0..1c87db674eb40 100644 --- a/x-pack/plugins/security/public/analytics/analytics_service.ts +++ b/x-pack/plugins/security/public/analytics/analytics_service.ts @@ -11,6 +11,7 @@ import { throttleTime } from 'rxjs/operators'; import type { AnalyticsServiceSetup as CoreAnalyticsServiceSetup, + HttpSetup, HttpStart, } from '@kbn/core/public'; @@ -22,6 +23,7 @@ interface AnalyticsServiceSetupParams { securityLicense: SecurityLicense; analytics: CoreAnalyticsServiceSetup; authc: AuthenticationServiceSetup; + http: HttpSetup; cloudId?: string; } @@ -43,9 +45,11 @@ export class AnalyticsService { private securityLicense!: SecurityLicense; private securityFeaturesSubscription?: Subscription; - public setup({ analytics, authc, cloudId, securityLicense }: AnalyticsServiceSetupParams) { + public setup({ analytics, authc, cloudId, http, securityLicense }: AnalyticsServiceSetupParams) { this.securityLicense = securityLicense; - registerUserContext(analytics, authc, cloudId); + if (http.anonymousPaths.isAnonymous(window.location.pathname) === false) { + registerUserContext(analytics, authc, cloudId); + } } public start({ http }: AnalyticsServiceStartParams) { diff --git a/x-pack/plugins/security/public/analytics/register_user_context.ts b/x-pack/plugins/security/public/analytics/register_user_context.ts index bc48846913d02..19ecf0a6896fa 100644 --- a/x-pack/plugins/security/public/analytics/register_user_context.ts +++ b/x-pack/plugins/security/public/analytics/register_user_context.ts @@ -12,6 +12,11 @@ import { Sha256 } from '@kbn/crypto-browser'; import type { AuthenticationServiceSetup } from '..'; +interface UserIdContext { + userId?: string; + isElasticCloudUser: boolean; +} + /** * Set up the Analytics context provider for the User information. * @param analytics Core's Analytics service. The Setup contract. @@ -24,7 +29,7 @@ export function registerUserContext( authc: AuthenticationServiceSetup, cloudId?: string ) { - analytics.registerContextProvider({ + analytics.registerContextProvider({ name: 'user_id', context$: from(authc.getCurrentUser()).pipe( map((user) => { @@ -50,7 +55,7 @@ export function registerUserContext( schema: { userId: { type: 'keyword', - _meta: { description: 'The user id scoped as seen by Cloud (hashed)' }, + _meta: { description: 'The user id scoped as seen by Cloud (hashed)', optional: true }, }, isElasticCloudUser: { type: 'boolean', diff --git a/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.tsx b/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.tsx index 5899fb68ec3d3..9b35c7b1558f8 100644 --- a/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.tsx @@ -141,7 +141,7 @@ function usePrivileges( ); useEffect(() => { Promise.all([ - privilegesAPIClient.getAll({ includeActions: true }), + privilegesAPIClient.getAll({ includeActions: true, respectLicenseLevel: false }), privilegesAPIClient.getBuiltIn(), ]).then( ([kibanaPrivileges, builtInESPrivileges]) => diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/feature_table.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/feature_table.tsx index a506f8675bc11..505dd8e70024e 100644 --- a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/feature_table.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/feature_table.tsx @@ -216,7 +216,6 @@ export class FeatureTable extends Component { extraAction: EuiAccordionProps['extraAction'], infoIcon: JSX.Element ) => { - const { canCustomizeSubFeaturePrivileges } = this.props; const hasSubFeaturePrivileges = feature.getSubFeaturePrivileges().length > 0; return ( @@ -228,12 +227,8 @@ export class FeatureTable extends Component { data-test-subj="featurePrivilegeControls" buttonContent={buttonContent} extraAction={extraAction} - forceState={ - canCustomizeSubFeaturePrivileges && hasSubFeaturePrivileges ? undefined : 'closed' - } - arrowDisplay={ - canCustomizeSubFeaturePrivileges && hasSubFeaturePrivileges ? 'left' : 'none' - } + forceState={hasSubFeaturePrivileges ? undefined : 'closed'} + arrowDisplay={hasSubFeaturePrivileges ? 'left' : 'none'} onToggle={(isOpen: boolean) => { if (isOpen) { this.state.expandedPrivilegeControls.add(feature.id); @@ -256,6 +251,9 @@ export class FeatureTable extends Component { this.props.role.kibana[this.props.privilegeIndex].feature[feature.id] ?? [] } disabled={this.props.disabled} + licenseAllowsSubFeatPrivCustomization={ + this.props.canCustomizeSubFeaturePrivileges + } />
@@ -335,14 +333,10 @@ export class FeatureTable extends Component { ); } - const { canCustomizeSubFeaturePrivileges } = this.props; const hasSubFeaturePrivileges = feature.getSubFeaturePrivileges().length > 0; - - const showAccordionArrow = canCustomizeSubFeaturePrivileges && hasSubFeaturePrivileges; - const buttonContent = ( <> - {!showAccordionArrow && }{' '} + {!hasSubFeaturePrivileges && }{' '} ); diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/feature_table_expanded_row.test.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/feature_table_expanded_row.test.tsx index 0503ec1bf75f9..8e435dc43ef20 100644 --- a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/feature_table_expanded_row.test.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/feature_table_expanded_row.test.tsx @@ -25,6 +25,75 @@ const createRole = (kibana: Role['kibana'] = []): Role => { }; describe('FeatureTableExpandedRow', () => { + it('indicates sub-feature privileges are not customizable when licenseAllowsSubFeatPrivCustomization is false', () => { + const role = createRole([ + { + base: [], + feature: { + with_sub_features: ['minimal_read'], + }, + spaces: ['foo'], + }, + ]); + const kibanaPrivileges = createKibanaPrivileges(kibanaFeatures); + + const calculator = new PrivilegeFormCalculator(kibanaPrivileges, role); + + const feature = kibanaPrivileges.getSecuredFeature('with_sub_features'); + + const wrapper = mountWithIntl( + + ); + + expect( + wrapper.find('EuiSwitch[data-test-subj="customizeSubFeaturePrivileges"]').props() + ).toMatchObject({ + disabled: true, + checked: false, + }); + + expect(wrapper.find('EuiIconTip[data-test-subj="subFeaturesTip"]').length).toBe(1); + }); + + it('indicates sub-feature privileges can be customized when licenseAllowsSubFeatPrivCustomization is true', () => { + const role = createRole([ + { + base: [], + feature: { + with_sub_features: ['minimal_read'], + }, + spaces: ['foo'], + }, + ]); + const kibanaPrivileges = createKibanaPrivileges(kibanaFeatures); + + const calculator = new PrivilegeFormCalculator(kibanaPrivileges, role); + + const feature = kibanaPrivileges.getSecuredFeature('with_sub_features'); + + const wrapper = mountWithIntl( + + ); + + expect( + wrapper.find('EuiIconTip[data-test-subj="cannotCustomizeSubFeaturesTooltip"]').length + ).toBe(0); + }); + it('indicates sub-feature privileges are being customized if a minimal feature privilege is set', () => { const role = createRole([ { @@ -48,6 +117,7 @@ describe('FeatureTableExpandedRow', () => { privilegeCalculator={calculator} selectedFeaturePrivileges={['minimal_read']} onChange={jest.fn()} + licenseAllowsSubFeatPrivCustomization={true} /> ); @@ -82,6 +152,7 @@ describe('FeatureTableExpandedRow', () => { privilegeCalculator={calculator} selectedFeaturePrivileges={['read']} onChange={jest.fn()} + licenseAllowsSubFeatPrivCustomization={true} /> ); @@ -114,6 +185,7 @@ describe('FeatureTableExpandedRow', () => { privilegeCalculator={calculator} selectedFeaturePrivileges={['read']} onChange={jest.fn()} + licenseAllowsSubFeatPrivCustomization={true} /> ); @@ -150,6 +222,7 @@ describe('FeatureTableExpandedRow', () => { privilegeCalculator={calculator} selectedFeaturePrivileges={['read']} onChange={onChange} + licenseAllowsSubFeatPrivCustomization={true} /> ); @@ -189,6 +262,7 @@ describe('FeatureTableExpandedRow', () => { privilegeCalculator={calculator} selectedFeaturePrivileges={['minimal_read', 'cool_read', 'cool_toggle_2']} onChange={onChange} + licenseAllowsSubFeatPrivCustomization={true} /> ); diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/feature_table_expanded_row.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/feature_table_expanded_row.tsx index 50f2b8c504ee7..a0726ad2ef566 100644 --- a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/feature_table_expanded_row.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/feature_table_expanded_row.tsx @@ -6,9 +6,10 @@ */ import type { EuiSwitchEvent } from '@elastic/eui'; -import { EuiFlexGroup, EuiFlexItem, EuiSwitch } from '@elastic/eui'; +import { EuiFlexGroup, EuiFlexItem, EuiIconTip, EuiSwitch } from '@elastic/eui'; import React, { useEffect, useState } from 'react'; +import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import type { SecuredFeature } from '../../../../model'; @@ -21,6 +22,7 @@ interface Props { privilegeIndex: number; selectedFeaturePrivileges: string[]; disabled?: boolean; + licenseAllowsSubFeatPrivCustomization: boolean; onChange: (featureId: string, featurePrivileges: string[]) => void; } @@ -31,11 +33,13 @@ export const FeatureTableExpandedRow = ({ privilegeCalculator, selectedFeaturePrivileges, disabled, + licenseAllowsSubFeatPrivCustomization, }: Props) => { const [isCustomizing, setIsCustomizing] = useState(() => { - return feature - .getMinimalFeaturePrivileges() - .some((p) => selectedFeaturePrivileges.includes(p.id)); + return ( + licenseAllowsSubFeatPrivCustomization && + feature.getMinimalFeaturePrivileges().some((p) => selectedFeaturePrivileges.includes(p.id)) + ); }); useEffect(() => { @@ -43,10 +47,13 @@ export const FeatureTableExpandedRow = ({ .getMinimalFeaturePrivileges() .some((p) => selectedFeaturePrivileges.includes(p.id)); - if (!hasMinimalFeaturePrivilegeSelected && isCustomizing) { + if ( + (!licenseAllowsSubFeatPrivCustomization || !hasMinimalFeaturePrivilegeSelected) && + isCustomizing + ) { setIsCustomizing(false); } - }, [feature, isCustomizing, selectedFeaturePrivileges]); + }, [feature, isCustomizing, selectedFeaturePrivileges, licenseAllowsSubFeatPrivCustomization]); const onCustomizeSubFeatureChange = (e: EuiSwitchEvent) => { onChange( @@ -63,21 +70,44 @@ export const FeatureTableExpandedRow = ({ return ( - + + } + checked={isCustomizing} + onChange={onCustomizeSubFeatureChange} + data-test-subj="customizeSubFeaturePrivileges" + disabled={ + disabled || + !licenseAllowsSubFeatPrivCustomization || + !privilegeCalculator.canCustomizeSubFeaturePrivileges(feature.id, privilegeIndex) + } + /> + {licenseAllowsSubFeatPrivCustomization ? undefined : ( + - } - checked={isCustomizing} - onChange={onCustomizeSubFeatureChange} - data-test-subj="customizeSubFeaturePrivileges" - disabled={ - disabled || - !privilegeCalculator.canCustomizeSubFeaturePrivileges(feature.id, privilegeIndex) - } - /> + )} +
{feature.getSubFeatures().map((subFeature) => { return ( diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_space_form.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_space_form.tsx index 52b8025b2b668..a26b9587d450a 100644 --- a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_space_form.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/space_aware_privilege_section/privilege_space_form.tsx @@ -547,6 +547,7 @@ export class PrivilegeSpaceForm extends Component { } }); } + this.setState({ role, privilegeCalculator: new PrivilegeFormCalculator(this.props.kibanaPrivileges, role), diff --git a/x-pack/plugins/security/public/management/roles/privileges_api_client.ts b/x-pack/plugins/security/public/management/roles/privileges_api_client.ts index b4b372faec710..a96fdd4340cc6 100644 --- a/x-pack/plugins/security/public/management/roles/privileges_api_client.ts +++ b/x-pack/plugins/security/public/management/roles/privileges_api_client.ts @@ -12,9 +12,19 @@ import type { BuiltinESPrivileges, RawKibanaPrivileges } from '../../../common/m export class PrivilegesAPIClient { constructor(private readonly http: HttpStart) {} - async getAll({ includeActions }: { includeActions: boolean }) { + /* + * respectLicenseLevel is an internal optional parameter soley for getting all sub-feature + * privilieges to use in the UI. It is not meant for any other use. + */ + async getAll({ + includeActions, + respectLicenseLevel = true, + }: { + includeActions: boolean; + respectLicenseLevel: boolean; + }) { return await this.http.get('/api/security/privileges', { - query: { includeActions }, + query: { includeActions, respectLicenseLevel }, }); } diff --git a/x-pack/plugins/security/public/plugin.tsx b/x-pack/plugins/security/public/plugin.tsx index 2a91479824062..c56c40f63b4d0 100644 --- a/x-pack/plugins/security/public/plugin.tsx +++ b/x-pack/plugins/security/public/plugin.tsx @@ -113,6 +113,7 @@ export class SecurityPlugin analytics: core.analytics, authc: this.authc, cloudId: cloud?.cloudId, + http: core.http, securityLicense: license, }); diff --git a/x-pack/plugins/security/server/authorization/privileges/privileges.test.ts b/x-pack/plugins/security/server/authorization/privileges/privileges.test.ts index 1a8d7814e5a38..17a157263cf52 100644 --- a/x-pack/plugins/security/server/authorization/privileges/privileges.test.ts +++ b/x-pack/plugins/security/server/authorization/privileges/privileges.test.ts @@ -1888,6 +1888,225 @@ describe('subFeatures', () => { actions.ui.get('foo', 'sub-feature-ui'), ]); }); + + test(`should get the sub-feature privileges if 'respectLicenseLevel' is false`, () => { + const features: KibanaFeature[] = [ + new KibanaFeature({ + id: 'foo', + name: 'Foo KibanaFeature', + app: [], + category: { id: 'foo', label: 'foo' }, + privileges: { + all: { + savedObject: { + all: [], + read: [], + }, + ui: ['foo'], + }, + read: { + savedObject: { + all: [], + read: [], + }, + ui: ['foo'], + }, + }, + subFeatures: [ + { + name: 'subFeature1', + privilegeGroups: [ + { + groupType: 'independent', + privileges: [ + { + id: 'subFeaturePriv1', + name: 'sub feature priv 1', + includeIn: 'read', + savedObject: { + all: ['all-sub-feature-type'], + read: ['read-sub-feature-type'], + }, + ui: ['sub-feature-ui'], + }, + ], + }, + ], + }, + ], + }), + ]; + + const mockFeaturesPlugin = featuresPluginMock.createSetup(); + mockFeaturesPlugin.getKibanaFeatures.mockReturnValue(features); + const privileges = privilegesFactory(actions, mockFeaturesPlugin, mockLicenseServiceBasic); + + const actual = privileges.get(false); + expect(actual.features).toHaveProperty(`foo.subFeaturePriv1`); + + expect(actual.features).toHaveProperty(`foo.all`, [ + actions.login, + actions.version, + actions.savedObject.get('all-sub-feature-type', 'bulk_get'), + actions.savedObject.get('all-sub-feature-type', 'get'), + actions.savedObject.get('all-sub-feature-type', 'find'), + actions.savedObject.get('all-sub-feature-type', 'open_point_in_time'), + actions.savedObject.get('all-sub-feature-type', 'close_point_in_time'), + actions.savedObject.get('all-sub-feature-type', 'create'), + actions.savedObject.get('all-sub-feature-type', 'bulk_create'), + actions.savedObject.get('all-sub-feature-type', 'update'), + actions.savedObject.get('all-sub-feature-type', 'bulk_update'), + actions.savedObject.get('all-sub-feature-type', 'delete'), + actions.savedObject.get('all-sub-feature-type', 'bulk_delete'), + actions.savedObject.get('all-sub-feature-type', 'share_to_space'), + actions.savedObject.get('read-sub-feature-type', 'bulk_get'), + actions.savedObject.get('read-sub-feature-type', 'get'), + actions.savedObject.get('read-sub-feature-type', 'find'), + actions.savedObject.get('read-sub-feature-type', 'open_point_in_time'), + actions.savedObject.get('read-sub-feature-type', 'close_point_in_time'), + actions.ui.get('foo', 'foo'), + actions.ui.get('foo', 'sub-feature-ui'), + ]); + + expect(actual.features).toHaveProperty(`foo.minimal_all`, [ + actions.login, + actions.version, + actions.ui.get('foo', 'foo'), + ]); + + expect(actual.features).toHaveProperty(`foo.read`, [ + actions.login, + actions.version, + actions.savedObject.get('all-sub-feature-type', 'bulk_get'), + actions.savedObject.get('all-sub-feature-type', 'get'), + actions.savedObject.get('all-sub-feature-type', 'find'), + actions.savedObject.get('all-sub-feature-type', 'open_point_in_time'), + actions.savedObject.get('all-sub-feature-type', 'close_point_in_time'), + actions.savedObject.get('all-sub-feature-type', 'create'), + actions.savedObject.get('all-sub-feature-type', 'bulk_create'), + actions.savedObject.get('all-sub-feature-type', 'update'), + actions.savedObject.get('all-sub-feature-type', 'bulk_update'), + actions.savedObject.get('all-sub-feature-type', 'delete'), + actions.savedObject.get('all-sub-feature-type', 'bulk_delete'), + actions.savedObject.get('all-sub-feature-type', 'share_to_space'), + actions.savedObject.get('read-sub-feature-type', 'bulk_get'), + actions.savedObject.get('read-sub-feature-type', 'get'), + actions.savedObject.get('read-sub-feature-type', 'find'), + actions.savedObject.get('read-sub-feature-type', 'open_point_in_time'), + actions.savedObject.get('read-sub-feature-type', 'close_point_in_time'), + actions.ui.get('foo', 'foo'), + actions.ui.get('foo', 'sub-feature-ui'), + ]); + + expect(actual.features).toHaveProperty(`foo.minimal_read`, [ + actions.login, + actions.version, + actions.ui.get('foo', 'foo'), + ]); + + expect(actual).toHaveProperty('global.all', [ + actions.login, + actions.version, + actions.api.get('decryptedTelemetry'), + actions.api.get('features'), + actions.api.get('taskManager'), + actions.space.manage, + actions.ui.get('spaces', 'manage'), + actions.ui.get('management', 'kibana', 'spaces'), + actions.ui.get('catalogue', 'spaces'), + actions.ui.get('enterpriseSearch', 'all'), + actions.savedObject.get('all-sub-feature-type', 'bulk_get'), + actions.savedObject.get('all-sub-feature-type', 'get'), + actions.savedObject.get('all-sub-feature-type', 'find'), + actions.savedObject.get('all-sub-feature-type', 'open_point_in_time'), + actions.savedObject.get('all-sub-feature-type', 'close_point_in_time'), + actions.savedObject.get('all-sub-feature-type', 'create'), + actions.savedObject.get('all-sub-feature-type', 'bulk_create'), + actions.savedObject.get('all-sub-feature-type', 'update'), + actions.savedObject.get('all-sub-feature-type', 'bulk_update'), + actions.savedObject.get('all-sub-feature-type', 'delete'), + actions.savedObject.get('all-sub-feature-type', 'bulk_delete'), + actions.savedObject.get('all-sub-feature-type', 'share_to_space'), + actions.savedObject.get('read-sub-feature-type', 'bulk_get'), + actions.savedObject.get('read-sub-feature-type', 'get'), + actions.savedObject.get('read-sub-feature-type', 'find'), + actions.savedObject.get('read-sub-feature-type', 'open_point_in_time'), + actions.savedObject.get('read-sub-feature-type', 'close_point_in_time'), + actions.ui.get('foo', 'foo'), + actions.ui.get('foo', 'sub-feature-ui'), + ]); + expect(actual).toHaveProperty('global.read', [ + actions.login, + actions.version, + actions.api.get('decryptedTelemetry'), + actions.savedObject.get('all-sub-feature-type', 'bulk_get'), + actions.savedObject.get('all-sub-feature-type', 'get'), + actions.savedObject.get('all-sub-feature-type', 'find'), + actions.savedObject.get('all-sub-feature-type', 'open_point_in_time'), + actions.savedObject.get('all-sub-feature-type', 'close_point_in_time'), + actions.savedObject.get('all-sub-feature-type', 'create'), + actions.savedObject.get('all-sub-feature-type', 'bulk_create'), + actions.savedObject.get('all-sub-feature-type', 'update'), + actions.savedObject.get('all-sub-feature-type', 'bulk_update'), + actions.savedObject.get('all-sub-feature-type', 'delete'), + actions.savedObject.get('all-sub-feature-type', 'bulk_delete'), + actions.savedObject.get('all-sub-feature-type', 'share_to_space'), + actions.savedObject.get('read-sub-feature-type', 'bulk_get'), + actions.savedObject.get('read-sub-feature-type', 'get'), + actions.savedObject.get('read-sub-feature-type', 'find'), + actions.savedObject.get('read-sub-feature-type', 'open_point_in_time'), + actions.savedObject.get('read-sub-feature-type', 'close_point_in_time'), + actions.ui.get('foo', 'foo'), + actions.ui.get('foo', 'sub-feature-ui'), + ]); + + expect(actual).toHaveProperty('space.all', [ + actions.login, + actions.version, + actions.savedObject.get('all-sub-feature-type', 'bulk_get'), + actions.savedObject.get('all-sub-feature-type', 'get'), + actions.savedObject.get('all-sub-feature-type', 'find'), + actions.savedObject.get('all-sub-feature-type', 'open_point_in_time'), + actions.savedObject.get('all-sub-feature-type', 'close_point_in_time'), + actions.savedObject.get('all-sub-feature-type', 'create'), + actions.savedObject.get('all-sub-feature-type', 'bulk_create'), + actions.savedObject.get('all-sub-feature-type', 'update'), + actions.savedObject.get('all-sub-feature-type', 'bulk_update'), + actions.savedObject.get('all-sub-feature-type', 'delete'), + actions.savedObject.get('all-sub-feature-type', 'bulk_delete'), + actions.savedObject.get('all-sub-feature-type', 'share_to_space'), + actions.savedObject.get('read-sub-feature-type', 'bulk_get'), + actions.savedObject.get('read-sub-feature-type', 'get'), + actions.savedObject.get('read-sub-feature-type', 'find'), + actions.savedObject.get('read-sub-feature-type', 'open_point_in_time'), + actions.savedObject.get('read-sub-feature-type', 'close_point_in_time'), + actions.ui.get('foo', 'foo'), + actions.ui.get('foo', 'sub-feature-ui'), + ]); + expect(actual).toHaveProperty('space.read', [ + actions.login, + actions.version, + actions.savedObject.get('all-sub-feature-type', 'bulk_get'), + actions.savedObject.get('all-sub-feature-type', 'get'), + actions.savedObject.get('all-sub-feature-type', 'find'), + actions.savedObject.get('all-sub-feature-type', 'open_point_in_time'), + actions.savedObject.get('all-sub-feature-type', 'close_point_in_time'), + actions.savedObject.get('all-sub-feature-type', 'create'), + actions.savedObject.get('all-sub-feature-type', 'bulk_create'), + actions.savedObject.get('all-sub-feature-type', 'update'), + actions.savedObject.get('all-sub-feature-type', 'bulk_update'), + actions.savedObject.get('all-sub-feature-type', 'delete'), + actions.savedObject.get('all-sub-feature-type', 'bulk_delete'), + actions.savedObject.get('all-sub-feature-type', 'share_to_space'), + actions.savedObject.get('read-sub-feature-type', 'bulk_get'), + actions.savedObject.get('read-sub-feature-type', 'get'), + actions.savedObject.get('read-sub-feature-type', 'find'), + actions.savedObject.get('read-sub-feature-type', 'open_point_in_time'), + actions.savedObject.get('read-sub-feature-type', 'close_point_in_time'), + actions.ui.get('foo', 'foo'), + actions.ui.get('foo', 'sub-feature-ui'), + ]); + }); }); describe(`when license allows subfeatures, but not a specific sub feature`, () => { diff --git a/x-pack/plugins/security/server/authorization/privileges/privileges.ts b/x-pack/plugins/security/server/authorization/privileges/privileges.ts index 3684014fd5b1d..546a392c73e1e 100644 --- a/x-pack/plugins/security/server/authorization/privileges/privileges.ts +++ b/x-pack/plugins/security/server/authorization/privileges/privileges.ts @@ -18,7 +18,7 @@ import type { Actions } from '../actions'; import { featurePrivilegeBuilderFactory } from './feature_privilege_builder'; export interface PrivilegesService { - get(): RawKibanaPrivileges; + get(respectLicenseLevel?: boolean): RawKibanaPrivileges; } export function privilegesFactory( @@ -29,7 +29,7 @@ export function privilegesFactory( const featurePrivilegeBuilder = featurePrivilegeBuilderFactory(actions); return { - get() { + get(respectLicenseLevel: boolean = true) { const features = featuresService.getKibanaFeatures(); const { allowSubFeaturePrivileges } = licenseService.getFeatures(); const { hasAtLeast: licenseHasAtLeast } = licenseService; @@ -82,7 +82,10 @@ export function privilegesFactory( ]; } - if (allowSubFeaturePrivileges && feature.subFeatures?.length > 0) { + if ( + (!respectLicenseLevel || allowSubFeaturePrivileges) && + feature.subFeatures?.length > 0 + ) { for (const subFeaturePrivilege of featuresService.subFeaturePrivilegeIterator( feature, licenseHasAtLeast diff --git a/x-pack/plugins/security/server/routes/authorization/privileges/get.ts b/x-pack/plugins/security/server/routes/authorization/privileges/get.ts index 8724323fdf510..8817fca4831ae 100644 --- a/x-pack/plugins/security/server/routes/authorization/privileges/get.ts +++ b/x-pack/plugins/security/server/routes/authorization/privileges/get.ts @@ -21,11 +21,15 @@ export function defineGetPrivilegesRoutes({ router, authz }: RouteDefinitionPara includeActions: schema.maybe( schema.oneOf([schema.literal('true'), schema.literal('false')]) ), + respectLicenseLevel: schema.maybe( + schema.oneOf([schema.literal('true'), schema.literal('false')]) + ), }), }, }, createLicensedRouteHandler((context, request, response) => { - const privileges = authz.privileges.get(); + const respectLicenseLevel = request.query.respectLicenseLevel !== 'false'; // if undefined resolve to true by default + const privileges = authz.privileges.get(respectLicenseLevel); const includeActions = request.query.includeActions === 'true'; const privilegesResponseBody = includeActions ? privileges diff --git a/x-pack/plugins/security_solution/common/endpoint/constants.ts b/x-pack/plugins/security_solution/common/endpoint/constants.ts index 19df6122044a4..2d8f468233f0d 100644 --- a/x-pack/plugins/security_solution/common/endpoint/constants.ts +++ b/x-pack/plugins/security_solution/common/endpoint/constants.ts @@ -67,6 +67,7 @@ export const UNISOLATE_HOST_ROUTE_V2 = `${BASE_ENDPOINT_ACTION_ROUTE}/unisolate` export const GET_PROCESSES_ROUTE = `${BASE_ENDPOINT_ACTION_ROUTE}/running_procs`; export const KILL_PROCESS_ROUTE = `${BASE_ENDPOINT_ACTION_ROUTE}/kill_process`; export const SUSPEND_PROCESS_ROUTE = `${BASE_ENDPOINT_ACTION_ROUTE}/suspend_process`; +export const GET_FILE_ROUTE = `${BASE_ENDPOINT_ACTION_ROUTE}/get_file`; /** Endpoint Actions Routes */ export const ENDPOINT_ACTION_LOG_ROUTE = `${BASE_ENDPOINT_ROUTE}/action_log/{agent_id}`; @@ -78,26 +79,3 @@ export const failedFleetActionErrorCode = '424'; export const ENDPOINT_DEFAULT_PAGE = 0; export const ENDPOINT_DEFAULT_PAGE_SIZE = 10; - -/** - * The list of possible capabilities, reported by the endpoint in the metadata document - */ -export const RESPONDER_CAPABILITIES = [ - 'isolation', - 'kill_process', - 'suspend_process', - 'running_processes', -] as const; - -export type ResponderCapabilities = typeof RESPONDER_CAPABILITIES[number]; - -/** The list of possible responder command names **/ -export const RESPONDER_COMMANDS = [ - 'isolate', - 'release', - 'kill-process', - 'suspend-process', - 'processes', -] as const; - -export type ResponderCommands = typeof RESPONDER_COMMANDS[number]; diff --git a/x-pack/plugins/security_solution/common/endpoint/data_generators/endpoint_action_generator.ts b/x-pack/plugins/security_solution/common/endpoint/data_generators/endpoint_action_generator.ts index 971f096300e66..79a02f79c5008 100644 --- a/x-pack/plugins/security_solution/common/endpoint/data_generators/endpoint_action_generator.ts +++ b/x-pack/plugins/security_solution/common/endpoint/data_generators/endpoint_action_generator.ts @@ -22,7 +22,7 @@ import type { ActionResponseOutput, } from '../types'; import { ActivityLogItemTypes } from '../types'; -import { RESPONSE_ACTION_COMMANDS } from '../service/response_actions/constants'; +import { RESPONSE_ACTION_API_COMMANDS_NAMES } from '../service/response_actions/constants'; export class EndpointActionGenerator extends BaseDataGenerator { /** Generate a random endpoint Action request (isolate or unisolate) */ @@ -245,6 +245,6 @@ export class EndpointActionGenerator extends BaseDataGenerator { } protected randomResponseActionCommand() { - return this.randomChoice(RESPONSE_ACTION_COMMANDS); + return this.randomChoice(RESPONSE_ACTION_API_COMMANDS_NAMES); } } diff --git a/x-pack/plugins/security_solution/common/endpoint/data_generators/endpoint_metadata_generator.ts b/x-pack/plugins/security_solution/common/endpoint/data_generators/endpoint_metadata_generator.ts index 67ff2d3605093..3c370dc99aa62 100644 --- a/x-pack/plugins/security_solution/common/endpoint/data_generators/endpoint_metadata_generator.ts +++ b/x-pack/plugins/security_solution/common/endpoint/data_generators/endpoint_metadata_generator.ts @@ -8,6 +8,7 @@ import type { DeepPartial } from 'utility-types'; import { merge } from 'lodash'; import { gte } from 'semver'; +import type { EndpointCapabilities } from '../service/response_actions/constants'; import { BaseDataGenerator } from './base_data_generator'; import type { HostMetadataInterface, OSFields } from '../types'; import { EndpointStatus, HostPolicyResponseActionStatus } from '../types'; @@ -23,13 +24,17 @@ export class EndpointMetadataGenerator extends BaseDataGenerator { const agentVersion = overrides?.agent?.version ?? this.randomVersion(); const agentId = this.seededUUIDv4(); const isIsolated = this.randomBoolean(0.3); - const capabilities = ['isolation']; + const capabilities: EndpointCapabilities[] = ['isolation']; // v8.4 introduced additional endpoint capabilities if (gte(agentVersion, '8.4.0')) { capabilities.push('kill_process', 'suspend_process', 'running_processes'); } + if (gte(agentVersion, '8.6.0')) { + capabilities.push('get_file'); + } + const hostMetadataDoc: HostMetadataInterface = { '@timestamp': ts, event: { diff --git a/x-pack/plugins/security_solution/common/endpoint/data_generators/fleet_action_generator.ts b/x-pack/plugins/security_solution/common/endpoint/data_generators/fleet_action_generator.ts index f1d81c902a4a8..215a8d5b339cf 100644 --- a/x-pack/plugins/security_solution/common/endpoint/data_generators/fleet_action_generator.ts +++ b/x-pack/plugins/security_solution/common/endpoint/data_generators/fleet_action_generator.ts @@ -17,7 +17,7 @@ import type { EndpointActionResponse, } from '../types'; import { ActivityLogItemTypes } from '../types'; -import { RESPONSE_ACTION_COMMANDS } from '../service/response_actions/constants'; +import { RESPONSE_ACTION_API_COMMANDS_NAMES } from '../service/response_actions/constants'; export class FleetActionGenerator extends BaseDataGenerator { /** Generate a random endpoint Action (isolate or unisolate) */ @@ -143,6 +143,6 @@ export class FleetActionGenerator extends BaseDataGenerator { } protected randomResponseActionCommand() { - return this.randomChoice(RESPONSE_ACTION_COMMANDS); + return this.randomChoice(RESPONSE_ACTION_API_COMMANDS_NAMES); } } diff --git a/x-pack/plugins/security_solution/common/endpoint/schema/actions.ts b/x-pack/plugins/security_solution/common/endpoint/schema/actions.ts index 8b982e6e6f463..0a7c401e3a589 100644 --- a/x-pack/plugins/security_solution/common/endpoint/schema/actions.ts +++ b/x-pack/plugins/security_solution/common/endpoint/schema/actions.ts @@ -9,7 +9,7 @@ import type { TypeOf } from '@kbn/config-schema'; import { schema } from '@kbn/config-schema'; import { ENDPOINT_DEFAULT_PAGE_SIZE } from '../constants'; import { - RESPONSE_ACTION_COMMANDS, + RESPONSE_ACTION_API_COMMANDS_NAMES, RESPONSE_ACTION_STATUS, } from '../service/response_actions/constants'; @@ -78,7 +78,7 @@ export const ActionDetailsRequestSchema = { // TODO: fix the odd TS error const commandsSchema = schema.oneOf( // @ts-expect-error TS2769: No overload matches this call - RESPONSE_ACTION_COMMANDS.map((command) => schema.literal(command)) + RESPONSE_ACTION_API_COMMANDS_NAMES.map((command) => schema.literal(command)) ); // TODO: fix the odd TS error @@ -115,3 +115,13 @@ export const EndpointActionListRequestSchema = { }; export type EndpointActionListRequestQuery = TypeOf; + +export const EndpointActionGetFileSchema = { + body: schema.object({ + ...BaseActionRequestSchema, + + parameters: schema.object({ + path: schema.string({ minLength: 1 }), + }), + }), +}; diff --git a/x-pack/plugins/security_solution/common/endpoint/service/authz/authz.test.ts b/x-pack/plugins/security_solution/common/endpoint/service/authz/authz.test.ts index e5b2f78c25472..e00434559b9ca 100644 --- a/x-pack/plugins/security_solution/common/endpoint/service/authz/authz.test.ts +++ b/x-pack/plugins/security_solution/common/endpoint/service/authz/authz.test.ts @@ -5,7 +5,13 @@ * 2.0. */ -import { calculateEndpointAuthz, getEndpointAuthzInitialState } from './authz'; +import { + calculateEndpointAuthz, + calculatePermissionsFromCapabilities, + calculatePermissionsFromPrivileges, + defaultEndpointPermissions, + getEndpointAuthzInitialState, +} from './authz'; import type { FleetAuthz } from '@kbn/fleet-plugin/common'; import { createFleetAuthzMock } from '@kbn/fleet-plugin/common'; import { createLicenseServiceMock } from '../../../license/mocks'; @@ -168,11 +174,31 @@ describe('Endpoint Authz service', () => { expect(authz[auth]).toBe(false); }); }); + + it('correctly handles permissions', () => { + const authz = calculateEndpointAuthz(licenseService, fleetAuthz, userRoles, true, { + canWriteSecuritySolution: false, + canReadSecuritySolution: true, + }); + expect(authz.canWriteSecuritySolution).toBe(false); + expect(authz.canReadSecuritySolution).toBe(true); + }); + }); + + describe('defaultEndpointPermissions', () => { + it('returns expected permissions', () => { + expect(defaultEndpointPermissions()).toEqual({ + canWriteSecuritySolution: false, + canReadSecuritySolution: false, + }); + }); }); describe('getEndpointAuthzInitialState()', () => { it('returns expected initial state', () => { expect(getEndpointAuthzInitialState()).toEqual({ + canWriteSecuritySolution: false, + canReadSecuritySolution: false, canAccessFleet: false, canAccessEndpointManagement: false, canCreateArtifactsByPolicy: false, @@ -200,4 +226,49 @@ describe('Endpoint Authz service', () => { }); }); }); + + describe('calculatePermissionsFromPrivileges', () => { + it('returns default permissions if no privileges', () => { + const permissions = calculatePermissionsFromPrivileges(undefined); + expect(permissions).toEqual(defaultEndpointPermissions()); + }); + + it('returns expected permissions from privileges', () => { + const privileges = [ + { privilege: 'ui:8.6.0:siem/crud', authorized: false }, + { privilege: 'ui:8.6.0:siem/show', authorized: true }, + { privilege: 'ui:8.6.0:siem/foobar', authorized: true }, + ]; + const permissions = calculatePermissionsFromPrivileges(privileges); + expect(permissions).toEqual({ + canWriteSecuritySolution: false, + canReadSecuritySolution: true, + }); + }); + }); + + describe('calculatePermissionsFromCapabilities', () => { + it('returns default permissions if no capabilities', () => { + const permissions = calculatePermissionsFromCapabilities(undefined); + expect(permissions).toEqual(defaultEndpointPermissions()); + }); + + it('returns expected permissions from capabilities', () => { + const capabilities = { + navLinks: {}, + management: {}, + catalogue: {}, + siem: { + crud: false, + show: true, + foobar: true, + }, + }; + const permissions = calculatePermissionsFromCapabilities(capabilities); + expect(permissions).toEqual({ + canWriteSecuritySolution: false, + canReadSecuritySolution: true, + }); + }); + }); }); diff --git a/x-pack/plugins/security_solution/common/endpoint/service/authz/authz.ts b/x-pack/plugins/security_solution/common/endpoint/service/authz/authz.ts index d25fd440d1c24..93b5289bdc391 100644 --- a/x-pack/plugins/security_solution/common/endpoint/service/authz/authz.ts +++ b/x-pack/plugins/security_solution/common/endpoint/service/authz/authz.ts @@ -5,18 +5,26 @@ * 2.0. */ -import type { ENDPOINT_PRIVILEGES } from '@kbn/fleet-plugin/common'; -import { type FleetAuthz } from '@kbn/fleet-plugin/common'; +import type { ENDPOINT_PRIVILEGES, FleetAuthz } from '@kbn/fleet-plugin/common'; +import type { Capabilities } from '@kbn/core-capabilities-common'; + import type { LicenseService } from '../../../license'; -import type { EndpointAuthz } from '../../types/authz'; +import type { EndpointPermissions, EndpointAuthz } from '../../types/authz'; import type { MaybeImmutable } from '../../types'; +export function defaultEndpointPermissions(): EndpointPermissions { + return { + canWriteSecuritySolution: false, + canReadSecuritySolution: false, + }; +} + function hasPermission( fleetAuthz: FleetAuthz, isEndpointRbacEnabled: boolean, hasEndpointManagementAccess: boolean, privilege: typeof ENDPOINT_PRIVILEGES[number] -) { +): boolean { return isEndpointRbacEnabled ? fleetAuthz.packagePrivileges?.endpoint?.actions[privilege].executePackageAction ?? false : hasEndpointManagementAccess; @@ -34,11 +42,13 @@ export const calculateEndpointAuthz = ( licenseService: LicenseService, fleetAuthz: FleetAuthz, userRoles: MaybeImmutable, - isEndpointRbacEnabled: boolean = false + isEndpointRbacEnabled: boolean = false, + permissions: Partial = defaultEndpointPermissions() ): EndpointAuthz => { const isPlatinumPlusLicense = licenseService.isPlatinumPlus(); const isEnterpriseLicense = licenseService.isEnterprise(); const hasEndpointManagementAccess = userRoles.includes('superuser'); + const { canWriteSecuritySolution = false, canReadSecuritySolution = false } = permissions; const canWriteEndpointList = hasPermission( fleetAuthz, isEndpointRbacEnabled, @@ -152,6 +162,8 @@ export const calculateEndpointAuthz = ( ); return { + canWriteSecuritySolution, + canReadSecuritySolution, canAccessFleet: fleetAuthz?.fleet.all ?? userRoles.includes('superuser'), canAccessEndpointManagement: hasEndpointManagementAccess, canCreateArtifactsByPolicy: hasEndpointManagementAccess && isPlatinumPlusLicense, @@ -160,14 +172,16 @@ export const calculateEndpointAuthz = ( canWritePolicyManagement, canReadPolicyManagement, canWriteActionsLogManagement, - canReadActionsLogManagement: canReadActionsLogManagement && isPlatinumPlusLicense, + canReadActionsLogManagement: canReadActionsLogManagement && isEnterpriseLicense, // Response Actions canIsolateHost: canIsolateHost && isPlatinumPlusLicense, canUnIsolateHost: canIsolateHost, canKillProcess: canWriteProcessOperations && isEnterpriseLicense, canSuspendProcess: canWriteProcessOperations && isEnterpriseLicense, canGetRunningProcesses: canWriteProcessOperations && isEnterpriseLicense, - canAccessResponseConsole: hasEndpointManagementAccess && isEnterpriseLicense, + canAccessResponseConsole: + isEnterpriseLicense && + (canIsolateHost || canWriteProcessOperations || canWriteFileOperations), canWriteFileOperations: canWriteFileOperations && isEnterpriseLicense, // artifacts canWriteTrustedApplications, @@ -183,6 +197,7 @@ export const calculateEndpointAuthz = ( export const getEndpointAuthzInitialState = (): EndpointAuthz => { return { + ...defaultEndpointPermissions(), canAccessFleet: false, canAccessEndpointManagement: false, canCreateArtifactsByPolicy: false, @@ -209,3 +224,66 @@ export const getEndpointAuthzInitialState = (): EndpointAuthz => { canReadEventFilters: false, }; }; + +const SIEM_PERMISSIONS = [ + { permission: 'canWriteSecuritySolution', privilege: 'crud' }, + { permission: 'canReadSecuritySolution', privilege: 'show' }, +] as const; + +function hasPrivilege( + kibanaPrivileges: Array<{ + resource?: string; + privilege: string; + authorized: boolean; + }>, + prefix: string, + searchPrivilege: string +): boolean { + const privilege = kibanaPrivileges.find((p) => + p.privilege.endsWith(`${prefix}${searchPrivilege}`) + ); + return privilege?.authorized || false; +} + +export function calculatePermissionsFromPrivileges( + kibanaPrivileges: + | Array<{ + resource?: string; + privilege: string; + authorized: boolean; + }> + | undefined +): EndpointPermissions { + if (!kibanaPrivileges || !kibanaPrivileges.length) { + return defaultEndpointPermissions(); + } + + const siemPermissions: EndpointPermissions = SIEM_PERMISSIONS.reduce( + (acc, { permission, privilege }) => { + return { + ...acc, + [permission]: hasPrivilege(kibanaPrivileges, 'siem/', privilege), + }; + }, + {} as EndpointPermissions + ); + + return { + ...siemPermissions, + }; +} + +export function calculatePermissionsFromCapabilities( + capabilities: Capabilities | undefined +): EndpointPermissions { + if (!capabilities || !capabilities.siem) { + return defaultEndpointPermissions(); + } + + return SIEM_PERMISSIONS.reduce((acc, { permission, privilege }) => { + return { + ...acc, + [permission]: capabilities.siem[privilege] || false, + }; + }, {} as EndpointPermissions); +} diff --git a/x-pack/plugins/security_solution/common/endpoint/service/authz/index.ts b/x-pack/plugins/security_solution/common/endpoint/service/authz/index.ts index 03d14a0945184..e1e2d241754e9 100644 --- a/x-pack/plugins/security_solution/common/endpoint/service/authz/index.ts +++ b/x-pack/plugins/security_solution/common/endpoint/service/authz/index.ts @@ -5,4 +5,10 @@ * 2.0. */ -export { getEndpointAuthzInitialState, calculateEndpointAuthz } from './authz'; +export { + getEndpointAuthzInitialState, + calculateEndpointAuthz, + calculatePermissionsFromPrivileges, + calculatePermissionsFromCapabilities, + defaultEndpointPermissions, +} from './authz'; diff --git a/x-pack/plugins/security_solution/common/endpoint/service/response_actions/constants.ts b/x-pack/plugins/security_solution/common/endpoint/service/response_actions/constants.ts index 5a22f37e0e006..06072813956b4 100644 --- a/x-pack/plugins/security_solution/common/endpoint/service/response_actions/constants.ts +++ b/x-pack/plugins/security_solution/common/endpoint/service/response_actions/constants.ts @@ -7,7 +7,10 @@ export const RESPONSE_ACTION_STATUS = ['failed', 'pending', 'successful'] as const; export type ResponseActionStatus = typeof RESPONSE_ACTION_STATUS[number]; -export const RESPONSE_ACTION_COMMANDS = [ +/** + * The Command names that are used in the API payload for the `{ command: '' }` attribute + */ +export const RESPONSE_ACTION_API_COMMANDS_NAMES = [ 'isolate', 'unisolate', 'kill-process', @@ -15,4 +18,33 @@ export const RESPONSE_ACTION_COMMANDS = [ 'running-processes', 'get-file', ] as const; -export type ResponseActions = typeof RESPONSE_ACTION_COMMANDS[number]; + +export type ResponseActionsApiCommandNames = typeof RESPONSE_ACTION_API_COMMANDS_NAMES[number]; + +/** + * The list of possible capabilities, reported by the endpoint in the metadata document + */ +export const ENDPOINT_CAPABILITIES = [ + 'isolation', + 'kill_process', + 'suspend_process', + 'running_processes', + 'get_file', +] as const; + +export type EndpointCapabilities = typeof ENDPOINT_CAPABILITIES[number]; + +/** + * The list of possible console command names that generate a Response Action to be dispatched + * to the Endpoint. (FYI: not all console commands are response actions) + */ +export const CONSOLE_RESPONSE_ACTION_COMMANDS = [ + 'isolate', + 'release', + 'kill-process', + 'suspend-process', + 'processes', + 'get-file', +] as const; + +export type ConsoleResponseActionCommands = typeof CONSOLE_RESPONSE_ACTION_COMMANDS[number]; diff --git a/x-pack/plugins/security_solution/common/endpoint/types/actions.ts b/x-pack/plugins/security_solution/common/endpoint/types/actions.ts index 40a65e886fb6d..53c6c0ae245cb 100644 --- a/x-pack/plugins/security_solution/common/endpoint/types/actions.ts +++ b/x-pack/plugins/security_solution/common/endpoint/types/actions.ts @@ -12,7 +12,10 @@ import type { ResponseActionBodySchema, KillOrSuspendProcessRequestSchema, } from '../schema/actions'; -import type { ResponseActionStatus, ResponseActions } from '../service/response_actions/constants'; +import type { + ResponseActionStatus, + ResponseActionsApiCommandNames, +} from '../service/response_actions/constants'; export type ISOLATION_ACTIONS = 'isolate' | 'unisolate'; @@ -140,7 +143,7 @@ export interface EndpointActionData< T extends EndpointActionDataParameterTypes = never, TOutputContent extends object = object > { - command: ResponseActions; + command: ResponseActionsApiCommandNames; comment?: string; parameters?: T; output?: ActionResponseOutput; @@ -282,7 +285,7 @@ export interface ActionDetails { * The Endpoint type of action (ex. `isolate`, `release`) that is being requested to be * performed on the endpoint */ - command: ResponseActions; + command: ResponseActionsApiCommandNames; /** * Will be set to true only if action is not yet completed and elapsed time has exceeded * the request's expiration date diff --git a/x-pack/plugins/security_solution/common/endpoint/types/authz.ts b/x-pack/plugins/security_solution/common/endpoint/types/authz.ts index b8ca15d69d1a6..838edc695c540 100644 --- a/x-pack/plugins/security_solution/common/endpoint/types/authz.ts +++ b/x-pack/plugins/security_solution/common/endpoint/types/authz.ts @@ -5,11 +5,21 @@ * 2.0. */ +/** + * Endpoint permissions derived from Kibana capabilities and privileges + */ +export interface EndpointPermissions { + /** if user has write permissions to the security solution app */ + canWriteSecuritySolution: boolean; + /** if user has read permissions to the security solution app */ + canReadSecuritySolution: boolean; +} + /** * Set of Endpoint Specific privileges that control application authorization. This interface is * used both on the client and server for consistency */ -export interface EndpointAuthz { +export interface EndpointAuthz extends EndpointPermissions { /** If user has permissions to access Fleet */ canAccessFleet: boolean; /** If user has permissions to access Endpoint management (includes check to ensure they also have access to fleet) */ diff --git a/x-pack/plugins/security_solution/cypress/screens/alerts.ts b/x-pack/plugins/security_solution/cypress/screens/alerts.ts index db8596074ca99..2ceeaac0e8ca7 100644 --- a/x-pack/plugins/security_solution/cypress/screens/alerts.ts +++ b/x-pack/plugins/security_solution/cypress/screens/alerts.ts @@ -22,8 +22,6 @@ export const ALERT_SEVERITY = '[data-test-subj="formatted-field-kibana.alert.sev export const ALERT_DATA_GRID = '[data-test-subj="euiDataGridBody"]'; -export const ALERTS = '[data-test-subj="events-viewer-panel"][data-test-subj="event"]'; - export const ALERTS_COUNT = '[data-test-subj="events-viewer-panel"] [data-test-subj="server-side-event-count"]'; diff --git a/x-pack/plugins/security_solution/cypress/screens/alerts_details.ts b/x-pack/plugins/security_solution/cypress/screens/alerts_details.ts index ee8bbd66b771d..5963307075113 100644 --- a/x-pack/plugins/security_solution/cypress/screens/alerts_details.ts +++ b/x-pack/plugins/security_solution/cypress/screens/alerts_details.ts @@ -42,7 +42,7 @@ export const OVERVIEW_SEVERITY = '[data-test-subj="eventDetails"] [data-test-sub export const OVERVIEW_STATUS = '[data-test-subj="eventDetails"] [data-test-subj="alertStatus"]'; -export const SUMMARY_VIEW = '[data-test-subj="summary-view"]'; +const SUMMARY_VIEW = '[data-test-subj="summary-view"]'; export const TABLE_CELL = '.euiTableRowCell'; @@ -64,8 +64,6 @@ export const THREAT_DETAILS_VIEW = '[data-test-subj="threat-details-view-0"]'; export const THREAT_INTEL_TAB = '[data-test-subj="threatIntelTab"]'; -export const TITLE = '.euiTitle'; - export const UPDATE_ENRICHMENT_RANGE_BUTTON = '[data-test-subj="enrichment-button"]'; export const OVERVIEW_TAB = '[data-test-subj="overviewTab"]'; diff --git a/x-pack/plugins/security_solution/cypress/screens/alerts_detection_rules.ts b/x-pack/plugins/security_solution/cypress/screens/alerts_detection_rules.ts index f68f31750a890..8b717d7f6bd22 100644 --- a/x-pack/plugins/security_solution/cypress/screens/alerts_detection_rules.ts +++ b/x-pack/plugins/security_solution/cypress/screens/alerts_detection_rules.ts @@ -78,8 +78,6 @@ export const RULES_MONITORING_TABLE = '[data-test-subj="allRulesTableTab-monitor export const SEVERITY = '[data-test-subj="severity"]'; -export const SHOWING_RULES_TEXT = '[data-test-subj="showingRules"]'; - export const SORT_RULES_BTN = '[data-test-subj="tableHeaderSortButton"]'; export const PAGINATION_POPOVER_BTN = '[data-test-subj="tablePaginationPopoverButton"]'; @@ -90,9 +88,6 @@ export const rowsPerPageSelector = (count: number) => export const pageSelector = (pageNumber: number) => `[data-test-subj="pagination-button-${pageNumber - 1}"]`; -export const ruleCheckboxByIdSelector = (id: string) => - `[data-test-subj="checkboxSelectRow-${id}"]`; - export const SELECT_ALL_RULES_BTN = '[data-test-subj="selectAllRules"]'; export const RULES_EMPTY_PROMPT = '[data-test-subj="rulesEmptyPrompt"]'; diff --git a/x-pack/plugins/security_solution/cypress/screens/create_new_rule.ts b/x-pack/plugins/security_solution/cypress/screens/create_new_rule.ts index 85f91188e6535..0d14673f4cf2b 100644 --- a/x-pack/plugins/security_solution/cypress/screens/create_new_rule.ts +++ b/x-pack/plugins/security_solution/cypress/screens/create_new_rule.ts @@ -125,10 +125,6 @@ export const MITRE_ATTACK_ADD_TECHNIQUE_BUTTON = '[data-test-subj="addMitreAttac export const MITRE_ATTACK_ADD_SUBTECHNIQUE_BUTTON = '[data-test-subj="addMitreAttackSubtechnique"]'; -export const PREVIEW_HEADER_SUBTITLE = '[data-test-subj="header-panel-subtitle"]'; - -export const QUERY_PREVIEW_BUTTON = '[data-test-subj="queryPreviewButton"]'; - export const REFERENCE_URLS_INPUT = '[data-test-subj="detectionEngineStepAboutRuleReferenceUrls"] input'; diff --git a/x-pack/plugins/security_solution/cypress/screens/date_picker.ts b/x-pack/plugins/security_solution/cypress/screens/date_picker.ts index 337a53650d250..b4d4e459871d8 100644 --- a/x-pack/plugins/security_solution/cypress/screens/date_picker.ts +++ b/x-pack/plugins/security_solution/cypress/screens/date_picker.ts @@ -30,8 +30,5 @@ export const SHOW_DATES_BUTTON = '[data-test-subj="superDatePickerShowDatesButto export const DATE_PICKER_SHOW_DATE_POPOVER_BUTTON = `${GLOBAL_FILTERS_CONTAINER} ${SHOW_DATES_BUTTON}`; -export const DATE_PICKER_RELATIVE_DATE_INPUT_UNIT_SELECTOR = - '[data-test-subj="superDatePickerRelativeDateInputUnitSelector"]'; - export const DATE_PICKER_START_DATE_POPOVER_BUTTON_TIMELINE = '[data-test-subj="timeline-date-picker-container"] [data-test-subj="superDatePickerstartDatePopoverButton"]'; diff --git a/x-pack/plugins/security_solution/cypress/screens/fields_browser.ts b/x-pack/plugins/security_solution/cypress/screens/fields_browser.ts index a7616e1792a65..d554d1195adef 100644 --- a/x-pack/plugins/security_solution/cypress/screens/fields_browser.ts +++ b/x-pack/plugins/security_solution/cypress/screens/fields_browser.ts @@ -18,7 +18,7 @@ export const FIELDS_BROWSER_FIELDS_COUNT = `${FIELDS_BROWSER_CONTAINER} [data-te export const FIELDS_BROWSER_FILTER_INPUT = `${FIELDS_BROWSER_CONTAINER} [data-test-subj="field-search"]`; export const FIELDS_BROWSER_VIEW_BUTTON = `${FIELDS_BROWSER_CONTAINER} [data-test-subj="viewSelectorButton"]`; -export const FIELDS_BROWSER_VIEW_MENU = '[data-test-subj="viewSelectorMenu"]'; +const FIELDS_BROWSER_VIEW_MENU = '[data-test-subj="viewSelectorMenu"]'; export const FIELDS_BROWSER_VIEW_ALL = `${FIELDS_BROWSER_VIEW_MENU} [data-test-subj="viewSelectorOption-all"]`; export const FIELDS_BROWSER_VIEW_SELECTED = `${FIELDS_BROWSER_VIEW_MENU} [data-test-subj="viewSelectorOption-selected"]`; diff --git a/x-pack/plugins/security_solution/cypress/screens/hosts/host_risk.ts b/x-pack/plugins/security_solution/cypress/screens/hosts/host_risk.ts index 8144f27565ad7..c9a1e0691f4fe 100644 --- a/x-pack/plugins/security_solution/cypress/screens/hosts/host_risk.ts +++ b/x-pack/plugins/security_solution/cypress/screens/hosts/host_risk.ts @@ -5,8 +5,6 @@ * 2.0. */ -export const RULE_NAME = '[data-test-subj="topRiskScoreContributors"] .euiTableCellContent'; - export const RISK_DETAILS_NAV = '[data-test-subj="navigation-hostRisk"]'; export const LOADING_SPINNER = '[data-test-subj="loading-spinner"]'; diff --git a/x-pack/plugins/security_solution/cypress/screens/overview.ts b/x-pack/plugins/security_solution/cypress/screens/overview.ts index 14bfce599dfaf..12de337a51aa3 100644 --- a/x-pack/plugins/security_solution/cypress/screens/overview.ts +++ b/x-pack/plugins/security_solution/cypress/screens/overview.ts @@ -6,67 +6,67 @@ */ // Host Stats -export const STAT_AUDITD = { +const STAT_AUDITD = { value: '1', domId: '[data-test-subj="host-stat-auditbeatAuditd"]', }; -export const ENDGAME_DNS = { +const ENDGAME_DNS = { value: '1', domId: '[data-test-subj="host-stat-endgameDns"]', }; -export const ENDGAME_FILE = { +const ENDGAME_FILE = { value: '1', domId: '[data-test-subj="host-stat-endgameFile"]', }; -export const ENDGAME_IMAGE_LOAD = { +const ENDGAME_IMAGE_LOAD = { value: '1', domId: '[data-test-subj="host-stat-endgameImageLoad"]', }; -export const ENDGAME_NETWORK = { +const ENDGAME_NETWORK = { value: '1', domId: '[data-test-subj="host-stat-endgameNetwork"]', }; -export const ENDGAME_PROCESS = { +const ENDGAME_PROCESS = { value: '1', domId: '[data-test-subj="host-stat-endgameProcess"]', }; -export const ENDGAME_REGISTRY = { +const ENDGAME_REGISTRY = { value: '1', domId: '[data-test-subj="host-stat-endgameRegistry"]', }; -export const ENDGAME_SECURITY = { +const ENDGAME_SECURITY = { value: '1', domId: '[data-test-subj="host-stat-endgameSecurity"]', }; -export const STAT_FILEBEAT = { +const STAT_FILEBEAT = { value: '1', domId: '[data-test-subj="host-stat-filebeatSystemModule"]', }; -export const STAT_FIM = { +const STAT_FIM = { value: '1', domId: '[data-test-subj="host-stat-auditbeatFIM"]', }; -export const STAT_LOGIN = { +const STAT_LOGIN = { value: '1', domId: '[data-test-subj="host-stat-auditbeatLogin"]', }; -export const STAT_PACKAGE = { +const STAT_PACKAGE = { value: '1', domId: '[data-test-subj="host-stat-auditbeatPackage"]', }; -export const STAT_PROCESS = { +const STAT_PROCESS = { value: '2', domId: '[data-test-subj="host-stat-auditbeatProcess"]', }; -export const STAT_USER = { +const STAT_USER = { value: '1', domId: '[data-test-subj="host-stat-auditbeatUser"]', }; -export const STAT_WINLOGBEAT_SECURITY = { +const STAT_WINLOGBEAT_SECURITY = { value: '1', domId: '[data-test-subj="host-stat-winlogbeatSecurity"]', }; -export const STAT_WINLOGBEAT_MWSYSMON_OPERATIONAL = { +const STAT_WINLOGBEAT_MWSYSMON_OPERATIONAL = { value: '1', domId: '[data-test-subj="host-stat-winlogbeatMWSysmonOperational"]', }; @@ -91,39 +91,39 @@ export const HOST_STATS = [ ]; // Network Stats -export const STAT_SOCKET = { +const STAT_SOCKET = { value: '1', domId: '[data-test-subj="network-stat-auditbeatSocket"]', }; -export const STAT_CISCO = { +const STAT_CISCO = { value: '1', domId: '[data-test-subj="network-stat-filebeatCisco"]', }; -export const STAT_NETFLOW = { +const STAT_NETFLOW = { value: '1', domId: '[data-test-subj="network-stat-filebeatNetflow"]', }; -export const STAT_PANW = { +const STAT_PANW = { value: '1', domId: '[data-test-subj="network-stat-filebeatPanw"]', }; -export const STAT_SURICATA = { +const STAT_SURICATA = { value: '1', domId: '[data-test-subj="network-stat-filebeatSuricata"]', }; -export const STAT_ZEEK = { +const STAT_ZEEK = { value: '1', domId: '[data-test-subj="network-stat-filebeatZeek"]', }; -export const STAT_DNS = { +const STAT_DNS = { value: '1', domId: '[data-test-subj="network-stat-packetbeatDNS"]', }; -export const STAT_FLOW = { +const STAT_FLOW = { value: '1', domId: '[data-test-subj="network-stat-packetbeatFlow"]', }; -export const STAT_TLS = { +const STAT_TLS = { value: '1', domId: '[data-test-subj="network-stat-packetbeatTLS"]', }; diff --git a/x-pack/plugins/security_solution/cypress/screens/rule_details.ts b/x-pack/plugins/security_solution/cypress/screens/rule_details.ts index 853e6036aac12..bad0770ffd763 100644 --- a/x-pack/plugins/security_solution/cypress/screens/rule_details.ts +++ b/x-pack/plugins/security_solution/cypress/screens/rule_details.ts @@ -28,8 +28,6 @@ export const SAVED_QUERY_DETAILS = /^Saved query$/; export const SAVED_QUERY_FILTERS_DETAILS = 'Saved query filters'; -export const FILTERS_DETAILS = 'Filters'; - export const DATA_VIEW_DETAILS = 'Data View'; export const DEFINITION_DETAILS = diff --git a/x-pack/plugins/security_solution/cypress/screens/rules_bulk_edit.ts b/x-pack/plugins/security_solution/cypress/screens/rules_bulk_edit.ts index f31d8ca86a824..9546b5da8ad8d 100644 --- a/x-pack/plugins/security_solution/cypress/screens/rules_bulk_edit.ts +++ b/x-pack/plugins/security_solution/cypress/screens/rules_bulk_edit.ts @@ -64,8 +64,6 @@ export const UPDATE_SCHEDULE_INTERVAL_INPUT = export const UPDATE_SCHEDULE_LOOKBACK_INPUT = '[data-test-subj="bulkEditRulesScheduleLookbackSelector"]'; -export const UPDATE_SCHEDULE_TIME_INTERVAL = '[data-test-subj="interval"]'; - export const UPDATE_SCHEDULE_TIME_UNIT_SELECT = '[data-test-subj="timeType"]'; export const RULES_BULK_EDIT_ACTIONS_THROTTLE_INPUT = diff --git a/x-pack/plugins/security_solution/cypress/screens/timeline.ts b/x-pack/plugins/security_solution/cypress/screens/timeline.ts index c2f83fe2b4760..529847261e06d 100644 --- a/x-pack/plugins/security_solution/cypress/screens/timeline.ts +++ b/x-pack/plugins/security_solution/cypress/screens/timeline.ts @@ -215,8 +215,6 @@ export const TIMELINE_KQLMODE_SEARCH = '[data-test-subj="kqlModePopoverSearch"]' export const TIMELINE_KQLMODE_FILTER = '[data-test-subj="kqlModePopoverFilter"]'; -export const QUERYBAR_MENU_POPOVER = '[data-test-subj="queryBarMenuPopover"]'; - export const TIMELINE_SHOWQUERYBARMENU_BUTTON = `${TIMELINE_FLYOUT} [data-test-subj="showQueryBarMenu"]`; export const TIMELINE_SWITCHQUERYLANGUAGE_BUTTON = '[data-test-subj="switchQueryLanguageButton"]'; @@ -247,7 +245,7 @@ export const TIMELINE_FLYOUT_WRAPPER = '[data-test-subj="flyout-pane"]'; export const TIMELINE_FULL_SCREEN_BUTTON = '[data-test-subj="full-screen-active"]'; -export const TIMELINE_ROW_RENDERERS_MODAL = '[data-test-subj="row-renderers-modal"]'; +const TIMELINE_ROW_RENDERERS_MODAL = '[data-test-subj="row-renderers-modal"]'; export const TIMELINE_ROW_RENDERERS_DISABLE_ALL_BTN = `[data-test-subj="disable-all"]`; @@ -293,14 +291,9 @@ export const ALERT_TABLE_CELL_ACTIONS_ADD_TO_TIMELINE = '[data-test-subj="add-to export const ACTIVE_TIMELINE_BOTTOM_BAR = '[data-test-subj="flyoutBottomBar"] .active-timeline-button'; -export const DATA_GRID_BODY = '[data-test-subj=body-data-grid] .euiDataGrid__virtualized'; - export const GET_TIMELINE_GRID_CELL = (fieldName: string) => `[data-test-subj="draggable-content-${fieldName}"]`; -export const GET_TIMELINE_GRID_HEADER = (fieldName: string) => - `[data-test-subj="header-${fieldName}"]`; - export const EMPTY_DROPPABLE_DATA_PROVIDER_GROUP = `.empty-providers-group`; export const TIMELINE_DATA_PROVIDERS_CONTAINER = '[data-test-subj="dataProviders"]'; diff --git a/x-pack/plugins/security_solution/cypress/screens/timelines.ts b/x-pack/plugins/security_solution/cypress/screens/timelines.ts index c9f06fa88b52f..40b75ad9c63be 100644 --- a/x-pack/plugins/security_solution/cypress/screens/timelines.ts +++ b/x-pack/plugins/security_solution/cypress/screens/timelines.ts @@ -46,7 +46,7 @@ export const TIMELINES_USERNAME = '[data-test-subj="username"]'; export const REFRESH_BUTTON = '[data-test-subj="refreshButton-linkIcon"]'; -export const TIMELINES_OVERVIEW = '[data-test-subj="timelines-container"]'; +const TIMELINES_OVERVIEW = '[data-test-subj="timelines-container"]'; export const TIMELINES_OVERVIEW_ONLY_FAVORITES = `${TIMELINES_OVERVIEW} [data-test-subj="only-favorites-toggle"]`; diff --git a/x-pack/plugins/security_solution/cypress/screens/users/user_risk_score.ts b/x-pack/plugins/security_solution/cypress/screens/users/user_risk_score.ts index 717cefb6190a8..816334d7fc197 100644 --- a/x-pack/plugins/security_solution/cypress/screens/users/user_risk_score.ts +++ b/x-pack/plugins/security_solution/cypress/screens/users/user_risk_score.ts @@ -7,4 +7,3 @@ export const RISK_SCORE_TAB = '[data-test-subj="navigation-userRisk"]'; export const RISK_SCORE_TAB_CONTENT = '[data-test-subj="table-userRisk-loading-false"]'; -export const RISK_SCORE_ENABLE_BUTTON = '[data-test-subj="enable_user_risk_score"]'; diff --git a/x-pack/plugins/security_solution/cypress/tasks/alerts.ts b/x-pack/plugins/security_solution/cypress/tasks/alerts.ts index b9191075a214f..9df0fb86f218c 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/alerts.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/alerts.ts @@ -16,7 +16,6 @@ import { GROUP_BY_TOP_INPUT, ACKNOWLEDGED_ALERTS_FILTER_BTN, LOADING_ALERTS_PANEL, - MANAGE_ALERT_DETECTION_RULES_BTN, MARK_ALERT_ACKNOWLEDGED_BTN, OPEN_ALERT_BTN, OPENED_ALERTS_FILTER_BTN, @@ -107,10 +106,6 @@ export const goToClosedAlerts = () => { cy.get(TIMELINE_COLUMN_SPINNER).should('not.exist'); }; -export const goToManageAlertsDetectionRules = () => { - cy.get(MANAGE_ALERT_DETECTION_RULES_BTN).should('exist').click({ force: true }); -}; - export const goToOpenedAlerts = () => { cy.get(OPENED_ALERTS_FILTER_BTN).click({ force: true }); cy.get(REFRESH_BUTTON).should('not.have.attr', 'aria-label', 'Needs updating'); diff --git a/x-pack/plugins/security_solution/cypress/tasks/alerts_details.ts b/x-pack/plugins/security_solution/cypress/tasks/alerts_details.ts index e95e031680e7b..b5bff14fd5492 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/alerts_details.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/alerts_details.ts @@ -9,7 +9,6 @@ import { ALERT_FLYOUT, ENRICHMENT_COUNT_NOTIFICATION, JSON_VIEW_TAB, - OVERVIEW_TAB, TABLE_TAB, FILTER_INPUT, } from '../screens/alerts_details'; @@ -23,10 +22,6 @@ export const openJsonView = () => { cy.get(JSON_VIEW_TAB).click(); }; -export const openOverview = () => { - cy.get(OVERVIEW_TAB).click(); -}; - export const openTable = () => { cy.get(TABLE_TAB).click(); }; diff --git a/x-pack/plugins/security_solution/cypress/tasks/alerts_detection_rules.ts b/x-pack/plugins/security_solution/cypress/tasks/alerts_detection_rules.ts index 45d594e236316..13c0c7a7735bc 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/alerts_detection_rules.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/alerts_detection_rules.ts @@ -9,7 +9,6 @@ import { duplicatedRuleName } from '../objects/rule'; import { BULK_ACTIONS_BTN, COLLAPSED_ACTION_BTN, - CREATE_NEW_RULE_BTN, CUSTOM_RULES_BTN, DELETE_RULE_ACTION_BTN, DELETE_RULE_BULK_BTN, @@ -164,10 +163,6 @@ export const filterByCustomRules = () => { cy.get(CUSTOM_RULES_BTN).click({ force: true }); }; -export const goToCreateNewRule = () => { - cy.get(CREATE_NEW_RULE_BTN).click({ force: true }); -}; - export const goToRuleDetails = () => { cy.get(RULE_NAME).first().click({ force: true }); }; @@ -348,13 +343,13 @@ export const importRules = (rulesFile: string) => { cy.get(INPUT_FILE).should('not.exist'); }; -export const selectOverwriteRulesImport = () => { +const selectOverwriteRulesImport = () => { cy.get(RULE_IMPORT_OVERWRITE_CHECKBOX) .pipe(($el) => $el.trigger('click')) .should('be.checked'); }; -export const selectOverwriteExceptionsRulesImport = () => { +const selectOverwriteExceptionsRulesImport = () => { cy.get(RULE_IMPORT_OVERWRITE_EXCEPTIONS_CHECKBOX) .pipe(($el) => $el.trigger('click')) .should('be.checked'); diff --git a/x-pack/plugins/security_solution/cypress/tasks/api_calls/elasticsearch.ts b/x-pack/plugins/security_solution/cypress/tasks/api_calls/elasticsearch.ts index 7e2cef6654034..385b38ffca507 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/api_calls/elasticsearch.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/api_calls/elasticsearch.ts @@ -5,24 +5,6 @@ * 2.0. */ -export const createIndex = (index: string) => { - cy.request({ - method: 'PUT', - url: `${Cypress.env('ELASTICSEARCH_URL')}/${index}`, - headers: { 'kbn-xsrf': 'cypress-creds' }, - failOnStatusCode: false, - }); -}; - -export const createDocument = (index: string, document: string) => { - cy.request({ - method: 'POST', - url: `${Cypress.env('ELASTICSEARCH_URL')}/${index}/_doc`, - headers: { 'kbn-xsrf': 'cypress-creds' }, - body: JSON.parse(document), - }); -}; - export const deleteIndex = (index: string) => { cy.request({ method: 'DELETE', diff --git a/x-pack/plugins/security_solution/cypress/tasks/api_calls/risk_scores/index.ts b/x-pack/plugins/security_solution/cypress/tasks/api_calls/risk_scores/index.ts index 8180c47698ea7..4429bfae8820a 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/api_calls/risk_scores/index.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/api_calls/risk_scores/index.ts @@ -10,8 +10,8 @@ import { RISK_SCORE_URL } from '../../../urls/risk_score'; import { visit } from '../../login'; import { RiskScoreEntity } from '../../risk_scores/common'; import { - getCreateLegacyRiskScoreIndicesOptions, - getCreateLegacyRiskScoreLatestIndicesOptions, + getLegacyRiskScoreIndicesOptions, + getLegacyRiskScoreLatestIndicesOptions, } from '../../risk_scores/indices'; import { getIngestPipelineName, @@ -133,7 +133,7 @@ const installLegacyHostRiskScoreModule = (spaceId: string) => { * Step 6 create ml_host_risk_score_{spaceId} index */ return createIndex( - getCreateLegacyRiskScoreIndicesOptions({ + getLegacyRiskScoreIndicesOptions({ spaceId, riskScoreEntity: RiskScoreEntity.host, }) @@ -153,7 +153,7 @@ const installLegacyHostRiskScoreModule = (spaceId: string) => { * Step 8 create ml_host_risk_score_latest_{spaceId} index */ return createIndex( - getCreateLegacyRiskScoreLatestIndicesOptions({ + getLegacyRiskScoreLatestIndicesOptions({ spaceId, riskScoreEntity: RiskScoreEntity.host, }) @@ -216,7 +216,7 @@ const installLegacyUserRiskScoreModule = async (spaceId = 'default') => { * Step 5 create ml_user_risk_score_{spaceId} index */ return createIndex( - getCreateLegacyRiskScoreIndicesOptions({ + getLegacyRiskScoreIndicesOptions({ spaceId, riskScoreEntity: RiskScoreEntity.user, }) @@ -236,7 +236,7 @@ const installLegacyUserRiskScoreModule = async (spaceId = 'default') => { * Step 7 create ml_user_risk_score_latest_{spaceId} index */ return createIndex( - getCreateLegacyRiskScoreLatestIndicesOptions({ + getLegacyRiskScoreLatestIndicesOptions({ spaceId, riskScoreEntity: RiskScoreEntity.user, }) diff --git a/x-pack/plugins/security_solution/cypress/tasks/api_calls/risk_scores/saved_objects.ts b/x-pack/plugins/security_solution/cypress/tasks/api_calls/risk_scores/saved_objects.ts index 786396654b3bf..8cdc0bbf2c1e9 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/api_calls/risk_scores/saved_objects.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/api_calls/risk_scores/saved_objects.ts @@ -24,15 +24,6 @@ export const deleteSavedObjects = ( }); }; -export const createSavedObjects = (templateName: `${RiskScoreEntity}RiskScoreDashboards`) => { - return cy.request({ - method: 'post', - url: `${RISK_SCORE_SAVED_OBJECTS_URL}/_bulk_create/${templateName}`, - failOnStatusCode: false, - headers: { 'kbn-xsrf': 'cypress-creds-via-config' }, - }); -}; - export const findSavedObjects = (riskScoreEntity: RiskScoreEntity, spaceId = 'default') => { const search = getRiskScoreTagName(riskScoreEntity, spaceId); diff --git a/x-pack/plugins/security_solution/cypress/tasks/api_calls/spaces.ts b/x-pack/plugins/security_solution/cypress/tasks/api_calls/spaces.ts deleted file mode 100644 index 2bcd2910a3c1a..0000000000000 --- a/x-pack/plugins/security_solution/cypress/tasks/api_calls/spaces.ts +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -export const createSpace = (id: string) => { - cy.request({ - method: 'POST', - url: 'api/spaces/space', - body: { - id, - name: id, - }, - headers: { 'kbn-xsrf': 'cypress-creds' }, - }).then((response) => { - expect(response.status).equal(200); - }); -}; - -export const removeSpace = (id: string) => { - cy.request({ - method: 'delete', - url: `/api/spaces/space/${id}`, - headers: { 'kbn-xsrf': 'cypress-creds' }, - }).then((response) => { - expect(response.status).equal(204); - }); -}; diff --git a/x-pack/plugins/security_solution/cypress/tasks/common.ts b/x-pack/plugins/security_solution/cypress/tasks/common.ts index 738563d002368..4b1a647906d46 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/common.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/common.ts @@ -156,23 +156,6 @@ export const deleteConnectors = () => { }); }; -export const deleteSavedQueries = () => { - const kibanaIndexUrl = `${Cypress.env('ELASTICSEARCH_URL')}/.kibana_\*`; - cy.request('POST', `${kibanaIndexUrl}/_delete_by_query?conflicts=proceed`, { - query: { - bool: { - filter: [ - { - match: { - type: 'query', - }, - }, - ], - }, - }, - }); -}; - export const postDataView = (dataSource: string) => { cy.request({ method: 'POST', diff --git a/x-pack/plugins/security_solution/cypress/tasks/create_new_rule.ts b/x-pack/plugins/security_solution/cypress/tasks/create_new_rule.ts index e2b0b1bca56f0..7fdc101f8b14c 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/create_new_rule.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/create_new_rule.ts @@ -56,7 +56,6 @@ import { MITRE_ATTACK_TECHNIQUE_DROPDOWN, MITRE_TACTIC, QUERY_BAR, - QUERY_PREVIEW_BUTTON, REFERENCE_URLS_INPUT, REFRESH_BUTTON, RISK_MAPPING_OVERRIDE_OPTION, @@ -150,11 +149,11 @@ export const fillAboutRule = ( } }; -export const fillNote = (note: string) => { +const fillNote = (note: string) => { cy.get(INVESTIGATION_NOTES_TEXTAREA).clear({ force: true }).type(note, { force: true }); }; -export const fillMitre = (mitreAttacks: Mitre[]) => { +const fillMitre = (mitreAttacks: Mitre[]) => { let techniqueIndex = 0; let subtechniqueInputIndex = 0; mitreAttacks.forEach((mitre, tacticIndex) => { @@ -181,7 +180,7 @@ export const fillMitre = (mitreAttacks: Mitre[]) => { }); }; -export const fillFalsePositiveExamples = (falsePositives: string[]) => { +const fillFalsePositiveExamples = (falsePositives: string[]) => { falsePositives.forEach((falsePositive, index) => { cy.get(FALSE_POSITIVES_INPUT) .eq(index) @@ -191,22 +190,22 @@ export const fillFalsePositiveExamples = (falsePositives: string[]) => { }); }; -export const fillSeverity = (severity: string) => { +const fillSeverity = (severity: string) => { cy.get(SEVERITY_DROPDOWN).click({ force: true }); cy.get(`#${severity.toLowerCase()}`).click(); }; -export const fillRiskScore = (riskScore: string) => { +const fillRiskScore = (riskScore: string) => { cy.get(DEFAULT_RISK_SCORE_INPUT).type(`{selectall}${riskScore}`, { force: true }); }; -export const fillRuleTags = (tags: string[]) => { +const fillRuleTags = (tags: string[]) => { tags.forEach((tag) => { cy.get(TAGS_INPUT).type(`${tag}{enter}`, { force: true }); }); }; -export const fillReferenceUrls = (referenceUrls: string[]) => { +const fillReferenceUrls = (referenceUrls: string[]) => { referenceUrls.forEach((url, index) => { cy.get(REFERENCE_URLS_INPUT).eq(index).clear({ force: true }).type(url, { force: true }); cy.get(ADD_REFERENCE_URL_BTN).click({ force: true }); @@ -275,7 +274,7 @@ export const fillAboutRuleWithOverrideAndContinue = (rule: OverrideRule) => { getAboutContinueButton().should('exist').click({ force: true }); }; -export const fillCustomQuery = (rule: CustomRule | OverrideRule) => { +const fillCustomQuery = (rule: CustomRule | OverrideRule) => { if (rule.timeline?.id) { cy.get(IMPORT_QUERY_FROM_SAVED_TIMELINE_LINK).click(); cy.get(TIMELINE(rule.timeline.id)).click(); @@ -329,29 +328,6 @@ export const fillRuleAction = (rule: CustomRule) => { } }; -export const fillDefineThresholdRule = (rule: ThresholdRule) => { - const thresholdField = 0; - const threshold = 1; - - fillCustomQuery(rule); - cy.get(COMBO_BOX_CLEAR_BTN).first().click(); - - if (rule.dataSource.type === 'indexPatterns') { - rule.dataSource.index.forEach((index) => { - cy.get(COMBO_BOX_INPUT).first().type(`${index}{enter}`); - }); - } - - cy.get(CUSTOM_QUERY_INPUT).should('have.value', rule.customQuery); - cy.get(THRESHOLD_INPUT_AREA) - .find(INPUT) - .then((inputs) => { - cy.wrap(inputs[thresholdField]).type(rule.thresholdField); - cy.get(EUI_FILTER_SELECT_ITEM).click({ force: true }); - cy.wrap(inputs[threshold]).clear().type(rule.threshold); - }); -}; - export const fillDefineThresholdRuleAndContinue = (rule: ThresholdRule) => { const thresholdField = 0; const threshold = 1; @@ -504,7 +480,7 @@ export const getIndicatorAtLeastOneInvalidationText = () => cy.contains(AT_LEAST export const getIndexPatternInvalidationText = () => cy.contains(AT_LEAST_ONE_INDEX_PATTERN); /** Returns the continue button on the step of about */ -export const getAboutContinueButton = () => cy.get(ABOUT_CONTINUE_BTN); +const getAboutContinueButton = () => cy.get(ABOUT_CONTINUE_BTN); /** Returns the continue button on the step of define */ export const getDefineContinueButton = () => cy.get(DEFINE_CONTINUE_BUTTON); @@ -595,10 +571,6 @@ export const selectNewTermsRuleType = () => { cy.get(NEW_TERMS_TYPE).click({ force: true }); }; -export const previewResults = () => { - cy.get(QUERY_PREVIEW_BUTTON).click(); -}; - export const waitForAlertsToPopulate = async (alertCountThreshold = 1) => { cy.waitUntil( () => { diff --git a/x-pack/plugins/security_solution/cypress/tasks/kibana_navigation.ts b/x-pack/plugins/security_solution/cypress/tasks/kibana_navigation.ts index 43630e63ebfe2..3b3fc0c6da4e4 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/kibana_navigation.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/kibana_navigation.ts @@ -5,11 +5,7 @@ * 2.0. */ -import { - KIBANA_NAVIGATION_TOGGLE, - SPACES_BUTTON, - getGoToSpaceMenuItem, -} from '../screens/kibana_navigation'; +import { KIBANA_NAVIGATION_TOGGLE } from '../screens/kibana_navigation'; export const navigateFromKibanaCollapsibleTo = (page: string) => { cy.get(page).click(); @@ -18,9 +14,3 @@ export const navigateFromKibanaCollapsibleTo = (page: string) => { export const openKibanaNavigation = () => { cy.get(KIBANA_NAVIGATION_TOGGLE).click(); }; - -export const changeSpace = (space: string) => { - cy.get(`${SPACES_BUTTON}`).click(); - cy.get(getGoToSpaceMenuItem(space)).click(); - cy.get(`[data-test-subj="space-avatar-${space}"]`).should('exist'); -}; diff --git a/x-pack/plugins/security_solution/cypress/tasks/lists.ts b/x-pack/plugins/security_solution/cypress/tasks/lists.ts index 19f7645b8522d..edbeb785d4297 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/lists.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/lists.ts @@ -70,9 +70,7 @@ export const exportValueList = (): Cypress.Chainable> => { * Given an array of value lists this will delete them all using Cypress Request and the lists REST API * Ref: https://www.elastic.co/guide/en/security/current/lists-api-delete-container.html */ -export const deleteValueLists = ( - lists: string[] -): Array>> => { +const deleteValueLists = (lists: string[]): Array>> => { return lists.map((list) => deleteValueList(list)); }; @@ -80,7 +78,7 @@ export const deleteValueLists = ( * Given a single value list this will delete it using Cypress Request and lists REST API * Ref: https://www.elastic.co/guide/en/security/current/lists-api-delete-container.html */ -export const deleteValueList = (list: string): Cypress.Chainable> => { +const deleteValueList = (list: string): Cypress.Chainable> => { return cy.request({ method: 'DELETE', url: `api/lists?id=${list}`, @@ -99,7 +97,7 @@ export const deleteValueList = (list: string): Cypress.Chainable { +const getUrlWithRoute = (role: ROLES, route: string) => { const url = Cypress.config().baseUrl; const kibana = new URL(String(url)); const theUrl = `${Url.format({ @@ -100,14 +100,14 @@ export const constructUrlWithUser = (user: User, route: string) => { return builtUrl.href; }; -export const getCurlScriptEnvVars = () => ({ +const getCurlScriptEnvVars = () => ({ ELASTICSEARCH_URL: Cypress.env('ELASTICSEARCH_URL'), ELASTICSEARCH_USERNAME: Cypress.env('ELASTICSEARCH_USERNAME'), ELASTICSEARCH_PASSWORD: Cypress.env('ELASTICSEARCH_PASSWORD'), KIBANA_URL: Cypress.config().baseUrl, }); -export const postRoleAndUser = (role: ROLES) => { +const postRoleAndUser = (role: ROLES) => { const env = getCurlScriptEnvVars(); const detectionsRoleScriptPath = `./server/lib/detection_engine/scripts/roles_users/${role}/post_detections_role.sh`; const detectionsRoleJsonPath = `./server/lib/detection_engine/scripts/roles_users/${role}/detections_role.json`; @@ -152,7 +152,7 @@ export const loginWithUser = (user: User) => { }); }; -export const loginWithRole = async (role: ROLES) => { +const loginWithRole = async (role: ROLES) => { postRoleAndUser(role); const theUrl = Url.format({ auth: `${role}:changeme`, diff --git a/x-pack/plugins/security_solution/cypress/tasks/overview.ts b/x-pack/plugins/security_solution/cypress/tasks/overview.ts index efda406c46243..315591c94c11d 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/overview.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/overview.ts @@ -7,7 +7,7 @@ import { OVERVIEW_HOST_STATS, OVERVIEW_NETWORK_STATS } from '../screens/overview'; -export const expand = (statType: string) => { +const expand = (statType: string) => { cy.get(statType).find('button').invoke('click'); }; diff --git a/x-pack/plugins/security_solution/cypress/tasks/risk_scores/indices.ts b/x-pack/plugins/security_solution/cypress/tasks/risk_scores/indices.ts index 6a7c7f317c8ca..1d064fcdbb59b 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/risk_scores/indices.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/risk_scores/indices.ts @@ -13,14 +13,8 @@ export const getPivotTransformIndex = (riskScoreEntity: RiskScoreEntity, spaceId export const getLatestTransformIndex = (riskScoreEntity: RiskScoreEntity, spaceId = 'default') => `ml_${riskScoreEntity}_risk_score_latest_${spaceId}`; -export const getCreateLegacyRiskScoreIndicesOptions = ({ - spaceId = 'default', - riskScoreEntity, -}: { - spaceId?: string; - riskScoreEntity: RiskScoreEntity; -}) => { - const mappings = { +export const getLegacyRiskScoreMapping = (riskScoreEntity: RiskScoreEntity) => { + return { properties: { [`${riskScoreEntity}.name`]: { type: 'keyword', @@ -48,49 +42,30 @@ export const getCreateLegacyRiskScoreIndicesOptions = ({ }, }, }; +}; + +export const getLegacyRiskScoreIndicesOptions = ({ + spaceId = 'default', + riskScoreEntity, +}: { + spaceId?: string; + riskScoreEntity: RiskScoreEntity; +}) => { return { index: getPivotTransformIndex(riskScoreEntity, spaceId), - mappings, + mappings: getLegacyRiskScoreMapping(riskScoreEntity), }; }; -export const getCreateLegacyRiskScoreLatestIndicesOptions = ({ +export const getLegacyRiskScoreLatestIndicesOptions = ({ spaceId = 'default', riskScoreEntity, }: { spaceId?: string; riskScoreEntity: RiskScoreEntity; }) => { - const mappings = { - properties: { - [`${riskScoreEntity}.name`]: { - type: 'keyword', - }, - '@timestamp': { - type: 'date', - }, - ingest_timestamp: { - type: 'date', - }, - risk: { - type: 'text', - fields: { - keyword: { - type: 'keyword', - }, - }, - }, - risk_stats: { - properties: { - risk_score: { - type: 'float', - }, - }, - }, - }, - }; return { index: getLatestTransformIndex(riskScoreEntity, spaceId), - mappings, + mappings: getLegacyRiskScoreMapping(riskScoreEntity), }; }; diff --git a/x-pack/plugins/security_solution/cypress/tasks/risk_scores/transforms.ts b/x-pack/plugins/security_solution/cypress/tasks/risk_scores/transforms.ts index aa41facee24e9..c1e654d530653 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/risk_scores/transforms.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/risk_scores/transforms.ts @@ -16,7 +16,7 @@ import { } from './stored_scripts'; const DEFAULT_ALERTS_INDEX = '.alerts-security.alerts' as const; -export const getAlertsIndex = (spaceId = 'default') => `${DEFAULT_ALERTS_INDEX}-${spaceId}`; +const getAlertsIndex = (spaceId = 'default') => `${DEFAULT_ALERTS_INDEX}-${spaceId}`; export const getRiskScorePivotTransformId = ( riskScoreEntity: RiskScoreEntity, @@ -76,7 +76,7 @@ export const createTransform = (transformId: string, options: string | Record { +const deleteTransform = (transformId: string) => { return cy.request({ method: 'post', url: `${TRANSFORMS_URL}/delete_transforms`, diff --git a/x-pack/plugins/security_solution/cypress/tasks/rule_details.ts b/x-pack/plugins/security_solution/cypress/tasks/rule_details.ts index a412675ab5331..3f7d31f060473 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/rule_details.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/rule_details.ts @@ -86,7 +86,7 @@ export const searchForExceptionItem = (query: string) => { }); }; -export const addExceptionFlyoutFromViewerHeader = () => { +const addExceptionFlyoutFromViewerHeader = () => { cy.root() .pipe(($el) => { $el.find(ADD_EXCEPTIONS_BTN_FROM_VIEWER_HEADER).trigger('click'); diff --git a/x-pack/plugins/security_solution/cypress/tasks/rules_bulk_edit.ts b/x-pack/plugins/security_solution/cypress/tasks/rules_bulk_edit.ts index 2f6863dbd3a1c..64f0e88849356 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/rules_bulk_edit.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/rules_bulk_edit.ts @@ -48,12 +48,12 @@ export const clickApplyTimelineTemplatesMenuItem = () => { cy.get(APPLY_TIMELINE_RULE_BULK_MENU_ITEM).click().should('not.exist'); }; -export const clickIndexPatternsMenuItem = () => { +const clickIndexPatternsMenuItem = () => { cy.get(BULK_ACTIONS_BTN).click(); cy.get(INDEX_PATTERNS_RULE_BULK_MENU_ITEM).click().should('not.exist'); }; -export const clickTagsMenuItem = () => { +const clickTagsMenuItem = () => { cy.get(BULK_ACTIONS_BTN).click(); cy.get(TAGS_RULE_BULK_MENU_ITEM).click(); }; @@ -73,11 +73,6 @@ export const clickAddIndexPatternsMenuItem = () => { cy.get(ADD_INDEX_PATTERNS_RULE_BULK_MENU_ITEM).click(); }; -export const clickDeleteIndexPatternsMenuItem = () => { - clickIndexPatternsMenuItem(); - cy.get(DELETE_INDEX_PATTERNS_RULE_BULK_MENU_ITEM).click().should('not.exist'); -}; - export const openBulkEditAddIndexPatternsForm = () => { clickAddIndexPatternsMenuItem(); diff --git a/x-pack/plugins/security_solution/cypress/tasks/sourcerer.ts b/x-pack/plugins/security_solution/cypress/tasks/sourcerer.ts index d8fe638da7f0c..dc600f9250618 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/sourcerer.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/sourcerer.ts @@ -22,7 +22,8 @@ export const openSourcerer = (sourcererScope?: string) => { cy.get(SOURCERER.trigger).click(); cy.get(SOURCERER.wrapper).should('be.visible'); }; -export const openTimelineSourcerer = () => { + +const openTimelineSourcerer = () => { cy.get(SOURCERER.triggerTimeline).should('be.enabled'); cy.get(SOURCERER.triggerTimeline).should('be.visible'); cy.get(SOURCERER.triggerTimeline).first().click(); @@ -33,7 +34,7 @@ export const openAdvancedSettings = () => { cy.get(SOURCERER.advancedSettings).click(); }; -export const clickOutOfSelector = () => { +const clickOutOfSelector = () => { return cy.get(SOURCERER.popoverTitle).first().click(); }; @@ -128,7 +129,7 @@ export const deleteAlertsIndex = () => { }); }; -export const refreshUntilAlertsIndexExists = async () => { +const refreshUntilAlertsIndexExists = async () => { cy.waitUntil( () => { cy.reload(); diff --git a/x-pack/plugins/security_solution/cypress/tasks/timeline.ts b/x-pack/plugins/security_solution/cypress/tasks/timeline.ts index f5b1a2c794cbc..1ff04833db2a4 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/timeline.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/timeline.ts @@ -85,7 +85,7 @@ import { drag, drop } from './common'; import { closeFieldsBrowser, filterFieldsBrowser } from './fields_browser'; -export const hostExistsQuery = 'host.name: *'; +const hostExistsQuery = 'host.name: *'; export const addDescriptionToTimeline = ( description: string, diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/insights/related_alerts_by_process_ancestry.tsx b/x-pack/plugins/security_solution/public/common/components/event_details/insights/related_alerts_by_process_ancestry.tsx index 28737c60f4e07..a36328fd57813 100644 --- a/x-pack/plugins/security_solution/public/common/components/event_details/insights/related_alerts_by_process_ancestry.tsx +++ b/x-pack/plugins/security_solution/public/common/components/event_details/insights/related_alerts_by_process_ancestry.tsx @@ -6,8 +6,9 @@ */ import React, { useMemo, useCallback, useEffect, useState } from 'react'; -import { EuiSpacer, EuiLoadingSpinner } from '@elastic/eui'; +import { EuiBetaBadge, EuiSpacer, EuiLoadingSpinner } from '@elastic/eui'; +import type { Filter } from '@kbn/es-query'; import type { DataProvider } from '../../../../../common/types'; import { TimelineId } from '../../../../../common/types/timeline'; import type { TimelineEventsDetailsItem } from '../../../../../common/search_strategy/timeline'; @@ -22,7 +23,9 @@ import { PROCESS_ANCESTRY_COUNT, PROCESS_ANCESTRY_EMPTY, PROCESS_ANCESTRY_ERROR, + PROCESS_ANCESTRY_FILTER, } from './translations'; +import { BETA } from '../../../translations'; interface Props { data: TimelineEventsDetailsItem; @@ -36,6 +39,8 @@ interface Cache { alertIds: string[]; } +const dataProviderLimit = 5; + /** * Fetches and displays alerts that were generated in the associated process' * process tree. @@ -97,6 +102,8 @@ export const RelatedAlertsByProcessAncestry = React.memo( ); }, [showContent, cache, data, eventId, timelineId, index, originalDocumentId]); + const betaBadge = useMemo(() => , []); + return ( ( } renderContent={renderContent} onToggle={onToggle} + extraAction={betaBadge} /> ); } @@ -167,18 +175,55 @@ const ActualRelatedAlertsByProcessAncestry: React.FC<{ eventId: string; timelineId?: string; }> = ({ alertIds, eventId, timelineId }) => { + const shouldUseFilters = alertIds && alertIds.length && alertIds.length >= dataProviderLimit; const dataProviders = useMemo(() => { if (alertIds && alertIds.length) { - return alertIds.reduce((result, alertId, index) => { - const id = `${timelineId}-${eventId}-event.id-${index}-${alertId}`; - result.push(getDataProvider('_id', id, alertId)); - return result; - }, []); + if (shouldUseFilters) { + return null; + } else { + return alertIds.reduce((result, alertId, index) => { + const id = `${timelineId}-${eventId}-event.id-${index}-${alertId}`; + result.push(getDataProvider('_id', id, alertId)); + return result; + }, []); + } } return null; - }, [alertIds, eventId, timelineId]); + }, [alertIds, eventId, timelineId, shouldUseFilters]); + + const filters: Filter[] | null = useMemo(() => { + if (shouldUseFilters) { + return [ + { + meta: { + alias: PROCESS_ANCESTRY_FILTER, + type: 'phrases', + key: '_id', + params: [...alertIds], + negate: false, + disabled: false, + value: alertIds.join(), + }, + query: { + bool: { + should: alertIds.map((id) => { + return { + match_phrase: { + _id: id, + }, + }; + }), + minimum_should_match: 1, + }, + }, + }, + ]; + } else { + return null; + } + }, [alertIds, shouldUseFilters]); - if (!dataProviders) { + if (!dataProviders && !filters) { return null; } @@ -189,6 +234,7 @@ const ActualRelatedAlertsByProcessAncestry: React.FC<{ {ACTION_INVESTIGATE_IN_TIMELINE} diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/insights/translations.ts b/x-pack/plugins/security_solution/public/common/components/event_details/insights/translations.ts index 10d9efca4682d..270c1eedb62c0 100644 --- a/x-pack/plugins/security_solution/public/common/components/event_details/insights/translations.ts +++ b/x-pack/plugins/security_solution/public/common/components/event_details/insights/translations.ts @@ -34,6 +34,13 @@ export const PROCESS_ANCESTRY_ERROR = i18n.translate( } ); +export const PROCESS_ANCESTRY_FILTER = i18n.translate( + 'xpack.securitySolution.alertDetails.overview.insights.processAncestryFilter', + { + defaultMessage: 'Process Ancestry Alert IDs', + } +); + export const PROCESS_ANCESTRY_EMPTY = i18n.translate( 'xpack.securitySolution.alertDetails.overview.insights.related_alerts_by_process_ancestry_empty', { diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/table/investigate_in_timeline_button.tsx b/x-pack/plugins/security_solution/public/common/components/event_details/table/investigate_in_timeline_button.tsx index b1819128a14a8..820488225e17b 100644 --- a/x-pack/plugins/security_solution/public/common/components/event_details/table/investigate_in_timeline_button.tsx +++ b/x-pack/plugins/security_solution/public/common/components/event_details/table/investigate_in_timeline_button.tsx @@ -7,12 +7,13 @@ import React, { useMemo } from 'react'; import { EuiButton, EuiButtonEmpty } from '@elastic/eui'; +import type { Filter } from '@kbn/es-query'; import { useDispatch } from 'react-redux'; import { sourcererSelectors } from '../../../store'; import { InputsModelId } from '../../../store/inputs/constants'; import { inputsActions } from '../../../store/inputs'; -import { updateProviders } from '../../../../timelines/store/timeline/actions'; +import { updateProviders, setFilters } from '../../../../timelines/store/timeline/actions'; import { sourcererActions } from '../../../store/actions'; import { SourcererScopeName } from '../../../store/sourcerer/model'; import type { DataProvider } from '../../../../../common/types'; @@ -23,8 +24,9 @@ import { useDeepEqualSelector } from '../../../hooks/use_selector'; export const InvestigateInTimelineButton: React.FunctionComponent<{ asEmptyButton: boolean; - dataProviders: DataProvider[]; -}> = ({ asEmptyButton, children, dataProviders, ...rest }) => { + dataProviders: DataProvider[] | null; + filters?: Filter[] | null; +}> = ({ asEmptyButton, children, dataProviders, filters, ...rest }) => { const dispatch = useDispatch(); const getDataViewsSelector = useMemo( @@ -41,16 +43,27 @@ export const InvestigateInTimelineButton: React.FunctionComponent<{ }); const configureAndOpenTimeline = React.useCallback(() => { - if (dataProviders) { + if (dataProviders || filters) { // Reset the current timeline clearTimeline(); - // Update the timeline's providers to match the current prevalence field query - dispatch( - updateProviders({ - id: TimelineId.active, - providers: dataProviders, - }) - ); + if (dataProviders) { + // Update the timeline's providers to match the current prevalence field query + dispatch( + updateProviders({ + id: TimelineId.active, + providers: dataProviders, + }) + ); + } + // Use filters if more than a certain amount of ids for dom performance. + if (filters) { + dispatch( + setFilters({ + id: TimelineId.active, + filters, + }) + ); + } // Only show detection alerts // (This is required so the timeline event count matches the prevalence count) dispatch( @@ -63,7 +76,7 @@ export const InvestigateInTimelineButton: React.FunctionComponent<{ // Unlock the time range from the global time range dispatch(inputsActions.removeLinkTo([InputsModelId.timeline, InputsModelId.global])); } - }, [dataProviders, clearTimeline, dispatch, defaultDataView.id, signalIndexName]); + }, [dataProviders, clearTimeline, dispatch, defaultDataView.id, signalIndexName, filters]); return asEmptyButton ? ( > = { @@ -26,8 +27,22 @@ export const defaultSessionsFilter: Required> = { bool: { filter: [ { - exists: { - field: 'process.entry_leader.entity_id', // to exclude any records which have no entry_leader.entity_id + bool: { + // show sessions table results by filtering events where event.action is fork, exec, or end + should: [ + { term: { [EVENT_ACTION]: EventAction.exec } }, + { term: { [EVENT_ACTION]: EventAction.fork } }, + { term: { [EVENT_ACTION]: EventAction.end } }, + ], + }, + }, + { + bool: { + filter: { + exists: { + field: ENTRY_SESSION_ENTITY_ID_PROPERTY, // to exclude any records which have no entry_leader.entity_id + }, + }, }, }, ], @@ -36,7 +51,7 @@ export const defaultSessionsFilter: Required> = { meta: { alias: null, disabled: false, - key: 'process.entry_leader.entity_id', + key: ENTRY_SESSION_ENTITY_ID_PROPERTY, negate: false, params: {}, type: 'string', diff --git a/x-pack/plugins/security_solution/public/common/components/user_privileges/endpoint/use_endpoint_privileges.test.ts b/x-pack/plugins/security_solution/public/common/components/user_privileges/endpoint/use_endpoint_privileges.test.ts index a0d23820025b8..b9df2e976966a 100644 --- a/x-pack/plugins/security_solution/public/common/components/user_privileges/endpoint/use_endpoint_privileges.test.ts +++ b/x-pack/plugins/security_solution/public/common/components/user_privileges/endpoint/use_endpoint_privileges.test.ts @@ -52,6 +52,15 @@ describe('When using useEndpointPrivileges hook', () => { (useCurrentUser as jest.Mock).mockReturnValue(authenticatedUser); useKibanaMock().services.fleet!.authz = createFleetAuthzMock(); + useKibanaMock().services.application.capabilities = { + catalogue: {}, + management: {}, + navLinks: {}, + siem: { + crud: true, + show: true, + }, + }; licenseServiceMock.isPlatinumPlus.mockReturnValue(true); @@ -63,6 +72,7 @@ describe('When using useEndpointPrivileges hook', () => { }); afterEach(() => { + jest.resetAllMocks(); unmount(); }); diff --git a/x-pack/plugins/security_solution/public/common/components/user_privileges/endpoint/use_endpoint_privileges.ts b/x-pack/plugins/security_solution/public/common/components/user_privileges/endpoint/use_endpoint_privileges.ts index 7d7233312fecc..17de09113df9a 100644 --- a/x-pack/plugins/security_solution/public/common/components/user_privileges/endpoint/use_endpoint_privileges.ts +++ b/x-pack/plugins/security_solution/public/common/components/user_privileges/endpoint/use_endpoint_privileges.ts @@ -17,6 +17,7 @@ import type { import { calculateEndpointAuthz, getEndpointAuthzInitialState, + calculatePermissionsFromCapabilities, } from '../../../../../common/endpoint/service/authz'; import { useSecuritySolutionStartDependencies } from './security_solution_start_dependencies'; import { useIsExperimentalFeatureEnabled } from '../../../hooks/use_experimental_features'; @@ -44,11 +45,21 @@ export const useEndpointPrivileges = (): Immutable => { const fleetServices = fleetServicesFromUseKibana ?? fleetServicesFromPluginStart; const isEndpointRbacEnabled = useIsExperimentalFeatureEnabled('endpointRbacEnabled'); + const endpointPermissions = calculatePermissionsFromCapabilities( + useKibana().services.application.capabilities + ); + const privileges = useMemo(() => { const privilegeList: EndpointPrivileges = Object.freeze({ loading: !fleetCheckDone || !userRolesCheckDone || !user, ...(fleetAuthz - ? calculateEndpointAuthz(licenseService, fleetAuthz, userRoles, isEndpointRbacEnabled) + ? calculateEndpointAuthz( + licenseService, + fleetAuthz, + userRoles, + isEndpointRbacEnabled, + endpointPermissions + ) : getEndpointAuthzInitialState()), }); @@ -61,6 +72,7 @@ export const useEndpointPrivileges = (): Immutable => { licenseService, userRoles, isEndpointRbacEnabled, + endpointPermissions, ]); // Check if user can access fleet diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/common/__snapshots__/authentication.test.ts.snap b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/common/__snapshots__/authentication.test.ts.snap index 747487203066b..f683d2828bae3 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/common/__snapshots__/authentication.test.ts.snap +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/common/__snapshots__/authentication.test.ts.snap @@ -27,7 +27,7 @@ Object { ], "state": Object { "datasourceStates": Object { - "indexpattern": Object { + "formBased": Object { "layers": Object { "3fd0c5d5-f762-4a27-8c56-14eee0223e13": Object { "columnOrder": Array [ diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/common/__snapshots__/external_alert.test.ts.snap b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/common/__snapshots__/external_alert.test.ts.snap index ac42b228012fe..425f545129ee6 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/common/__snapshots__/external_alert.test.ts.snap +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/common/__snapshots__/external_alert.test.ts.snap @@ -27,7 +27,7 @@ Object { ], "state": Object { "datasourceStates": Object { - "indexpattern": Object { + "formBased": Object { "layers": Object { "a3c54471-615f-4ff9-9fda-69b5b2ea3eef": Object { "columnOrder": Array [ diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/common/authentication.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/common/authentication.ts index 15d7f029ae612..4e69bac6287ec 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/common/authentication.ts +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/common/authentication.ts @@ -98,7 +98,7 @@ export const authenticationLensAttributes: LensAttributes = { }, ], datasourceStates: { - indexpattern: { + formBased: { layers: { '3fd0c5d5-f762-4a27-8c56-14eee0223e13': { columns: { diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/common/external_alert.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/common/external_alert.ts index a815d442b043e..f5a664b98161b 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/common/external_alert.ts +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/common/external_alert.ts @@ -71,7 +71,7 @@ export const getExternalAlertLensAttributes: GetLensAttributes = ( }, ], datasourceStates: { - indexpattern: { + formBased: { layers: { 'a3c54471-615f-4ff9-9fda-69b5b2ea3eef': { columns: { diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/__snapshots__/event.test.ts.snap b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/__snapshots__/event.test.ts.snap index 7f3fdb6c66107..129a82aa1692c 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/__snapshots__/event.test.ts.snap +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/__snapshots__/event.test.ts.snap @@ -17,7 +17,7 @@ Object { ], "state": Object { "datasourceStates": Object { - "indexpattern": Object { + "formBased": Object { "layers": Object { "0039eb0c-9a1a-4687-ae54-0f4e239bec75": Object { "columnOrder": Array [ diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/__snapshots__/kpi_host_area.test.ts.snap b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/__snapshots__/kpi_host_area.test.ts.snap index c5e4e272ec9c4..b9165ea5c38a8 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/__snapshots__/kpi_host_area.test.ts.snap +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/__snapshots__/kpi_host_area.test.ts.snap @@ -17,7 +17,7 @@ Object { ], "state": Object { "datasourceStates": Object { - "indexpattern": Object { + "formBased": Object { "layers": Object { "416b6fad-1923-4f6a-a2df-b223bb287e30": Object { "columnOrder": Array [ diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/__snapshots__/kpi_host_metric.test.ts.snap b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/__snapshots__/kpi_host_metric.test.ts.snap index 3669de2d30109..ea37bec0d1976 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/__snapshots__/kpi_host_metric.test.ts.snap +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/__snapshots__/kpi_host_metric.test.ts.snap @@ -17,7 +17,7 @@ Object { ], "state": Object { "datasourceStates": Object { - "indexpattern": Object { + "formBased": Object { "layers": Object { "416b6fad-1923-4f6a-a2df-b223bb287e30": Object { "columnOrder": Array [ diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/__snapshots__/kpi_unique_ips_area.test.ts.snap b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/__snapshots__/kpi_unique_ips_area.test.ts.snap index acaf78556269f..f45cd86c70ed2 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/__snapshots__/kpi_unique_ips_area.test.ts.snap +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/__snapshots__/kpi_unique_ips_area.test.ts.snap @@ -22,7 +22,7 @@ Object { ], "state": Object { "datasourceStates": Object { - "indexpattern": Object { + "formBased": Object { "layers": Object { "8be0156b-d423-4a39-adf1-f54d4c9f2e69": Object { "columnOrder": Array [ diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/__snapshots__/kpi_unique_ips_bar.test.ts.snap b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/__snapshots__/kpi_unique_ips_bar.test.ts.snap index 9f702ecb06412..0a66d46f9a7db 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/__snapshots__/kpi_unique_ips_bar.test.ts.snap +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/__snapshots__/kpi_unique_ips_bar.test.ts.snap @@ -22,7 +22,7 @@ Object { ], "state": Object { "datasourceStates": Object { - "indexpattern": Object { + "formBased": Object { "layers": Object { "8be0156b-d423-4a39-adf1-f54d4c9f2e69": Object { "columnOrder": Array [ diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/__snapshots__/kpi_unique_ips_destination_metric.test.ts.snap b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/__snapshots__/kpi_unique_ips_destination_metric.test.ts.snap index ebeb85e27a44f..3ca56d9f020b2 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/__snapshots__/kpi_unique_ips_destination_metric.test.ts.snap +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/__snapshots__/kpi_unique_ips_destination_metric.test.ts.snap @@ -17,7 +17,7 @@ Object { ], "state": Object { "datasourceStates": Object { - "indexpattern": Object { + "formBased": Object { "layers": Object { "8be0156b-d423-4a39-adf1-f54d4c9f2e69": Object { "columnOrder": Array [ diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/__snapshots__/kpi_unique_ips_source_metric.test.ts.snap b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/__snapshots__/kpi_unique_ips_source_metric.test.ts.snap index f8ec7bb8c70d7..2972842a6f419 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/__snapshots__/kpi_unique_ips_source_metric.test.ts.snap +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/__snapshots__/kpi_unique_ips_source_metric.test.ts.snap @@ -17,7 +17,7 @@ Object { ], "state": Object { "datasourceStates": Object { - "indexpattern": Object { + "formBased": Object { "layers": Object { "8be0156b-d423-4a39-adf1-f54d4c9f2e69": Object { "columnOrder": Array [ diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/events.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/events.ts index da244d40565fb..f07716f8c4bd7 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/events.ts +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/events.ts @@ -53,7 +53,7 @@ export const getEventsHistogramLensAttributes: GetLensAttributes = ( }, filters: [], datasourceStates: { - indexpattern: { + formBased: { layers: { '0039eb0c-9a1a-4687-ae54-0f4e239bec75': { columns: { diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/kpi_host_area.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/kpi_host_area.ts index 64f62133e9406..6eb400734ebe0 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/kpi_host_area.ts +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/kpi_host_area.ts @@ -12,7 +12,7 @@ export const kpiHostAreaLensAttributes: LensAttributes = { description: '', state: { datasourceStates: { - indexpattern: { + formBased: { layers: { '416b6fad-1923-4f6a-a2df-b223bb287e30': { columnOrder: [ diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/kpi_host_metric.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/kpi_host_metric.ts index 00ab0239acb40..66b6b63a69321 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/kpi_host_metric.ts +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/kpi_host_metric.ts @@ -11,7 +11,7 @@ export const kpiHostMetricLensAttributes: LensAttributes = { description: '', state: { datasourceStates: { - indexpattern: { + formBased: { layers: { '416b6fad-1923-4f6a-a2df-b223bb287e30': { columnOrder: ['b00c65ea-32be-4163-bfc8-f795b1ef9d06'], diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/kpi_unique_ips_area.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/kpi_unique_ips_area.ts index ac0d102a5f03c..79539f40390af 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/kpi_unique_ips_area.ts +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/kpi_unique_ips_area.ts @@ -12,7 +12,7 @@ export const kpiUniqueIpsAreaLensAttributes: LensAttributes = { description: '', state: { datasourceStates: { - indexpattern: { + formBased: { layers: { '8be0156b-d423-4a39-adf1-f54d4c9f2e69': { columnOrder: [ diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/kpi_unique_ips_bar.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/kpi_unique_ips_bar.ts index cf7dbf21913b5..862eb64b44eeb 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/kpi_unique_ips_bar.ts +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/kpi_unique_ips_bar.ts @@ -12,7 +12,7 @@ export const kpiUniqueIpsBarLensAttributes: LensAttributes = { description: '', state: { datasourceStates: { - indexpattern: { + formBased: { layers: { '8be0156b-d423-4a39-adf1-f54d4c9f2e69': { columnOrder: [ diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/kpi_unique_ips_destination_metric.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/kpi_unique_ips_destination_metric.ts index 5c4aa31f65833..094bc189f1ac7 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/kpi_unique_ips_destination_metric.ts +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/kpi_unique_ips_destination_metric.ts @@ -11,7 +11,7 @@ export const kpiUniqueIpsDestinationMetricLensAttributes: LensAttributes = { description: '', state: { datasourceStates: { - indexpattern: { + formBased: { layers: { '8be0156b-d423-4a39-adf1-f54d4c9f2e69': { columnOrder: ['d9a6eb6b-8b78-439e-98e7-a718f8ffbebe'], diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/kpi_unique_ips_source_metric.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/kpi_unique_ips_source_metric.ts index 4d308b95d796d..388f5ef53b301 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/kpi_unique_ips_source_metric.ts +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/kpi_unique_ips_source_metric.ts @@ -11,7 +11,7 @@ export const kpiUniqueIpsSourceMetricLensAttributes: LensAttributes = { description: '', state: { datasourceStates: { - indexpattern: { + formBased: { layers: { '8be0156b-d423-4a39-adf1-f54d4c9f2e69': { columnOrder: ['d9a6eb6b-8b78-439e-98e7-a718f8ffbebe'], diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/__snapshots__/dns_top_domains.test.ts.snap b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/__snapshots__/dns_top_domains.test.ts.snap index 6e0f9c2bbd516..392d68b512b41 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/__snapshots__/dns_top_domains.test.ts.snap +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/__snapshots__/dns_top_domains.test.ts.snap @@ -22,7 +22,7 @@ Object { ], "state": Object { "datasourceStates": Object { - "indexpattern": Object { + "formBased": Object { "layers": Object { "b1c3efc6-c886-4fba-978f-3b6bb5e7948a": Object { "columnOrder": Array [ diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/__snapshots__/kpi_dns_queries.test.ts.snap b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/__snapshots__/kpi_dns_queries.test.ts.snap index 39f16779abaf4..173a1229e1282 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/__snapshots__/kpi_dns_queries.test.ts.snap +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/__snapshots__/kpi_dns_queries.test.ts.snap @@ -22,7 +22,7 @@ Object { ], "state": Object { "datasourceStates": Object { - "indexpattern": Object { + "formBased": Object { "layers": Object { "cea37c70-8f91-43bf-b9fe-72d8c049f6a3": Object { "columnOrder": Array [ diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/__snapshots__/kpi_network_events.test.ts.snap b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/__snapshots__/kpi_network_events.test.ts.snap index 03bacfac49ad7..c9b0441a25a4b 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/__snapshots__/kpi_network_events.test.ts.snap +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/__snapshots__/kpi_network_events.test.ts.snap @@ -27,7 +27,7 @@ Object { ], "state": Object { "datasourceStates": Object { - "indexpattern": Object { + "formBased": Object { "layers": Object { "eaadfec7-deaa-4aeb-a403-3b4e516416d2": Object { "columnOrder": Array [ diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/__snapshots__/kpi_tls_handshakes.test.ts.snap b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/__snapshots__/kpi_tls_handshakes.test.ts.snap index 6e695484fdc0f..532d81001ab06 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/__snapshots__/kpi_tls_handshakes.test.ts.snap +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/__snapshots__/kpi_tls_handshakes.test.ts.snap @@ -17,7 +17,7 @@ Object { ], "state": Object { "datasourceStates": Object { - "indexpattern": Object { + "formBased": Object { "layers": Object { "1f48a633-8eee-45ae-9471-861227e9ca03": Object { "columnOrder": Array [ diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/__snapshots__/kpi_unique_flow_ids.test.ts.snap b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/__snapshots__/kpi_unique_flow_ids.test.ts.snap index 1e3f1f63c40c8..60a52f4f5b4a9 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/__snapshots__/kpi_unique_flow_ids.test.ts.snap +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/__snapshots__/kpi_unique_flow_ids.test.ts.snap @@ -17,7 +17,7 @@ Object { ], "state": Object { "datasourceStates": Object { - "indexpattern": Object { + "formBased": Object { "layers": Object { "5d46d48f-6ce8-46be-a797-17ad50642564": Object { "columnOrder": Array [ diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/__snapshots__/kpi_unique_private_ips_area.test.ts.snap b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/__snapshots__/kpi_unique_private_ips_area.test.ts.snap index 2415dcc6c750c..11e3f62d0cd4c 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/__snapshots__/kpi_unique_private_ips_area.test.ts.snap +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/__snapshots__/kpi_unique_private_ips_area.test.ts.snap @@ -22,7 +22,7 @@ Object { ], "state": Object { "datasourceStates": Object { - "indexpattern": Object { + "formBased": Object { "layers": Object { "38aa6532-6bf9-4c8f-b2a6-da8d32f7d0d7": Object { "columnOrder": Array [ diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/__snapshots__/kpi_unique_private_ips_bar.test.ts.snap b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/__snapshots__/kpi_unique_private_ips_bar.test.ts.snap index 2ea658869183c..2a702bb87f3fd 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/__snapshots__/kpi_unique_private_ips_bar.test.ts.snap +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/__snapshots__/kpi_unique_private_ips_bar.test.ts.snap @@ -22,7 +22,7 @@ Object { ], "state": Object { "datasourceStates": Object { - "indexpattern": Object { + "formBased": Object { "layers": Object { "38aa6532-6bf9-4c8f-b2a6-da8d32f7d0d7": Object { "columnOrder": Array [ diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/__snapshots__/kpi_unique_private_ips_destination_metric.test.ts.snap b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/__snapshots__/kpi_unique_private_ips_destination_metric.test.ts.snap index 37311a980c6b4..9f205c5c23c07 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/__snapshots__/kpi_unique_private_ips_destination_metric.test.ts.snap +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/__snapshots__/kpi_unique_private_ips_destination_metric.test.ts.snap @@ -17,7 +17,7 @@ Object { ], "state": Object { "datasourceStates": Object { - "indexpattern": Object { + "formBased": Object { "layers": Object { "cea37c70-8f91-43bf-b9fe-72d8c049f6a3": Object { "columnOrder": Array [ diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/__snapshots__/kpi_unique_private_ips_source_metric.test.ts.snap b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/__snapshots__/kpi_unique_private_ips_source_metric.test.ts.snap index 2f7ba7d2997b1..b7e25a6ceb8f4 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/__snapshots__/kpi_unique_private_ips_source_metric.test.ts.snap +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/__snapshots__/kpi_unique_private_ips_source_metric.test.ts.snap @@ -17,7 +17,7 @@ Object { ], "state": Object { "datasourceStates": Object { - "indexpattern": Object { + "formBased": Object { "layers": Object { "cea37c70-8f91-43bf-b9fe-72d8c049f6a3": Object { "columnOrder": Array [ diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/dns_top_domains.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/dns_top_domains.ts index ef75bea77c3e0..0f195bdeaa8d4 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/dns_top_domains.ts +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/dns_top_domains.ts @@ -89,7 +89,7 @@ export const dnsTopDomainsLensAttributes: LensAttributes = { }, ], datasourceStates: { - indexpattern: { + formBased: { layers: { 'b1c3efc6-c886-4fba-978f-3b6bb5e7948a': { columns: { diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_dns_queries.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_dns_queries.ts index 681cd278214b1..c4691a4797b5b 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_dns_queries.ts +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_dns_queries.ts @@ -64,7 +64,7 @@ export const kpiDnsQueriesLensAttributes: LensAttributes = { }, ], datasourceStates: { - indexpattern: { + formBased: { layers: { 'cea37c70-8f91-43bf-b9fe-72d8c049f6a3': { columns: { diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_network_events.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_network_events.ts index 534ffeb2024e6..bb88ceb732c66 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_network_events.ts +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_network_events.ts @@ -62,7 +62,7 @@ export const kpiNetworkEventsLensAttributes: LensAttributes = { }, ], datasourceStates: { - indexpattern: { + formBased: { layers: { 'eaadfec7-deaa-4aeb-a403-3b4e516416d2': { columns: { diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_tls_handshakes.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_tls_handshakes.ts index 367fe6fd40f6f..b7b651bf56362 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_tls_handshakes.ts +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_tls_handshakes.ts @@ -93,7 +93,7 @@ export const kpiTlsHandshakesLensAttributes: LensAttributes = { }, ], datasourceStates: { - indexpattern: { + formBased: { layers: { '1f48a633-8eee-45ae-9471-861227e9ca03': { columns: { diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_unique_flow_ids.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_unique_flow_ids.ts index 5f31645c75eca..3660f2ff6ad06 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_unique_flow_ids.ts +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_unique_flow_ids.ts @@ -56,7 +56,7 @@ export const kpiUniqueFlowIdsLensAttributes: LensAttributes = { }, ], datasourceStates: { - indexpattern: { + formBased: { layers: { '5d46d48f-6ce8-46be-a797-17ad50642564': { columns: { diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_unique_private_ips_area.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_unique_private_ips_area.ts index 394bc227e871c..86e9f21d7ffef 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_unique_private_ips_area.ts +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_unique_private_ips_area.ts @@ -82,7 +82,7 @@ export const kpiUniquePrivateIpsAreaLensAttributes: LensAttributes = { }, filters: [], datasourceStates: { - indexpattern: { + formBased: { layers: { '38aa6532-6bf9-4c8f-b2a6-da8d32f7d0d7': { columns: { diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_unique_private_ips_bar.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_unique_private_ips_bar.ts index fe4a698aedf5e..07a81a273e2b5 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_unique_private_ips_bar.ts +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_unique_private_ips_bar.ts @@ -85,7 +85,7 @@ export const kpiUniquePrivateIpsBarLensAttributes: LensAttributes = { }, filters: [], datasourceStates: { - indexpattern: { + formBased: { layers: { 'e406bf4f-942b-41ac-b516-edb5cef06ec8': { columns: { diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_unique_private_ips_destination_metric.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_unique_private_ips_destination_metric.ts index 6e3d440619e76..bcdd7d377b82b 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_unique_private_ips_destination_metric.ts +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_unique_private_ips_destination_metric.ts @@ -11,7 +11,7 @@ export const kpiUniquePrivateIpsDestinationMetricLensAttributes: LensAttributes description: '', state: { datasourceStates: { - indexpattern: { + formBased: { layers: { 'cea37c70-8f91-43bf-b9fe-72d8c049f6a3': { columnOrder: ['bd17c23e-4f83-4108-8005-2669170d064b'], diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_unique_private_ips_source_metric.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_unique_private_ips_source_metric.ts index 3f1110d706300..411dd90828a7b 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_unique_private_ips_source_metric.ts +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_unique_private_ips_source_metric.ts @@ -10,7 +10,7 @@ export const kpiUniquePrivateIpsSourceMetricLensAttributes: LensAttributes = { description: '', state: { datasourceStates: { - indexpattern: { + formBased: { layers: { 'cea37c70-8f91-43bf-b9fe-72d8c049f6a3': { columnOrder: ['bd17c23e-4f83-4108-8005-2669170d064b'], diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/__snapshots__/kpi_total_users_area.test.ts.snap b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/__snapshots__/kpi_total_users_area.test.ts.snap index 11df964f2eca1..f474a4c9d6e10 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/__snapshots__/kpi_total_users_area.test.ts.snap +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/__snapshots__/kpi_total_users_area.test.ts.snap @@ -17,7 +17,7 @@ Object { ], "state": Object { "datasourceStates": Object { - "indexpattern": Object { + "formBased": Object { "layers": Object { "416b6fad-1923-4f6a-a2df-b223bb287e30": Object { "columnOrder": Array [ diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/__snapshots__/kpi_total_users_metric.test.ts.snap b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/__snapshots__/kpi_total_users_metric.test.ts.snap index b53e1bd24d303..eef74c94537d4 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/__snapshots__/kpi_total_users_metric.test.ts.snap +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/__snapshots__/kpi_total_users_metric.test.ts.snap @@ -17,7 +17,7 @@ Object { ], "state": Object { "datasourceStates": Object { - "indexpattern": Object { + "formBased": Object { "layers": Object { "416b6fad-1923-4f6a-a2df-b223bb287e30": Object { "columnOrder": Array [ diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/__snapshots__/kpi_user_authentication_metric_failure.test.ts.snap b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/__snapshots__/kpi_user_authentication_metric_failure.test.ts.snap index 37c20b7e80265..b87fad1faa055 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/__snapshots__/kpi_user_authentication_metric_failure.test.ts.snap +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/__snapshots__/kpi_user_authentication_metric_failure.test.ts.snap @@ -17,7 +17,7 @@ Object { ], "state": Object { "datasourceStates": Object { - "indexpattern": Object { + "formBased": Object { "layers": Object { "4590dafb-4ac7-45aa-8641-47a3ff0b817c": Object { "columnOrder": Array [ diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/__snapshots__/kpi_user_authentications_area.test.ts.snap b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/__snapshots__/kpi_user_authentications_area.test.ts.snap index 1954bccfaffbe..1dcaab239de8e 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/__snapshots__/kpi_user_authentications_area.test.ts.snap +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/__snapshots__/kpi_user_authentications_area.test.ts.snap @@ -22,7 +22,7 @@ Object { ], "state": Object { "datasourceStates": Object { - "indexpattern": Object { + "formBased": Object { "layers": Object { "31213ae3-905b-4e88-b987-0cccb1f3209f": Object { "columnOrder": Array [ diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/__snapshots__/kpi_user_authentications_bar.test.ts.snap b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/__snapshots__/kpi_user_authentications_bar.test.ts.snap index 5335dca6057a6..ac7c883ca71b7 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/__snapshots__/kpi_user_authentications_bar.test.ts.snap +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/__snapshots__/kpi_user_authentications_bar.test.ts.snap @@ -22,7 +22,7 @@ Object { ], "state": Object { "datasourceStates": Object { - "indexpattern": Object { + "formBased": Object { "layers": Object { "31213ae3-905b-4e88-b987-0cccb1f3209f": Object { "columnOrder": Array [ diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/__snapshots__/kpi_user_authentications_metric_success.test.ts.snap b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/__snapshots__/kpi_user_authentications_metric_success.test.ts.snap index 4cadcaf19e91e..0b652257864c0 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/__snapshots__/kpi_user_authentications_metric_success.test.ts.snap +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/__snapshots__/kpi_user_authentications_metric_success.test.ts.snap @@ -17,7 +17,7 @@ Object { ], "state": Object { "datasourceStates": Object { - "indexpattern": Object { + "formBased": Object { "layers": Object { "4590dafb-4ac7-45aa-8641-47a3ff0b817c": Object { "columnOrder": Array [ diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/kpi_total_users_area.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/kpi_total_users_area.ts index c97748077a6be..c241d03266cc3 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/kpi_total_users_area.ts +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/kpi_total_users_area.ts @@ -12,7 +12,7 @@ export const kpiTotalUsersAreaLensAttributes: LensAttributes = { description: '', state: { datasourceStates: { - indexpattern: { + formBased: { layers: { '416b6fad-1923-4f6a-a2df-b223bb287e30': { columnOrder: [ diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/kpi_total_users_metric.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/kpi_total_users_metric.ts index faa6b62e18b65..08cfed0cb91f7 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/kpi_total_users_metric.ts +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/kpi_total_users_metric.ts @@ -11,7 +11,7 @@ export const kpiTotalUsersMetricLensAttributes: LensAttributes = { description: '', state: { datasourceStates: { - indexpattern: { + formBased: { layers: { '416b6fad-1923-4f6a-a2df-b223bb287e30': { columnOrder: ['3e51b035-872c-4b44-824b-fe069c222e91'], diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/kpi_user_authentication_metric_failure.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/kpi_user_authentication_metric_failure.ts index 3f421f8a1c30a..238a8b95e35d9 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/kpi_user_authentication_metric_failure.ts +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/kpi_user_authentication_metric_failure.ts @@ -49,7 +49,7 @@ export const kpiUserAuthenticationsMetricFailureLensAttributes: LensAttributes = }, ], datasourceStates: { - indexpattern: { + formBased: { layers: { '4590dafb-4ac7-45aa-8641-47a3ff0b817c': { columnOrder: ['0eb97c09-a351-4280-97da-944e4bd30dd7'], diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/kpi_user_authentications_area.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/kpi_user_authentications_area.ts index d96ea21489bb2..da6bdf139a1ca 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/kpi_user_authentications_area.ts +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/kpi_user_authentications_area.ts @@ -109,7 +109,7 @@ export const kpiUserAuthenticationsAreaLensAttributes: LensAttributes = { }, ], datasourceStates: { - indexpattern: { + formBased: { layers: { '31213ae3-905b-4e88-b987-0cccb1f3209f': { columnOrder: [ diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/kpi_user_authentications_bar.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/kpi_user_authentications_bar.ts index 4727c6010b751..a4a1629e360de 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/kpi_user_authentications_bar.ts +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/kpi_user_authentications_bar.ts @@ -104,7 +104,7 @@ export const kpiUserAuthenticationsBarLensAttributes: LensAttributes = { }, ], datasourceStates: { - indexpattern: { + formBased: { layers: { '31213ae3-905b-4e88-b987-0cccb1f3209f': { columnOrder: [ diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/kpi_user_authentications_metric_success.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/kpi_user_authentications_metric_success.ts index 3af6f5734d458..58ee89ac81b42 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/kpi_user_authentications_metric_success.ts +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/kpi_user_authentications_metric_success.ts @@ -49,7 +49,7 @@ export const kpiUserAuthenticationsMetricSuccessLensAttributes: LensAttributes = }, ], datasourceStates: { - indexpattern: { + formBased: { layers: { '4590dafb-4ac7-45aa-8641-47a3ff0b817c': { columnOrder: ['0eb97c09-a351-4280-97da-944e4bd30dd7'], 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 5c4de2c8953a3..f98020fe62d7f 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 @@ -5,14 +5,14 @@ * 2.0. */ -import { RESPONDER_CAPABILITIES } from '../../../../common/endpoint/constants'; +import { ENDPOINT_CAPABILITIES } from '../../../../common/endpoint/service/response_actions/constants'; import type { HostMetadata, MaybeImmutable } from '../../../../common/endpoint/types'; export const useDoesEndpointSupportResponder = ( endpointMetadata: MaybeImmutable | undefined ): boolean => { if (endpointMetadata) { - return RESPONDER_CAPABILITIES.every((capability) => + return ENDPOINT_CAPABILITIES.every((capability) => endpointMetadata?.Endpoint.capabilities?.includes(capability) ); } diff --git a/x-pack/plugins/security_solution/public/common/hooks/use_fetch/request_names.ts b/x-pack/plugins/security_solution/public/common/hooks/use_fetch/request_names.ts index 2d6c414090367..326b1ce69ceaa 100644 --- a/x-pack/plugins/security_solution/public/common/hooks/use_fetch/request_names.ts +++ b/x-pack/plugins/security_solution/public/common/hooks/use_fetch/request_names.ts @@ -10,7 +10,6 @@ export const REQUEST_NAMES = { SECURITY_DASHBOARDS: `${APP_UI_ID} fetch security dashboards`, ANOMALIES_TABLE: `${APP_UI_ID} fetch anomalies table data`, GET_RISK_SCORE_DEPRECATED: `${APP_UI_ID} fetch is risk score deprecated`, - GET_SAVED_QUERY: `${APP_UI_ID} fetch saved query`, ENABLE_RISK_SCORE: `${APP_UI_ID} fetch enable risk score`, REFRESH_RISK_SCORE: `${APP_UI_ID} fetch refresh risk score`, UPGRADE_RISK_SCORE: `${APP_UI_ID} fetch upgrade risk score`, diff --git a/x-pack/plugins/security_solution/public/common/translations.ts b/x-pack/plugins/security_solution/public/common/translations.ts index 18661e6580013..824b86cd8bb55 100644 --- a/x-pack/plugins/security_solution/public/common/translations.ts +++ b/x-pack/plugins/security_solution/public/common/translations.ts @@ -37,6 +37,14 @@ export const UPGRADE_ENDPOINT_FOR_RESPONDER = i18n.translate( } ); +export const INSUFFICIENT_PRIVILEGES_FOR_COMMAND = i18n.translate( + 'xpack.securitySolution.endpoint.actions.insufficientPrivileges.error', + { + defaultMessage: + 'You do not have sufficient privileges to use this command. Please contact your administrator for access.', + } +); + export const UNSAVED_TIMELINE_SAVE_PROMPT = i18n.translate( 'xpack.securitySolution.timeline.unsavedWorkMessage', { diff --git a/x-pack/plugins/security_solution/public/detections/components/rules/query_bar/index.tsx b/x-pack/plugins/security_solution/public/detections/components/rules/query_bar/index.tsx index 7d7c9534c1688..ec198514f7e82 100644 --- a/x-pack/plugins/security_solution/public/detections/components/rules/query_bar/index.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/rules/query_bar/index.tsx @@ -53,6 +53,7 @@ export interface QueryBarDefineRuleProps { * called when fetching of saved query fails */ onSavedQueryError?: () => void; + defaultSavedQuery?: SavedQuery | undefined; } const actionTimelineToHide: ActionTimelineToShow[] = ['duplicate', 'createFrom']; @@ -74,6 +75,7 @@ const savedQueryToFieldValue = (savedQuery: SavedQuery): FieldValueQueryBar => ( }); export const QueryBarDefineRule = ({ + defaultSavedQuery, browserFields, dataTestSubj, field, @@ -91,7 +93,7 @@ export const QueryBarDefineRule = ({ const { value: fieldValue, setValue: setFieldValue } = field as FieldHook; const [originalHeight, setOriginalHeight] = useState(-1); const [loadingTimeline, setLoadingTimeline] = useState(false); - const [savedQuery, setSavedQuery] = useState(undefined); + const [savedQuery, setSavedQuery] = useState(defaultSavedQuery); const [isSavedQueryFailedToLoad, setIsSavedQueryFailedToLoad] = useState(false); const { isInvalid, errorMessage } = getFieldValidityAndErrorMessage(field); diff --git a/x-pack/plugins/security_solution/public/detections/components/rules/step_define_rule/index.tsx b/x-pack/plugins/security_solution/public/detections/components/rules/step_define_rule/index.tsx index 21bf8125540b4..1dd2a2d1de798 100644 --- a/x-pack/plugins/security_solution/public/detections/components/rules/step_define_rule/index.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/rules/step_define_rule/index.tsx @@ -24,6 +24,7 @@ import { isEqual, isEmpty, omit } from 'lodash'; import type { FieldSpec } from '@kbn/data-views-plugin/common'; import usePrevious from 'react-use/lib/usePrevious'; +import type { SavedQuery } from '@kbn/data-plugin/public'; import type { DataViewBase } from '@kbn/es-query'; import { FormattedMessage } from '@kbn/i18n-react'; import { isMlRule } from '../../../../../common/machine_learning/helpers'; @@ -88,6 +89,7 @@ interface StepDefineRuleProps extends RuleStepProps { defaultValues: DefineStepRule; onRuleDataChange?: (data: DefineStepRule) => void; onPreviewDisabledStateChange?: (isDisabled: boolean) => void; + defaultSavedQuery?: SavedQuery; } export const MyLabelButton = styled(EuiButtonEmpty)` @@ -124,6 +126,7 @@ const StepDefineRuleComponent: FC = ({ threatIndicesConfig, onRuleDataChange, onPreviewDisabledStateChange, + defaultSavedQuery, }) => { const mlCapabilities = useMlCapabilities(); const [openTimelineSearch, setOpenTimelineSearch] = useState(false); @@ -615,6 +618,7 @@ const StepDefineRuleComponent: FC = ({ onValidityChange: setIsQueryBarValid, onCloseTimelineSearch: handleCloseTimelineSearch, onSavedQueryError: handleSavedQueryError, + defaultSavedQuery, } as QueryBarDefineRuleProps } /> @@ -629,6 +633,7 @@ const StepDefineRuleComponent: FC = ({ openTimelineSearch, formShouldLoadQueryDynamically, handleSavedQueryError, + defaultSavedQuery, ] ); const onOptionsChange = useCallback((field: FieldsEqlOptions, value: string | undefined) => { diff --git a/x-pack/plugins/security_solution/public/detections/components/take_action_dropdown/index.test.tsx b/x-pack/plugins/security_solution/public/detections/components/take_action_dropdown/index.test.tsx index 80ec4956fd1b6..5802ca16fe09f 100644 --- a/x-pack/plugins/security_solution/public/detections/components/take_action_dropdown/index.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/take_action_dropdown/index.test.tsx @@ -36,7 +36,7 @@ import { import { getUserPrivilegesMockDefaultValue } from '../../../common/components/user_privileges/__mocks__'; import { allCasesPermissions } from '../../../cases_test_utils'; import { HostStatus } from '../../../../common/endpoint/types'; -import { RESPONDER_CAPABILITIES } from '../../../../common/endpoint/constants'; +import { ENDPOINT_CAPABILITIES } from '../../../../common/endpoint/service/response_actions/constants'; jest.mock('../../../common/components/user_privileges'); @@ -367,6 +367,50 @@ describe('take action dropdown', () => { }); }); + describe('should correctly enable/disable the "Isolate Host" button', () => { + let wrapper: ReactWrapper; + + const render = (): ReactWrapper => { + wrapper = mount( + + + + ); + wrapper.find('button[data-test-subj="take-action-dropdown-btn"]').simulate('click'); + + return wrapper; + }; + + const isolateHostButtonExists = (): ReturnType => { + return wrapper.exists('[data-test-subj="isolate-host-action-item"]'); + }; + + beforeEach(() => { + setTypeOnEcsDataWithAgentType(); + }); + + it('should show Isolate host button if user has "Host isolation" privileges set to all', async () => { + (useUserPrivileges as jest.Mock).mockReturnValue({ + ...mockInitialUserPrivilegesState(), + endpointPrivileges: { loading: false, canIsolateHost: true }, + }); + render(); + + await waitFor(() => { + expect(isolateHostButtonExists()).toBeTruthy(); + }); + }); + it('should hide Isolate host button if user has "Host isolation" privileges set to none', () => { + (useUserPrivileges as jest.Mock).mockReturnValue({ + ...mockInitialUserPrivilegesState(), + endpointPrivileges: { loading: false, canIsolateHost: false }, + }); + render(); + + expect(isolateHostButtonExists()).toBeFalsy(); + }); + }); + describe('should correctly enable/disable the "Respond" button', () => { let wrapper: ReactWrapper; let apiMocks: ReturnType; @@ -470,7 +514,7 @@ describe('take action dropdown', () => { ...getApiResponse().metadata, Endpoint: { ...getApiResponse().metadata.Endpoint, - capabilities: [...RESPONDER_CAPABILITIES], + capabilities: [...ENDPOINT_CAPABILITIES], }, }, host_status: HostStatus.UNENROLLED, diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/index.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/index.tsx index 53d65e15a468e..f962cd806cc07 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/index.tsx +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/index.tsx @@ -116,7 +116,7 @@ import { ExecutionLogTable } from './execution_log_table/execution_log_table'; import * as detectionI18n from '../../translations'; import * as ruleI18n from '../translations'; import { RuleDetailsContextProvider } from './rule_details_context'; -import { useGetSavedQuery } from './use_get_saved_query'; +import { useGetSavedQuery } from '../use_get_saved_query'; import * as i18n from './translations'; import { NeedAdminForUpdateRulesCallOut } from '../../../../components/callouts/need_admin_for_update_callout'; import { MissingPrivilegesCallOut } from '../../../../components/callouts/missing_privileges_callout'; @@ -306,11 +306,9 @@ const RuleDetailsPageComponent: React.FC = ({ const [filterGroup, setFilterGroup] = useState(FILTER_OPEN); const [dataViewOptions, setDataViewOptions] = useState<{ [x: string]: DataViewListItem }>({}); - // load saved query only if rule type === 'saved_query', as other rule types still can have saved_id property that is not used - // Rule schema allows to save any rule with saved_id property, but it only used for saved_query rule type - // In future we might look in possibility to restrict rule schema (breaking change!) and remove saved_id from the rest of rules through migration - const savedQueryId = rule?.type === 'saved_query' ? rule?.saved_id : undefined; - const { isSavedQueryLoading, savedQueryBar } = useGetSavedQuery(savedQueryId); + const { isSavedQueryLoading, savedQueryBar } = useGetSavedQuery(rule?.saved_id, { + ruleType: rule?.type, + }); const [indicesConfig] = useUiSetting$(DEFAULT_INDEX_KEY); const [threatIndicesConfig] = useUiSetting$(DEFAULT_THREAT_INDEX_KEY); diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/translations.ts b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/translations.ts index b1c7e0033f5f4..1a50d570ea179 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/translations.ts +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/translations.ts @@ -69,10 +69,3 @@ export const DELETED_RULE = i18n.translate( defaultMessage: 'Deleted rule', } ); - -export const SAVED_QUERY_LOAD_ERROR_TOAST = i18n.translate( - 'xpack.securitySolution.hooks.useGetSavedQuery.errorToastMessage', - { - defaultMessage: 'Failed to load the saved query', - } -); diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/use_get_saved_query.ts b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/use_get_saved_query.ts deleted file mode 100644 index 4c3c4c6c42fe0..0000000000000 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/use_get_saved_query.ts +++ /dev/null @@ -1,55 +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 { useEffect, useMemo } from 'react'; - -import { useSavedQueryServices } from '../../../../../common/utils/saved_query_services'; -import type { DefineStepRule } from '../types'; - -import { useFetch, REQUEST_NAMES } from '../../../../../common/hooks/use_fetch'; -import { useAppToasts } from '../../../../../common/hooks/use_app_toasts'; - -import { SAVED_QUERY_LOAD_ERROR_TOAST } from './translations'; - -export const useGetSavedQuery = (savedQueryId: string | undefined) => { - const savedQueryServices = useSavedQueryServices(); - const { addError } = useAppToasts(); - const { fetch, data, isLoading, error } = useFetch( - REQUEST_NAMES.GET_SAVED_QUERY, - savedQueryServices.getSavedQuery - ); - - useEffect(() => { - if (savedQueryId) { - fetch(savedQueryId); - } - }, [savedQueryId, fetch]); - - useEffect(() => { - if (error) { - addError(error, { title: SAVED_QUERY_LOAD_ERROR_TOAST }); - } - }, [error, addError]); - - const savedQueryBar = useMemo( - () => - data - ? { - saved_id: data.id, - filters: data.attributes.filters ?? [], - query: data.attributes.query, - title: data.attributes.title, - } - : null, - [data] - ); - - return { - isSavedQueryLoading: isLoading, - savedQueryBar, - }; -}; diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/edit/index.test.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/edit/index.test.tsx index c990621acd47b..d283879045165 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/edit/index.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/edit/index.test.tsx @@ -31,6 +31,10 @@ jest.mock('react-router-dom', () => { }; }); jest.mock('../../../../../common/hooks/use_app_toasts'); +jest.mock('../use_get_saved_query', () => ({ + __esModule: true, + useGetSavedQuery: jest.fn().mockReturnValue({}), +})); describe('EditRulePage', () => { let appToastsMock: jest.Mocked>; diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/edit/index.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/edit/index.tsx index 7b133d1cb15a3..23d96c93aea2a 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/edit/index.tsx +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/edit/index.tsx @@ -18,6 +18,7 @@ import { FormattedMessage } from '@kbn/i18n-react'; import type { FC } from 'react'; import React, { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { useParams } from 'react-router-dom'; +import { noop } from 'lodash'; import type { DataViewListItem } from '@kbn/data-views-plugin/common'; import type { UpdateRulesSchema } from '../../../../../../common/detection_engine/schemas/request'; @@ -75,6 +76,7 @@ import { HeaderPage } from '../../../../../common/components/header_page'; import { useStartTransaction } from '../../../../../common/lib/apm/use_start_transaction'; import { SINGLE_RULE_ACTIONS } from '../../../../../common/lib/apm/user_actions'; import { PreviewFlyout } from '../preview'; +import { useGetSavedQuery } from '../use_get_saved_query'; const formHookNoop = async (): Promise => undefined; @@ -98,6 +100,11 @@ const EditRulePageComponent: FC = () => { const [ruleLoading, rule] = useRule(ruleId); const loading = ruleLoading || userInfoLoading || listsConfigLoading; + const { isSavedQueryLoading, savedQueryBar, savedQuery } = useGetSavedQuery(rule?.saved_id, { + ruleType: rule?.type, + onError: noop, + }); + const formHooks = useRef({ [RuleStep.defineRule]: formHookNoop, [RuleStep.aboutRule]: formHookNoop, @@ -195,6 +202,17 @@ const EditRulePageComponent: FC = () => { const [indicesConfig] = useUiSetting$(DEFAULT_INDEX_KEY); const [threatIndicesConfig] = useUiSetting$(DEFAULT_THREAT_INDEX_KEY); + const defineStepDataWithSavedQuery = useMemo( + () => + defineStep.data + ? { + ...defineStep.data, + queryBar: savedQueryBar ?? defineStep.data.queryBar, + } + : defineStep.data, + [defineStep.data, savedQueryBar] + ); + const tabs = useMemo( () => [ { @@ -205,19 +223,20 @@ const EditRulePageComponent: FC = () => { content: ( <> - - {defineStep.data != null && ( + + {defineStepDataWithSavedQuery != null && !isSavedQueryLoading && ( )} @@ -305,6 +324,8 @@ const EditRulePageComponent: FC = () => { loading, defineStep.data, isLoading, + isSavedQueryLoading, + defineStepDataWithSavedQuery, setFormHook, dataViewOptions, indicesConfig, @@ -314,6 +335,7 @@ const EditRulePageComponent: FC = () => { scheduleStep.data, actionsStep.data, actionMessageParams, + savedQuery, ] ); diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/translations.ts b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/translations.ts index f49e4695731bc..8b32821bc71f1 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/translations.ts +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/translations.ts @@ -1105,3 +1105,10 @@ export const CANCEL_BUTTON_LABEL = i18n.translate( defaultMessage: 'Cancel', } ); + +export const SAVED_QUERY_LOAD_ERROR_TOAST = i18n.translate( + 'xpack.securitySolution.hooks.useGetSavedQuery.errorToastMessage', + { + defaultMessage: 'Failed to load the saved query', + } +); diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/use_get_saved_query.ts b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/use_get_saved_query.ts new file mode 100644 index 0000000000000..5cd530754d8ce --- /dev/null +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/use_get_saved_query.ts @@ -0,0 +1,73 @@ +/* + * 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 { useMemo } from 'react'; +import { useQuery } from '@tanstack/react-query'; + +import type { Type } from '@kbn/securitysolution-io-ts-alerting-types'; + +import { useSavedQueryServices } from '../../../../common/utils/saved_query_services'; +import type { DefineStepRule } from './types'; + +import { useAppToasts } from '../../../../common/hooks/use_app_toasts'; + +import { SAVED_QUERY_LOAD_ERROR_TOAST } from './translations'; + +interface UseGetSavedQuerySettings { + onError?: (e: unknown) => void; + ruleType: Type | undefined; +} + +export const useGetSavedQuery = ( + savedQueryId: string | undefined, + { ruleType, onError }: UseGetSavedQuerySettings +) => { + const savedQueryServices = useSavedQueryServices(); + const { addError } = useAppToasts(); + + const defaultErrorHandler = (e: unknown) => { + addError(e, { title: SAVED_QUERY_LOAD_ERROR_TOAST }); + }; + + const query = useQuery( + ['detectionEngine', 'rule', 'savedQuery', savedQueryId], + async () => { + if (!savedQueryId) { + return null; + } + + return savedQueryServices.getSavedQuery(savedQueryId); + }, + { + onError: onError ?? defaultErrorHandler, + // load saved query only if rule type === 'saved_query', as other rule types still can have saved_id property that is not used + // Rule schema allows to save any rule with saved_id property, but it only used for saved_query rule type + // In future we might look in possibility to restrict rule schema (breaking change!) and remove saved_id from the rest of rules through migration + enabled: Boolean(savedQueryId) && ruleType === 'saved_query', + retry: false, + } + ); + + const savedQueryBar = useMemo( + () => + query.data + ? { + saved_id: query.data.id, + filters: query.data.attributes.filters ?? [], + query: query.data.attributes.query, + title: query.data.attributes.title, + } + : null, + [query.data] + ); + + return { + isSavedQueryLoading: savedQueryId ? query.isLoading : false, + savedQueryBar, + savedQuery: query.data ?? undefined, + }; +}; diff --git a/x-pack/plugins/security_solution/public/hosts/components/kpi_hosts/index.tsx b/x-pack/plugins/security_solution/public/hosts/components/kpi_hosts/index.tsx index 40281e32c12be..8c315de005691 100644 --- a/x-pack/plugins/security_solution/public/hosts/components/kpi_hosts/index.tsx +++ b/x-pack/plugins/security_solution/public/hosts/components/kpi_hosts/index.tsx @@ -6,81 +6,39 @@ */ import React from 'react'; -import { EuiFlexItem, EuiFlexGroup, EuiSpacer } from '@elastic/eui'; +import { EuiFlexItem, EuiFlexGroup } from '@elastic/eui'; import { HostsKpiHosts } from './hosts'; import { HostsKpiUniqueIps } from './unique_ips'; import type { HostsKpiProps } from './types'; -import { CallOutSwitcher } from '../../../common/components/callouts'; -import * as i18n from './translations'; -import { RiskScoreDocLink } from '../../../risk_score/components/risk_score_onboarding/risk_score_doc_link'; -import { getHostRiskIndex, RiskScoreEntity } from '../../../../common/search_strategy'; -import { useRiskScoreFeatureStatus } from '../../../risk_score/containers/feature_status'; -import { useSpaceId } from '../../../common/hooks/use_space_id'; export const HostsKpiComponent = React.memo( - ({ filterQuery, from, indexNames, to, setQuery, skip, updateDateRange }) => { - const spaceId = useSpaceId(); - const defaultIndex = spaceId ? getHostRiskIndex(spaceId) : undefined; - const { isEnabled, isLicenseValid, isLoading } = useRiskScoreFeatureStatus( - RiskScoreEntity.host, - defaultIndex - ); - - return ( - <> - {isLicenseValid && !isEnabled && !isLoading && ( - <> - - {i18n.LEARN_MORE}{' '} - - - - ), - }} - /> - - - )} - - - - - - - - - - - ); - } + ({ filterQuery, from, indexNames, to, setQuery, skip, updateDateRange }) => ( + + + + + + + + + ) ); HostsKpiComponent.displayName = 'HostsKpiComponent'; diff --git a/x-pack/plugins/security_solution/public/hosts/components/kpi_hosts/translations.ts b/x-pack/plugins/security_solution/public/hosts/components/kpi_hosts/translations.ts deleted file mode 100644 index cc706ed6e68e8..0000000000000 --- a/x-pack/plugins/security_solution/public/hosts/components/kpi_hosts/translations.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { i18n } from '@kbn/i18n'; - -export const LEARN_MORE = i18n.translate('xpack.securitySolution.kpiHost.learnMore', { - defaultMessage: 'Learn more about', -}); - -export const HOST_RISK_DATA = i18n.translate('xpack.securitySolution.kpiHost.hostRiskData', { - defaultMessage: 'host risk data', -}); - -export const ENABLE_HOST_RISK_TEXT = i18n.translate( - 'xpack.securitySolution.kpiHost.enableHostRiskText', - { - defaultMessage: 'Enable host risk module to see more data', - } -); diff --git a/x-pack/plugins/security_solution/public/management/components/console/components/command_input/hooks/use_input_hints.ts b/x-pack/plugins/security_solution/public/management/components/console/components/command_input/hooks/use_input_hints.ts index 3201d3633168a..c8f4f00d0b758 100644 --- a/x-pack/plugins/security_solution/public/management/components/console/components/command_input/hooks/use_input_hints.ts +++ b/x-pack/plugins/security_solution/public/management/components/console/components/command_input/hooks/use_input_hints.ts @@ -43,7 +43,7 @@ export const useInputHints = () => { // If we know the command name and the input popover is not opened, then show hints (if any) if (commandEntered && !isInputPopoverOpen) { // Is valid command name? ==> show usage - if (commandEnteredDefinition) { + if (commandEnteredDefinition && commandEnteredDefinition.helpHidden !== true) { const exampleInstruction = commandEnteredDefinition?.exampleInstruction ?? ''; const exampleUsage = commandEnteredDefinition?.exampleUsage ?? ''; diff --git a/x-pack/plugins/security_solution/public/management/components/console/components/command_list.tsx b/x-pack/plugins/security_solution/public/management/components/console/components/command_list.tsx index d1660b1ffe950..83c5df7397daa 100644 --- a/x-pack/plugins/security_solution/public/management/components/console/components/command_list.tsx +++ b/x-pack/plugins/security_solution/public/management/components/console/components/command_list.tsx @@ -82,6 +82,8 @@ export const CommandList = memo(({ commands, display = 'defaul const dispatch = useConsoleStateDispatch(); const { docLinks } = useKibana().services; + const allowedCommands = commands.filter((command) => command.helpHidden !== true); + const footerMessage = useMemo(() => { return ( (({ commands, display = 'defaul ); const commandsByGroups = useMemo(() => { - return Object.values(groupBy(commands, 'helpGroupLabel')).reduce( + return Object.values(groupBy(allowedCommands, 'helpGroupLabel')).reduce( (acc, current) => { if (current[0].helpGroupPosition !== undefined) { // If it already exists just move it to the end @@ -149,7 +151,7 @@ export const CommandList = memo(({ commands, display = 'defaul }, [] ); - }, [commands]); + }, [allowedCommands]); const getTableItems = useCallback( ( @@ -198,6 +200,7 @@ export const CommandList = memo(({ commands, display = 'defaul /> {command.helpGroupLabel !== HELP_GROUPS.supporting.label && + command.helpHidden !== true && command.RenderComponent && ( { describe('and using the ConsoleManagerInterface via the hook', () => { diff --git a/x-pack/plugins/security_solution/public/management/components/console/components/console_state/state_update_handlers/handle_execute_command.tsx b/x-pack/plugins/security_solution/public/management/components/console/components/console_state/state_update_handlers/handle_execute_command.tsx index 1f2b20df776ee..b54af6f02f4f9 100644 --- a/x-pack/plugins/security_solution/public/management/components/console/components/console_state/state_update_handlers/handle_execute_command.tsx +++ b/x-pack/plugins/security_solution/public/management/components/console/components/console_state/state_update_handlers/handle_execute_command.tsx @@ -449,7 +449,6 @@ export const handleExecuteCommand: ConsoleStoreReducer< // if the Command definition has a `validate()` callback, then call it now if (commandDefinition.validate) { const validationResult = commandDefinition.validate(command); - if (validationResult !== true) { return updateStateWithNewCommandHistoryItem( state, diff --git a/x-pack/plugins/security_solution/public/management/components/console/types.ts b/x-pack/plugins/security_solution/public/management/components/console/types.ts index 5b90a18f27ce1..ef9191bbad522 100644 --- a/x-pack/plugins/security_solution/public/management/components/console/types.ts +++ b/x-pack/plugins/security_solution/public/management/components/console/types.ts @@ -58,9 +58,13 @@ export interface CommandDefinition { */ HelpComponent?: CommandExecutionComponent; /** - * If defined, the button to add to the text bar will be disabled. + * If defined, the button to add to the text bar will be disabled and the user will not be able to use this command if entered into the console. */ helpDisabled?: boolean; + /** + * If defined, the command will be hidden from in the Help menu and help text. It will warn the user and not execute the command if manually typed in. + */ + helpHidden?: boolean; /** * A store for any data needed when the command is executed. * The entire `CommandDefinition` is passed along to the component diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_responder/endpoint_response_actions_console_commands.ts b/x-pack/plugins/security_solution/public/management/components/endpoint_responder/endpoint_response_actions_console_commands.ts index 456162545fec6..b75cd91b768cd 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_responder/endpoint_response_actions_console_commands.ts +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_responder/endpoint_response_actions_console_commands.ts @@ -6,6 +6,10 @@ */ import { i18n } from '@kbn/i18n'; +import type { + EndpointCapabilities, + ConsoleResponseActionCommands, +} from '../../../../common/endpoint/service/response_actions/constants'; import type { Command, CommandDefinition } from '../console'; import { IsolateActionResult } from './isolate_action'; import { ReleaseActionResult } from './release_action'; @@ -14,12 +18,11 @@ import { SuspendProcessActionResult } from './suspend_process_action'; import { EndpointStatusActionResult } from './status_action'; import { GetProcessesActionResult } from './get_processes_action'; import type { ParsedArgData } from '../console/service/parsed_command_input'; -import type { ImmutableArray } from '../../../../common/endpoint/types'; -import { UPGRADE_ENDPOINT_FOR_RESPONDER } from '../../../common/translations'; -import type { - ResponderCapabilities, - ResponderCommands, -} from '../../../../common/endpoint/constants'; +import type { EndpointPrivileges, ImmutableArray } from '../../../../common/endpoint/types'; +import { + INSUFFICIENT_PRIVILEGES_FOR_COMMAND, + UPGRADE_ENDPOINT_FOR_RESPONDER, +} from '../../../common/translations'; import { getCommandAboutInfo } from './get_command_about_info'; const emptyArgumentValidator = (argData: ParsedArgData): true | string => { @@ -45,7 +48,7 @@ const pidValidator = (argData: ParsedArgData): true | string => { } }; -const commandToCapabilitiesMap = new Map([ +const commandToCapabilitiesMap = new Map([ ['isolate', 'isolation'], ['release', 'isolation'], ['kill-process', 'kill_process'], @@ -53,17 +56,46 @@ const commandToCapabilitiesMap = new Map { - const endpointCapabilities: ResponderCapabilities[] = command.commandDefinition.meta.capabilities; - const responderCapability = commandToCapabilitiesMap.get( - command.commandDefinition.name as ResponderCommands - ); +const getRbacControl = ({ + commandName, + privileges, +}: { + commandName: ConsoleResponseActionCommands; + privileges: EndpointPrivileges; +}): boolean => { + const commandToPrivilegeMap = new Map([ + ['isolate', privileges.canIsolateHost], + ['release', privileges.canUnIsolateHost], + ['kill-process', privileges.canKillProcess], + ['suspend-process', privileges.canSuspendProcess], + ['processes', privileges.canGetRunningProcesses], + ]); + return commandToPrivilegeMap.get(commandName as ConsoleResponseActionCommands) ?? false; +}; + +const capabilitiesAndPrivilegesValidator = (command: Command): true | string => { + const privileges = command.commandDefinition.meta.privileges; + const endpointCapabilities: EndpointCapabilities[] = command.commandDefinition.meta.capabilities; + const commandName = command.commandDefinition.name as ConsoleResponseActionCommands; + const responderCapability = commandToCapabilitiesMap.get(commandName); + let errorMessage = ''; + if (!responderCapability) { + errorMessage = errorMessage.concat(UPGRADE_ENDPOINT_FOR_RESPONDER); + } if (responderCapability) { - if (endpointCapabilities.includes(responderCapability)) { - return true; + if (!endpointCapabilities.includes(responderCapability)) { + errorMessage = errorMessage.concat(UPGRADE_ENDPOINT_FOR_RESPONDER); } } - return UPGRADE_ENDPOINT_FOR_RESPONDER; + if (getRbacControl({ commandName, privileges }) !== true) { + errorMessage = errorMessage.concat(INSUFFICIENT_PRIVILEGES_FOR_COMMAND); + } + + if (errorMessage.length) { + return errorMessage; + } + + return true; }; const HELP_GROUPS = Object.freeze({ @@ -93,17 +125,20 @@ const COMMENT_ARG_ABOUT = i18n.translate( export const getEndpointResponseActionsConsoleCommands = ({ endpointAgentId, endpointCapabilities, + endpointPrivileges, }: { endpointAgentId: string; endpointCapabilities: ImmutableArray; + endpointPrivileges: EndpointPrivileges; }): CommandDefinition[] => { - const doesEndpointSupportCommand = (commandName: ResponderCommands) => { + const doesEndpointSupportCommand = (commandName: ConsoleResponseActionCommands) => { const responderCapability = commandToCapabilitiesMap.get(commandName); if (responderCapability) { return endpointCapabilities.includes(responderCapability); } return false; }; + return [ { name: 'isolate', @@ -117,10 +152,11 @@ export const getEndpointResponseActionsConsoleCommands = ({ meta: { endpointId: endpointAgentId, capabilities: endpointCapabilities, + privileges: endpointPrivileges, }, exampleUsage: 'isolate --comment "isolate this host"', exampleInstruction: ENTER_OR_ADD_COMMENT_ARG_INSTRUCTION, - validate: capabilitiesValidator, + validate: capabilitiesAndPrivilegesValidator, args: { comment: { required: false, @@ -132,6 +168,7 @@ export const getEndpointResponseActionsConsoleCommands = ({ helpGroupPosition: HELP_GROUPS.responseActions.position, helpCommandPosition: 0, helpDisabled: doesEndpointSupportCommand('isolate') === false, + helpHidden: !getRbacControl({ commandName: 'isolate', privileges: endpointPrivileges }), }, { name: 'release', @@ -145,10 +182,11 @@ export const getEndpointResponseActionsConsoleCommands = ({ meta: { endpointId: endpointAgentId, capabilities: endpointCapabilities, + privileges: endpointPrivileges, }, exampleUsage: 'release --comment "release this host"', exampleInstruction: ENTER_OR_ADD_COMMENT_ARG_INSTRUCTION, - validate: capabilitiesValidator, + validate: capabilitiesAndPrivilegesValidator, args: { comment: { required: false, @@ -160,6 +198,7 @@ export const getEndpointResponseActionsConsoleCommands = ({ helpGroupPosition: HELP_GROUPS.responseActions.position, helpCommandPosition: 1, helpDisabled: doesEndpointSupportCommand('release') === false, + helpHidden: !getRbacControl({ commandName: 'release', privileges: endpointPrivileges }), }, { name: 'kill-process', @@ -176,10 +215,11 @@ export const getEndpointResponseActionsConsoleCommands = ({ meta: { endpointId: endpointAgentId, capabilities: endpointCapabilities, + privileges: endpointPrivileges, }, exampleUsage: 'kill-process --pid 123 --comment "kill this process"', exampleInstruction: ENTER_PID_OR_ENTITY_ID_INSTRUCTION, - validate: capabilitiesValidator, + validate: capabilitiesAndPrivilegesValidator, mustHaveArgs: true, args: { comment: { @@ -213,6 +253,7 @@ export const getEndpointResponseActionsConsoleCommands = ({ helpGroupPosition: HELP_GROUPS.responseActions.position, helpCommandPosition: 4, helpDisabled: doesEndpointSupportCommand('kill-process') === false, + helpHidden: !getRbacControl({ commandName: 'kill-process', privileges: endpointPrivileges }), }, { name: 'suspend-process', @@ -229,10 +270,11 @@ export const getEndpointResponseActionsConsoleCommands = ({ meta: { endpointId: endpointAgentId, capabilities: endpointCapabilities, + privileges: endpointPrivileges, }, exampleUsage: 'suspend-process --pid 123 --comment "suspend this process"', exampleInstruction: ENTER_PID_OR_ENTITY_ID_INSTRUCTION, - validate: capabilitiesValidator, + validate: capabilitiesAndPrivilegesValidator, mustHaveArgs: true, args: { comment: { @@ -269,6 +311,10 @@ export const getEndpointResponseActionsConsoleCommands = ({ helpGroupPosition: HELP_GROUPS.responseActions.position, helpCommandPosition: 5, helpDisabled: doesEndpointSupportCommand('suspend-process') === false, + helpHidden: !getRbacControl({ + commandName: 'suspend-process', + privileges: endpointPrivileges, + }), }, { name: 'status', @@ -298,10 +344,11 @@ export const getEndpointResponseActionsConsoleCommands = ({ meta: { endpointId: endpointAgentId, capabilities: endpointCapabilities, + privileges: endpointPrivileges, }, exampleUsage: 'processes --comment "get the processes"', exampleInstruction: ENTER_OR_ADD_COMMENT_ARG_INSTRUCTION, - validate: capabilitiesValidator, + validate: capabilitiesAndPrivilegesValidator, args: { comment: { required: false, @@ -313,6 +360,7 @@ export const getEndpointResponseActionsConsoleCommands = ({ helpGroupPosition: HELP_GROUPS.responseActions.position, helpCommandPosition: 3, helpDisabled: doesEndpointSupportCommand('processes') === false, + helpHidden: !getRbacControl({ commandName: 'processes', privileges: endpointPrivileges }), }, ]; }; diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_responder/integration_tests/get_processes_action.test.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_responder/integration_tests/get_processes_action.test.tsx index 3b46967c33abf..e39cea0b7ce1c 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_responder/integration_tests/get_processes_action.test.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_responder/integration_tests/get_processes_action.test.tsx @@ -16,12 +16,13 @@ import { getEndpointResponseActionsConsoleCommands } from '../endpoint_response_ import { responseActionsHttpMocks } from '../../../mocks/response_actions_http_mocks'; import { enterConsoleCommand } from '../../console/mocks'; import { waitFor } from '@testing-library/react'; -import type { ResponderCapabilities } from '../../../../../common/endpoint/constants'; -import { RESPONDER_CAPABILITIES } from '../../../../../common/endpoint/constants'; +import { getEndpointAuthzInitialState } from '../../../../../common/endpoint/service/authz'; +import type { EndpointCapabilities } from '../../../../../common/endpoint/service/response_actions/constants'; +import { ENDPOINT_CAPABILITIES } from '../../../../../common/endpoint/service/response_actions/constants'; describe('When using processes action from response actions console', () => { let render: ( - capabilities?: ResponderCapabilities[] + capabilities?: EndpointCapabilities[] ) => Promise>; let renderResult: ReturnType; let apiMocks: ReturnType; @@ -34,7 +35,7 @@ describe('When using processes action from response actions console', () => { apiMocks = responseActionsHttpMocks(mockedContext.coreStart.http); - render = async (capabilities: ResponderCapabilities[] = [...RESPONDER_CAPABILITIES]) => { + render = async (capabilities: EndpointCapabilities[] = [...ENDPOINT_CAPABILITIES]) => { renderResult = mockedContext.render( { @@ -44,6 +45,13 @@ describe('When using processes action from response actions console', () => { commands: getEndpointResponseActionsConsoleCommands({ endpointAgentId: 'a.b.c', endpointCapabilities: [...capabilities], + endpointPrivileges: { + ...getEndpointAuthzInitialState(), + loading: false, + canKillProcess: true, + canSuspendProcess: true, + canGetRunningProcesses: true, + }, }), }, }; diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_responder/integration_tests/isolate_action.test.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_responder/integration_tests/isolate_action.test.tsx index 10dde22e6083a..f111b7aafbff6 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_responder/integration_tests/isolate_action.test.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_responder/integration_tests/isolate_action.test.tsx @@ -16,13 +16,14 @@ import { getEndpointResponseActionsConsoleCommands } from '../endpoint_response_ import { responseActionsHttpMocks } from '../../../mocks/response_actions_http_mocks'; import { enterConsoleCommand } from '../../console/mocks'; import { waitFor } from '@testing-library/react'; -import type { ResponderCapabilities } from '../../../../../common/endpoint/constants'; -import { RESPONDER_CAPABILITIES } from '../../../../../common/endpoint/constants'; import { getDeferred } from '../../../mocks/utils'; +import { getEndpointAuthzInitialState } from '../../../../../common/endpoint/service/authz'; +import type { EndpointCapabilities } from '../../../../../common/endpoint/service/response_actions/constants'; +import { ENDPOINT_CAPABILITIES } from '../../../../../common/endpoint/service/response_actions/constants'; describe('When using isolate action from response actions console', () => { let render: ( - capabilities?: ResponderCapabilities[] + capabilities?: EndpointCapabilities[] ) => Promise>; let renderResult: ReturnType; let apiMocks: ReturnType; @@ -35,7 +36,7 @@ describe('When using isolate action from response actions console', () => { apiMocks = responseActionsHttpMocks(mockedContext.coreStart.http); - render = async (capabilities: ResponderCapabilities[] = [...RESPONDER_CAPABILITIES]) => { + render = async (capabilities: EndpointCapabilities[] = [...ENDPOINT_CAPABILITIES]) => { renderResult = mockedContext.render( { @@ -45,6 +46,11 @@ describe('When using isolate action from response actions console', () => { commands: getEndpointResponseActionsConsoleCommands({ endpointAgentId: 'a.b.c', endpointCapabilities: [...capabilities], + endpointPrivileges: { + ...getEndpointAuthzInitialState(), + loading: false, + canIsolateHost: true, + }, }), }, }; diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_responder/integration_tests/kill_process_action.test.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_responder/integration_tests/kill_process_action.test.tsx index 12cec2dd613b5..631da12cc1d3a 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_responder/integration_tests/kill_process_action.test.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_responder/integration_tests/kill_process_action.test.tsx @@ -16,12 +16,13 @@ import { getEndpointResponseActionsConsoleCommands } from '../endpoint_response_ import { enterConsoleCommand } from '../../console/mocks'; import { waitFor } from '@testing-library/react'; import { responseActionsHttpMocks } from '../../../mocks/response_actions_http_mocks'; -import type { ResponderCapabilities } from '../../../../../common/endpoint/constants'; -import { RESPONDER_CAPABILITIES } from '../../../../../common/endpoint/constants'; +import { getEndpointAuthzInitialState } from '../../../../../common/endpoint/service/authz'; +import type { EndpointCapabilities } from '../../../../../common/endpoint/service/response_actions/constants'; +import { ENDPOINT_CAPABILITIES } from '../../../../../common/endpoint/service/response_actions/constants'; describe('When using the kill-process action from response actions console', () => { let render: ( - capabilities?: ResponderCapabilities[] + capabilities?: EndpointCapabilities[] ) => Promise>; let renderResult: ReturnType; let apiMocks: ReturnType; @@ -34,7 +35,7 @@ describe('When using the kill-process action from response actions console', () apiMocks = responseActionsHttpMocks(mockedContext.coreStart.http); - render = async (capabilities: ResponderCapabilities[] = [...RESPONDER_CAPABILITIES]) => { + render = async (capabilities: EndpointCapabilities[] = [...ENDPOINT_CAPABILITIES]) => { renderResult = mockedContext.render( { @@ -44,6 +45,13 @@ describe('When using the kill-process action from response actions console', () commands: getEndpointResponseActionsConsoleCommands({ endpointAgentId: 'a.b.c', endpointCapabilities: [...capabilities], + endpointPrivileges: { + ...getEndpointAuthzInitialState(), + loading: false, + canKillProcess: true, + canSuspendProcess: true, + canGetRunningProcesses: true, + }, }), }, }; diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_responder/integration_tests/release_action.test.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_responder/integration_tests/release_action.test.tsx index c2052a4e6401a..e377d23c2c145 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_responder/integration_tests/release_action.test.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_responder/integration_tests/release_action.test.tsx @@ -16,13 +16,14 @@ import { getEndpointResponseActionsConsoleCommands } from '../endpoint_response_ import { enterConsoleCommand } from '../../console/mocks'; import { waitFor } from '@testing-library/react'; import { responseActionsHttpMocks } from '../../../mocks/response_actions_http_mocks'; -import type { ResponderCapabilities } from '../../../../../common/endpoint/constants'; -import { RESPONDER_CAPABILITIES } from '../../../../../common/endpoint/constants'; import { getDeferred } from '../../../mocks/utils'; +import { getEndpointAuthzInitialState } from '../../../../../common/endpoint/service/authz'; +import type { EndpointCapabilities } from '../../../../../common/endpoint/service/response_actions/constants'; +import { ENDPOINT_CAPABILITIES } from '../../../../../common/endpoint/service/response_actions/constants'; describe('When using the release action from response actions console', () => { let render: ( - capabilities?: ResponderCapabilities[] + capabilities?: EndpointCapabilities[] ) => Promise>; let renderResult: ReturnType; let apiMocks: ReturnType; @@ -35,7 +36,7 @@ describe('When using the release action from response actions console', () => { apiMocks = responseActionsHttpMocks(mockedContext.coreStart.http); - render = async (capabilities: ResponderCapabilities[] = [...RESPONDER_CAPABILITIES]) => { + render = async (capabilities: EndpointCapabilities[] = [...ENDPOINT_CAPABILITIES]) => { renderResult = mockedContext.render( { @@ -45,6 +46,10 @@ describe('When using the release action from response actions console', () => { commands: getEndpointResponseActionsConsoleCommands({ endpointAgentId: 'a.b.c', endpointCapabilities: [...capabilities], + endpointPrivileges: { + ...getEndpointAuthzInitialState(), + loading: false, + }, }), }, }; diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_responder/integration_tests/suspend_process_action.test.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_responder/integration_tests/suspend_process_action.test.tsx index 28fe91999662a..a41ed9fe3d6eb 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_responder/integration_tests/suspend_process_action.test.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_responder/integration_tests/suspend_process_action.test.tsx @@ -16,12 +16,13 @@ import { getEndpointResponseActionsConsoleCommands } from '../endpoint_response_ import { enterConsoleCommand } from '../../console/mocks'; import { waitFor } from '@testing-library/react'; import { responseActionsHttpMocks } from '../../../mocks/response_actions_http_mocks'; -import type { ResponderCapabilities } from '../../../../../common/endpoint/constants'; -import { RESPONDER_CAPABILITIES } from '../../../../../common/endpoint/constants'; +import { getEndpointAuthzInitialState } from '../../../../../common/endpoint/service/authz'; +import type { EndpointCapabilities } from '../../../../../common/endpoint/service/response_actions/constants'; +import { ENDPOINT_CAPABILITIES } from '../../../../../common/endpoint/service/response_actions/constants'; describe('When using the suspend-process action from response actions console', () => { let render: ( - capabilities?: ResponderCapabilities[] + capabilities?: EndpointCapabilities[] ) => Promise>; let renderResult: ReturnType; let apiMocks: ReturnType; @@ -34,7 +35,7 @@ describe('When using the suspend-process action from response actions console', apiMocks = responseActionsHttpMocks(mockedContext.coreStart.http); - render = async (capabilities: ResponderCapabilities[] = [...RESPONDER_CAPABILITIES]) => { + render = async (capabilities: EndpointCapabilities[] = [...ENDPOINT_CAPABILITIES]) => { renderResult = mockedContext.render( { @@ -44,6 +45,13 @@ describe('When using the suspend-process action from response actions console', commands: getEndpointResponseActionsConsoleCommands({ endpointAgentId: 'a.b.c', endpointCapabilities: [...capabilities], + endpointPrivileges: { + ...getEndpointAuthzInitialState(), + loading: false, + canKillProcess: true, + canSuspendProcess: true, + canGetRunningProcesses: true, + }, }), }, }; diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/actions_log_filter.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/actions_log_filter.tsx index e4f03aec7953a..8482e275f7811 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/actions_log_filter.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/actions_log_filter.tsx @@ -8,7 +8,7 @@ import { orderBy } from 'lodash/fp'; import React, { memo, useEffect, useMemo, useState, useCallback, useRef } from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiSelectable, EuiPopoverTitle } from '@elastic/eui'; -import type { ResponseActions } from '../../../../../common/endpoint/service/response_actions/constants'; +import type { ResponseActionsApiCommandNames } from '../../../../../common/endpoint/service/response_actions/constants'; import { ActionsLogFilterPopover } from './actions_log_filter_popover'; import { type FilterItems, type FilterName, useActionsLogFilter, getUiCommand } from './hooks'; import { ClearAllButton } from './clear_all_button'; @@ -105,7 +105,9 @@ export const ActionsLogFilter = memo( // update URL params if (filterName === 'actions') { setUrlActionsFilters( - selectedItems.map((item) => getUiCommand(item as ResponseActions)).join() + selectedItems + .map((item) => getUiCommand(item as ResponseActionsApiCommandNames)) + .join() ); } else if (filterName === 'hosts') { setUrlHostsFilters(selectedItems.join()); diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/actions_log_users_filter.test.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/actions_log_users_filter.test.tsx index 5cf43df4ee2dc..60b5f5368dafc 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/actions_log_users_filter.test.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/actions_log_users_filter.test.tsx @@ -44,9 +44,7 @@ describe('Users filter', () => { const searchInput = renderResult.getByTestId(`${testPrefix}-search`); expect(searchInput).toBeTruthy(); - expect(searchInput.getAttribute('placeholder')).toEqual( - 'Filter by user or comma separated list of users' - ); + expect(searchInput.getAttribute('placeholder')).toEqual('Filter by username'); }); it('should search on given search string on enter', () => { diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/hooks.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/hooks.tsx index 34cc5a3ca0f99..e72e8614d6764 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/hooks.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/hooks.tsx @@ -11,11 +11,12 @@ import type { OnRefreshChangeProps, } from '@elastic/eui/src/components/date_picker/types'; import type { - ResponseActions, + ConsoleResponseActionCommands, + ResponseActionsApiCommandNames, ResponseActionStatus, } from '../../../../../common/endpoint/service/response_actions/constants'; import { - RESPONSE_ACTION_COMMANDS, + RESPONSE_ACTION_API_COMMANDS_NAMES, RESPONSE_ACTION_STATUS, } from '../../../../../common/endpoint/service/response_actions/constants'; import type { DateRangePickerValues } from './actions_log_date_range_picker'; @@ -131,8 +132,8 @@ export const getActionStatus = (status: ResponseActionStatus): string => { * running-processes -> processes */ export const getUiCommand = ( - command: ResponseActions -): Exclude | 'release' | 'processes' => { + command: ResponseActionsApiCommandNames +): ConsoleResponseActionCommands => { if (command === 'unisolate') { return 'release'; } else if (command === 'running-processes') { @@ -148,8 +149,8 @@ export const getUiCommand = ( * processes -> running-processes */ export const getCommandKey = ( - uiCommand: Exclude | 'release' | 'processes' -): ResponseActions => { + uiCommand: ConsoleResponseActionCommands +): ResponseActionsApiCommandNames => { if (uiCommand === 'release') { return 'unisolate'; } else if (uiCommand === 'processes') { @@ -231,7 +232,7 @@ export const useActionsLogFilter = ({ })) : isHostsFilter ? [] - : RESPONSE_ACTION_COMMANDS.map((commandName) => ({ + : RESPONSE_ACTION_API_COMMANDS_NAMES.map((commandName) => ({ key: commandName, label: getUiCommand(commandName), checked: diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/use_action_history_url_params.test.ts b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/use_action_history_url_params.test.ts index 5b62dbe814d3c..cd5655c7b96ea 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/use_action_history_url_params.test.ts +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/use_action_history_url_params.test.ts @@ -5,8 +5,18 @@ * 2.0. */ import { actionsLogFiltersFromUrlParams } from './use_action_history_url_params'; +import type { ConsoleResponseActionCommands } from '../../../../../common/endpoint/service/response_actions/constants'; +import { CONSOLE_RESPONSE_ACTION_COMMANDS } from '../../../../../common/endpoint/service/response_actions/constants'; describe('#actionsLogFiltersFromUrlParams', () => { + const getConsoleCommandsAsString = (): string => { + return [...CONSOLE_RESPONSE_ACTION_COMMANDS].sort().join(','); + }; + + const getConsoleCommandsAsArray = (): ConsoleResponseActionCommands[] => { + return [...CONSOLE_RESPONSE_ACTION_COMMANDS].sort(); + }; + it('should not use invalid command values from URL params', () => { expect(actionsLogFiltersFromUrlParams({ commands: 'asa,was' })).toEqual({ commands: undefined, @@ -21,10 +31,10 @@ describe('#actionsLogFiltersFromUrlParams', () => { it('should use valid command values from URL params', () => { expect( actionsLogFiltersFromUrlParams({ - commands: 'kill-process,isolate,processes,release,suspend-process', + commands: getConsoleCommandsAsString(), }) ).toEqual({ - commands: ['isolate', 'kill-process', 'processes', 'release', 'suspend-process'], + commands: getConsoleCommandsAsArray(), endDate: undefined, hosts: undefined, startDate: undefined, @@ -62,7 +72,7 @@ describe('#actionsLogFiltersFromUrlParams', () => { it('should use valid command and status along with given host, user and date values from URL params', () => { expect( actionsLogFiltersFromUrlParams({ - commands: 'release,kill-process,isolate,processes,suspend-process', + commands: getConsoleCommandsAsString(), statuses: 'successful,pending,failed', hosts: 'host-1,host-2', users: 'user-1,user-2', @@ -70,7 +80,7 @@ describe('#actionsLogFiltersFromUrlParams', () => { endDate: '2022-09-12T08:30:33.140Z', }) ).toEqual({ - commands: ['isolate', 'kill-process', 'processes', 'release', 'suspend-process'], + commands: getConsoleCommandsAsArray(), endDate: '2022-09-12T08:30:33.140Z', hosts: ['host-1', 'host-2'], startDate: '2022-09-12T08:00:00.000Z', diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/use_action_history_url_params.ts b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/use_action_history_url_params.ts index 8e12f429c3183..a0e1623055f26 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/use_action_history_url_params.ts +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/use_action_history_url_params.ts @@ -6,10 +6,11 @@ */ import { useCallback, useEffect, useMemo, useState } from 'react'; import { useHistory, useLocation } from 'react-router-dom'; +import type { ConsoleResponseActionCommands } from '../../../../../common/endpoint/service/response_actions/constants'; import { - RESPONSE_ACTION_COMMANDS, + RESPONSE_ACTION_API_COMMANDS_NAMES, RESPONSE_ACTION_STATUS, - type ResponseActions, + type ResponseActionsApiCommandNames, type ResponseActionStatus, } from '../../../../../common/endpoint/service/response_actions/constants'; import { useUrlParams } from '../../../hooks/use_url_params'; @@ -24,9 +25,7 @@ interface UrlParamsActionsLogFilters { } interface ActionsLogFiltersFromUrlParams { - commands?: Array< - Exclude | 'release' | 'processes' - >; + commands?: ConsoleResponseActionCommands[]; hosts?: string[]; statuses?: ResponseActionStatus[]; startDate?: string; @@ -61,7 +60,7 @@ export const actionsLogFiltersFromUrlParams = ( .split(',') .reduce['commands']>((acc, curr) => { if ( - RESPONSE_ACTION_COMMANDS.includes(curr as ResponseActions) || + RESPONSE_ACTION_API_COMMANDS_NAMES.includes(curr as ResponseActionsApiCommandNames) || curr === 'release' || curr === 'processes' ) { diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/response_actions_log.test.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/response_actions_log.test.tsx index ae59f3ceaa8b3..09d201c171e9e 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/response_actions_log.test.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/response_actions_log.test.tsx @@ -20,7 +20,7 @@ import { MANAGEMENT_PATH } from '../../../../common/constants'; import { getActionListMock } from './mocks'; import { useGetEndpointsList } from '../../hooks/endpoint/use_get_endpoints_list'; import uuid from 'uuid'; -import { RESPONSE_ACTION_COMMANDS } from '../../../../common/endpoint/service/response_actions/constants'; +import { RESPONSE_ACTION_API_COMMANDS_NAMES } from '../../../../common/endpoint/service/response_actions/constants'; let mockUseGetEndpointActionList: { isFetched?: boolean; @@ -557,7 +557,9 @@ describe('Response actions history', () => { userEvent.click(getByTestId(`${testPrefix}-${filterPrefix}-popoverButton`)); const filterList = getByTestId(`${testPrefix}-${filterPrefix}-popoverList`); expect(filterList).toBeTruthy(); - expect(filterList.querySelectorAll('ul>li').length).toEqual(RESPONSE_ACTION_COMMANDS.length); + expect(filterList.querySelectorAll('ul>li').length).toEqual( + RESPONSE_ACTION_API_COMMANDS_NAMES.length + ); expect( Array.from(filterList.querySelectorAll('ul>li')).map((option) => option.textContent) ).toEqual(['isolate', 'release', 'kill-process', 'suspend-process', 'processes', 'get-file']); diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/response_actions_log.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/response_actions_log.tsx index ac9a0829bb7b8..fc046ff574685 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/response_actions_log.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/response_actions_log.tsx @@ -11,7 +11,7 @@ import type { CriteriaWithPagination } from '@elastic/eui'; import React, { memo, useCallback, useEffect, useMemo, useState } from 'react'; import { FormattedMessage } from '@kbn/i18n-react'; import type { - ResponseActions, + ResponseActionsApiCommandNames, ResponseActionStatus, } from '../../../../common/endpoint/service/response_actions/constants'; @@ -142,7 +142,7 @@ export const ResponseActionsLog = memo< (selectedCommands: string[]) => { setQueryParams((prevState) => ({ ...prevState, - commands: selectedCommands as ResponseActions[], + commands: selectedCommands as ResponseActionsApiCommandNames[], })); }, [setQueryParams] diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/translations.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/translations.tsx index 36dfc76dc1d9e..363da92a025bf 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/translations.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/translations.tsx @@ -177,6 +177,6 @@ export const FILTER_NAMES = Object.freeze({ defaultMessage: 'Statuses', }), users: i18n.translate('xpack.securitySolution.responseActionsList.list.filter.users', { - defaultMessage: 'Filter by user or comma separated list of users', + defaultMessage: 'Filter by username', }), }); diff --git a/x-pack/plugins/security_solution/public/management/hooks/endpoint/use_with_show_endpoint_responder.tsx b/x-pack/plugins/security_solution/public/management/hooks/endpoint/use_with_show_endpoint_responder.tsx index 8c0236a42073d..7931e8a9765b8 100644 --- a/x-pack/plugins/security_solution/public/management/hooks/endpoint/use_with_show_endpoint_responder.tsx +++ b/x-pack/plugins/security_solution/public/management/hooks/endpoint/use_with_show_endpoint_responder.tsx @@ -25,12 +25,12 @@ const RESPONDER_PAGE_TITLE = i18n.translate('xpack.securitySolution.responder_ov export const useWithShowEndpointResponder = (): ShowEndpointResponseActionsConsole => { const consoleManager = useConsoleManager(); - const { canAccessResponseConsole } = useUserPrivileges().endpointPrivileges; + const endpointPrivileges = useUserPrivileges().endpointPrivileges; return useCallback( (endpointMetadata: HostMetadata) => { // If no authz, just exit and log something to the console - if (!canAccessResponseConsole) { + if (!endpointPrivileges.canAccessResponseConsole) { window.console.error(new Error('Access denied to endpoint response actions console')); return; } @@ -51,6 +51,7 @@ export const useWithShowEndpointResponder = (): ShowEndpointResponseActionsConso commands: getEndpointResponseActionsConsoleCommands({ endpointAgentId, endpointCapabilities: endpointMetadata.Endpoint.capabilities ?? [], + endpointPrivileges, }), 'data-test-subj': 'endpointResponseActionsConsole', TitleComponent: () => , @@ -62,6 +63,6 @@ export const useWithShowEndpointResponder = (): ShowEndpointResponseActionsConso .show(); } }, - [canAccessResponseConsole, consoleManager] + [endpointPrivileges, consoleManager] ); }; diff --git a/x-pack/plugins/security_solution/public/management/links.test.ts b/x-pack/plugins/security_solution/public/management/links.test.ts index c8166563428ab..3ddd52b918efd 100644 --- a/x-pack/plugins/security_solution/public/management/links.test.ts +++ b/x-pack/plugins/security_solution/public/management/links.test.ts @@ -60,7 +60,7 @@ describe('links', () => { } as unknown as StartPlugins); }); - it('it returns all links without filtering when having isolate permissions', async () => { + it('it returns all links without filtering when having isolate permission', async () => { (licenseService.isPlatinumPlus as jest.Mock).mockReturnValue(true); fakeHttpServices.get.mockResolvedValue({ total: 0 }); const filteredLinks = await getManagementFilteredLinks( @@ -70,30 +70,67 @@ describe('links', () => { expect(filteredLinks).toEqual(links); }); - it('it returns all links without filtering when not having isolation permissions but has at least one host isolation exceptions entry', async () => { + it('it returns all but response actions history link when NO isolation permission but HAS at least one host isolation exceptions entry', async () => { + (licenseService.isPlatinumPlus as jest.Mock).mockReturnValue(false); fakeHttpServices.get.mockResolvedValue({ total: 1 }); const filteredLinks = await getManagementFilteredLinks( coreMockStarted, getPlugins(['superuser']) ); - (licenseService.isPlatinumPlus as jest.Mock).mockReturnValue(false); - expect(filteredLinks).toEqual(links); + expect(filteredLinks).toEqual({ + ...links, + links: links.links?.filter((link) => link.id !== SecurityPageName.responseActionsHistory), + }); }); - it('it returns all but response actions history when no access privilege to either response actions history or HIE but have at least one HIE entry', async () => { + it('it returns all but response actions history when NO access to either response actions history or HIE but have at least one HIE entry', async () => { fakeHttpServices.get.mockResolvedValue({ total: 1 }); + (licenseService.isPlatinumPlus as jest.Mock).mockReturnValue(false); const filteredLinks = await getManagementFilteredLinks( coreMockStarted, getPlugins(['superuser']) ); + + expect(filteredLinks).toEqual({ + ...links, + links: links.links?.filter((link) => link.id !== SecurityPageName.responseActionsHistory), + }); + }); + + it('it returns all but response actions history when NO enterprise license and can not isolate but HAS an HIE entry', async () => { + (licenseService.isEnterprise as jest.Mock).mockReturnValue(false); (licenseService.isPlatinumPlus as jest.Mock).mockReturnValue(false); + fakeHttpServices.get.mockResolvedValue({ total: 1 }); + const filteredLinks = await getManagementFilteredLinks( + coreMockStarted, + getPlugins(['superuser']) + ); + expect(filteredLinks).toEqual({ ...links, links: links.links?.filter((link) => link.id !== SecurityPageName.responseActionsHistory), }); }); - it('it returns filtered links when not having isolation permissions and no host isolation exceptions entry', async () => { + it('it returns all but response actions history and HIE links when NO enterprise license and no HIE entry', async () => { + (licenseService.isEnterprise as jest.Mock).mockReturnValue(false); + fakeHttpServices.get.mockResolvedValue({ total: 0 }); + const filteredLinks = await getManagementFilteredLinks( + coreMockStarted, + getPlugins(['superuser']) + ); + + expect(filteredLinks).toEqual({ + ...links, + links: links.links?.filter( + (link) => + link.id !== SecurityPageName.hostIsolationExceptions && + link.id !== SecurityPageName.responseActionsHistory + ), + }); + }); + + it('it returns filtered links when not having NO isolation permission and NO host isolation exceptions entry', async () => { fakeHttpServices.get.mockResolvedValue({ total: 0 }); (licenseService.isPlatinumPlus as jest.Mock).mockReturnValue(false); const filteredLinks = await getManagementFilteredLinks(coreMockStarted, getPlugins([])); diff --git a/x-pack/plugins/security_solution/public/management/links.ts b/x-pack/plugins/security_solution/public/management/links.ts index 12a904201a9c5..75436383547ab 100644 --- a/x-pack/plugins/security_solution/public/management/links.ts +++ b/x-pack/plugins/security_solution/public/management/links.ts @@ -11,6 +11,7 @@ import { i18n } from '@kbn/i18n'; import { calculateEndpointAuthz, getEndpointAuthzInitialState, + calculatePermissionsFromCapabilities, } from '../../common/endpoint/service/authz'; import { BLOCKLIST_PATH, @@ -231,35 +232,54 @@ const excludeLinks = (linkIds: SecurityPageName[]) => ({ links: links.links?.filter((link) => !linkIds.includes(link.id)), }); +const getHostIsolationExceptionTotal = async (http: CoreStart['http']) => { + const hostIsolationExceptionsApiClientInstance = + HostIsolationExceptionsApiClient.getInstance(http); + const summaryResponse = await hostIsolationExceptionsApiClientInstance.summary(); + return summaryResponse.total; +}; + export const getManagementFilteredLinks = async ( core: CoreStart, plugins: StartPlugins ): Promise => { const fleetAuthz = plugins.fleet?.authz; const isEndpointRbacEnabled = ExperimentalFeaturesService.get().endpointRbacEnabled; + const endpointPermissions = calculatePermissionsFromCapabilities(core.application.capabilities); try { const currentUserResponse = await plugins.security.authc.getCurrentUser(); - const privileges = fleetAuthz + const { canAccessEndpointManagement, canIsolateHost, canReadActionsLogManagement } = fleetAuthz ? calculateEndpointAuthz( licenseService, fleetAuthz, currentUserResponse.roles, - isEndpointRbacEnabled + isEndpointRbacEnabled, + endpointPermissions ) : getEndpointAuthzInitialState(); - if (!privileges.canAccessEndpointManagement) { + + if (!canAccessEndpointManagement) { return excludeLinks([ SecurityPageName.hostIsolationExceptions, SecurityPageName.responseActionsHistory, ]); } - if (!privileges.canIsolateHost || !privileges.canReadActionsLogManagement) { - const hostIsolationExceptionsApiClientInstance = HostIsolationExceptionsApiClient.getInstance( - core.http - ); - const summaryResponse = await hostIsolationExceptionsApiClientInstance.summary(); - if (!summaryResponse.total) { + + if (!canReadActionsLogManagement) { + // <= enterprise license + const hostExceptionCount = await getHostIsolationExceptionTotal(core.http); + if (!canIsolateHost && !hostExceptionCount) { + return excludeLinks([ + SecurityPageName.hostIsolationExceptions, + SecurityPageName.responseActionsHistory, + ]); + } + return excludeLinks([SecurityPageName.responseActionsHistory]); + } else if (!canIsolateHost) { + const hostExceptionCount = await getHostIsolationExceptionTotal(core.http); + if (!hostExceptionCount) { + // <= platinum so exclude also links that require enterprise return excludeLinks([ SecurityPageName.hostIsolationExceptions, SecurityPageName.responseActionsHistory, diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/components/search_bar.test.tsx b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/components/integration_tests/search_bar.test.tsx similarity index 84% rename from x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/components/search_bar.test.tsx rename to x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/components/integration_tests/search_bar.test.tsx index 57611fcdf2484..1b1debe616844 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/components/search_bar.test.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/components/integration_tests/search_bar.test.tsx @@ -6,18 +6,17 @@ */ import React from 'react'; -import type { AppContextTestRender } from '../../../../../common/mock/endpoint'; -import { createAppRootMockRenderer } from '../../../../../common/mock/endpoint'; -import { endpointPageHttpMock } from '../../mocks'; +import type { AppContextTestRender } from '../../../../../../common/mock/endpoint'; +import { createAppRootMockRenderer } from '../../../../../../common/mock/endpoint'; +import { endpointPageHttpMock } from '../../../mocks'; import { act, waitFor, cleanup } from '@testing-library/react'; -import { getEndpointListPath } from '../../../../common/routing'; -import { AdminSearchBar } from './search_bar'; +import { getEndpointListPath } from '../../../../../common/routing'; +import { AdminSearchBar } from '../search_bar'; import { fireEvent } from '@testing-library/dom'; -import { uiQueryParams } from '../../store/selectors'; -import type { EndpointIndexUIQueryParams } from '../../types'; +import { uiQueryParams } from '../../../store/selectors'; +import type { EndpointIndexUIQueryParams } from '../../../types'; -// FLAKY: https://github.com/elastic/kibana/issues/140618 -describe.skip('when rendering the endpoint list `AdminSearchBar`', () => { +describe('when rendering the endpoint list `AdminSearchBar`', () => { let render: ( urlParams?: EndpointIndexUIQueryParams ) => Promise>; @@ -85,8 +84,7 @@ describe.skip('when rendering the endpoint list `AdminSearchBar`', () => { expect(getQueryParamsFromStore().admin_query).toBe("(language:kuery,query:'host.name: foo')"); }); - // FLAKY: https://github.com/elastic/kibana/issues/132398 - it.skip.each([ + it.each([ ['nothing', ''], ['spaces', ' '], ])( diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.test.tsx b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.test.tsx index 7d8d625d97e39..2c898e825258e 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.test.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.test.tsx @@ -50,11 +50,11 @@ import { HOST_METADATA_LIST_ROUTE, metadataTransformPrefix, METADATA_UNITED_TRANSFORM, - RESPONDER_CAPABILITIES, } from '../../../../../common/endpoint/constants'; import { useUserPrivileges } from '../../../../common/components/user_privileges'; import { initialUserPrivilegesState as mockInitialUserPrivilegesState } from '../../../../common/components/user_privileges/user_privileges_context'; import { getUserPrivilegesMockDefaultValue } from '../../../../common/components/user_privileges/__mocks__'; +import { ENDPOINT_CAPABILITIES } from '../../../../../common/endpoint/service/response_actions/constants'; // not sure why this can't be imported from '../../../../common/mock/formatted_relative'; // but sure enough it needs to be inline in this one file @@ -1019,7 +1019,7 @@ describe('when on the endpoint list page', () => { ...hosts[0].metadata, Endpoint: { ...hosts[0].metadata.Endpoint, - capabilities: [...RESPONDER_CAPABILITIES], + capabilities: [...ENDPOINT_CAPABILITIES], state: { ...hosts[0].metadata.Endpoint.state, isolation: false, diff --git a/x-pack/plugins/security_solution/public/management/pages/event_filters/view/event_filters_list.test.tsx b/x-pack/plugins/security_solution/public/management/pages/event_filters/view/integration_tests/event_filters_list.test.tsx similarity index 79% rename from x-pack/plugins/security_solution/public/management/pages/event_filters/view/event_filters_list.test.tsx rename to x-pack/plugins/security_solution/public/management/pages/event_filters/view/integration_tests/event_filters_list.test.tsx index 0ef525418f385..75b35eaea2be7 100644 --- a/x-pack/plugins/security_solution/public/management/pages/event_filters/view/event_filters_list.test.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/event_filters/view/integration_tests/event_filters_list.test.tsx @@ -8,13 +8,13 @@ import { act, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import React from 'react'; -import { EVENT_FILTERS_PATH } from '../../../../../common/constants'; -import type { AppContextTestRender } from '../../../../common/mock/endpoint'; -import { createAppRootMockRenderer } from '../../../../common/mock/endpoint'; -import { EventFiltersList } from './event_filters_list'; -import { exceptionsListAllHttpMocks } from '../../../mocks/exceptions_list_http_mocks'; -import { SEARCHABLE_FIELDS } from '../constants'; -import { parseQueryFilterToKQL } from '../../../common/utils'; +import { EVENT_FILTERS_PATH } from '../../../../../../common/constants'; +import type { AppContextTestRender } from '../../../../../common/mock/endpoint'; +import { createAppRootMockRenderer } from '../../../../../common/mock/endpoint'; +import { EventFiltersList } from '../event_filters_list'; +import { exceptionsListAllHttpMocks } from '../../../../mocks/exceptions_list_http_mocks'; +import { SEARCHABLE_FIELDS } from '../../constants'; +import { parseQueryFilterToKQL } from '../../../../common/utils'; describe('When on the Event Filters list page', () => { let render: () => ReturnType; diff --git a/x-pack/plugins/security_solution/public/management/pages/index.test.tsx b/x-pack/plugins/security_solution/public/management/pages/integration_tests/index.test.tsx similarity index 68% rename from x-pack/plugins/security_solution/public/management/pages/index.test.tsx rename to x-pack/plugins/security_solution/public/management/pages/integration_tests/index.test.tsx index 1df471633c3c2..0fcc8aa1f0ca5 100644 --- a/x-pack/plugins/security_solution/public/management/pages/index.test.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/integration_tests/index.test.tsx @@ -7,14 +7,14 @@ import React from 'react'; -import { ManagementContainer } from '.'; -import '../../common/mock/match_media'; -import type { AppContextTestRender } from '../../common/mock/endpoint'; -import { createAppRootMockRenderer } from '../../common/mock/endpoint'; -import { useUserPrivileges } from '../../common/components/user_privileges'; -import { endpointPageHttpMock } from './endpoint_hosts/mocks'; +import { ManagementContainer } from '..'; +import '../../../common/mock/match_media'; +import type { AppContextTestRender } from '../../../common/mock/endpoint'; +import { createAppRootMockRenderer } from '../../../common/mock/endpoint'; +import { useUserPrivileges } from '../../../common/components/user_privileges'; +import { endpointPageHttpMock } from '../endpoint_hosts/mocks'; -jest.mock('../../common/components/user_privileges'); +jest.mock('../../../common/components/user_privileges'); describe('when in the Administration tab', () => { let render: () => ReturnType; @@ -34,8 +34,7 @@ describe('when in the Administration tab', () => { expect(await render().findByTestId('noIngestPermissions')).not.toBeNull(); }); - // FLAKY: https://github.com/elastic/kibana/issues/135166 - it.skip('should display the Management view if user has privileges', async () => { + it('should display the Management view if user has privileges', async () => { (useUserPrivileges as jest.Mock).mockReturnValue({ endpointPrivileges: { loading: false, canAccessEndpointManagement: true }, }); diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/models/advanced_policy_schema.ts b/x-pack/plugins/security_solution/public/management/pages/policy/models/advanced_policy_schema.ts index b54d50011f99b..e1885881d81a5 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/models/advanced_policy_schema.ts +++ b/x-pack/plugins/security_solution/public/management/pages/policy/models/advanced_policy_schema.ts @@ -914,7 +914,7 @@ export const AdvancedPolicySchema: AdvancedPolicySchemaType[] = [ 'xpack.securitySolution.endpoint.policy.advanced.linux.advanced.kernel.capture_mode', { defaultMessage: - 'Allows users to control whether kprobes or ebpf are used to gather data. Possible options are kprobes, ebpf, or auto. Default: kprobes', + 'Allows users to control whether kprobes or ebpf are used to gather data. Options are kprobe, ebpf, or auto. Auto uses ebpf if possible, otherwise uses kprobe. Default: auto', } ), }, diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension/endpoint_policy_create_extension.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension/endpoint_policy_create_extension.tsx index 21bba2c37922d..216875237cf43 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension/endpoint_policy_create_extension.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension/endpoint_policy_create_extension.tsx @@ -338,11 +338,22 @@ export const EndpointPolicyCreateExtension = memo {'nginx'}, postgres: {'postgres'}, + cron: {'cron'}, + recommendation: ( + + + + + + ), }} /> @@ -357,10 +368,20 @@ export const EndpointPolicyCreateExtension = memo {'ssh'}, telnet: {'telnet'}, + recommendation: ( + + + + + + ), }} /> diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_list.test.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/integration_tests/policy_list.test.tsx similarity index 88% rename from x-pack/plugins/security_solution/public/management/pages/policy/view/policy_list.test.tsx rename to x-pack/plugins/security_solution/public/management/pages/policy/view/integration_tests/policy_list.test.tsx index 5127f0605648c..17b8e81e51ef5 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_list.test.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/integration_tests/policy_list.test.tsx @@ -7,18 +7,18 @@ import React from 'react'; import { act, waitFor, fireEvent } from '@testing-library/react'; -import type { AppContextTestRender } from '../../../../common/mock/endpoint'; -import { createAppRootMockRenderer } from '../../../../common/mock/endpoint'; -import { sendGetEndpointSpecificPackagePolicies } from '../../../services/policies/policies'; -import { sendGetEndpointSpecificPackagePoliciesMock } from '../../../services/policies/test_mock_utils'; -import { PolicyList } from './policy_list'; -import { sendBulkGetAgentPolicyList } from '../../../services/policies/ingest'; -import type { GetPolicyListResponse } from '../types'; -import { getEndpointListPath, getPoliciesPath } from '../../../common/routing'; -import { APP_UI_ID } from '../../../../../common/constants'; +import type { AppContextTestRender } from '../../../../../common/mock/endpoint'; +import { createAppRootMockRenderer } from '../../../../../common/mock/endpoint'; +import { sendGetEndpointSpecificPackagePolicies } from '../../../../services/policies/policies'; +import { sendGetEndpointSpecificPackagePoliciesMock } from '../../../../services/policies/test_mock_utils'; +import { PolicyList } from '../policy_list'; +import { sendBulkGetAgentPolicyList } from '../../../../services/policies/ingest'; +import type { GetPolicyListResponse } from '../../types'; +import { getEndpointListPath, getPoliciesPath } from '../../../../common/routing'; +import { APP_UI_ID } from '../../../../../../common/constants'; -jest.mock('../../../services/policies/policies'); -jest.mock('../../../services/policies/ingest'); +jest.mock('../../../../services/policies/policies'); +jest.mock('../../../../services/policies/ingest'); const getPackagePolicies = sendGetEndpointSpecificPackagePolicies as jest.Mock; @@ -119,14 +119,12 @@ describe('When on the policy list page', () => { expect(firstUpdatedByName.textContent).toEqual(expectedAvatarName); }); - // FLAKY: https://github.com/elastic/kibana/issues/139778 - it.skip('should show the correct endpoint count', async () => { + it('should show the correct endpoint count', async () => { const endpointCount = renderResult.getAllByTestId('policyEndpointCountLink'); expect(endpointCount[0].textContent).toBe('4'); }); - // FLAKY: https://github.com/elastic/kibana/issues/140153 - it.skip('endpoint count link should navigate to the endpoint list filtered by policy', () => { + it('endpoint count link should navigate to the endpoint list filtered by policy', () => { const policyId = policies.items[0].id; const filterByPolicyQuery = `?admin_query=(language:kuery,query:'united.endpoint.Endpoint.policy.applied.id : "${policyId}"')`; const backLink = { @@ -153,8 +151,7 @@ describe('When on the policy list page', () => { render(); }); }); - // FLAKY: https://github.com/elastic/kibana/issues/139207 - describe.skip('pagination', () => { + describe('pagination', () => { beforeEach(async () => { getPackagePolicies.mockImplementation(({ page, perPage }) => { // # policies = 100 to trigger UI to show pagination @@ -190,8 +187,7 @@ describe('When on the policy list page', () => { }); }); - // FLAKY: https://github.com/elastic/kibana/issues/139196 - it.skip('should pass the correct pageSize value to the api', async () => { + it('should pass the correct pageSize value to the api', async () => { await waitFor(() => { expect(renderResult.getByTestId('tablePaginationPopoverButton')).toBeTruthy(); }); @@ -212,8 +208,7 @@ describe('When on the policy list page', () => { }); }); - // FLAKY: https://github.com/elastic/kibana/issues/139207 - it.skip('should call the api with the initial pagination values taken from the url', async () => { + it('should call the api with the initial pagination values taken from the url', async () => { act(() => { history.push('/administration/policies?page=3&pageSize=50'); }); diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_forms/events/linux.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_forms/events/linux.tsx index 984bc53a014e3..f32f83cdf70cb 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_forms/events/linux.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_forms/events/linux.tsx @@ -81,7 +81,7 @@ const SUPPLEMENTAL_OPTIONS: ReadonlyArray { const { services: { ml, http }, @@ -86,7 +88,7 @@ export const EntityAnalyticsAnomalies = () => { }, [getSecuritySolutionLinkProps]); return ( - + eui.euiColorDanger}; @@ -74,10 +73,6 @@ export const EntityAnalyticsHeader = () => { const getSecuritySolutionLinkProps = useGetSecuritySolutionLinkProps(); const isPlatinumOrTrialLicense = useMlCapabilities().isPlatinumOrTrialLicense; - const { - services: { ml, http }, - } = useKibana(); - const [goToHostRiskTabFilteredByCritical, hostRiskTabUrl] = useMemo(() => { const { onClick, href } = getSecuritySolutionLinkProps({ deepLinkId: SecurityPageName.hosts, @@ -151,9 +146,14 @@ export const EntityAnalyticsHeader = () => { [data, areJobsEnabled] ); - const jobsUrl = useMlHref(ml, http.basePath.get(), { - page: ML_PAGES.ANOMALY_DETECTION_JOBS_MANAGE, - }); + const scrollToAnomalies = useCallback(() => { + const element = document.querySelector( + `[data-test-subj="${ENTITY_ANALYTICS_ANOMALIES_PANEL}"]` + ); + if (element) { + element.scrollIntoView({ behavior: 'smooth' }); + } + }, []); return ( @@ -211,9 +211,9 @@ export const EntityAnalyticsHeader = () => { - + {i18n.ANOMALIES} - + diff --git a/x-pack/plugins/security_solution/public/users/components/kpi_users/index.tsx b/x-pack/plugins/security_solution/public/users/components/kpi_users/index.tsx index b8baea1c42052..b7052bef14ba2 100644 --- a/x-pack/plugins/security_solution/public/users/components/kpi_users/index.tsx +++ b/x-pack/plugins/security_solution/public/users/components/kpi_users/index.tsx @@ -6,83 +6,39 @@ */ import React from 'react'; -import { EuiFlexItem, EuiFlexGroup, EuiSpacer } from '@elastic/eui'; - +import { EuiFlexItem, EuiFlexGroup } from '@elastic/eui'; import type { UsersKpiProps } from './types'; - import { UsersKpiAuthentications } from './authentications'; import { TotalUsersKpi } from './total_users'; -import { CallOutSwitcher } from '../../../common/components/callouts'; -import * as i18n from './translations'; -import { RiskScoreDocLink } from '../../../risk_score/components/risk_score_onboarding/risk_score_doc_link'; -import { getUserRiskIndex, RiskScoreEntity } from '../../../../common/search_strategy'; -import { useSpaceId } from '../../../common/hooks/use_space_id'; -import { useRiskScoreFeatureStatus } from '../../../risk_score/containers/feature_status'; export const UsersKpiComponent = React.memo( - ({ filterQuery, from, indexNames, to, setQuery, skip, updateDateRange }) => { - const spaceId = useSpaceId(); - const defaultIndex = spaceId ? getUserRiskIndex(spaceId) : undefined; - const { isEnabled, isLicenseValid, isLoading } = useRiskScoreFeatureStatus( - RiskScoreEntity.user, - defaultIndex - ); - - return ( - <> - {isLicenseValid && !isEnabled && !isLoading && ( - <> - - {i18n.LEARN_MORE}{' '} - - - - ), - }} - /> - - - )} - - - - - - - - - - - ); - } + ({ filterQuery, from, indexNames, to, setQuery, skip, updateDateRange }) => ( + + + + + + + + + + ) ); UsersKpiComponent.displayName = 'UsersKpiComponent'; diff --git a/x-pack/plugins/security_solution/public/users/components/kpi_users/translations.ts b/x-pack/plugins/security_solution/public/users/components/kpi_users/translations.ts deleted file mode 100644 index 8315b6dc21c19..0000000000000 --- a/x-pack/plugins/security_solution/public/users/components/kpi_users/translations.ts +++ /dev/null @@ -1,22 +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 { i18n } from '@kbn/i18n'; - -export const ENABLE_USER_RISK_TEXT = i18n.translate( - 'xpack.securitySolution.kpiUser.enableUserRiskText', - { - defaultMessage: 'Enable user risk module to see more data', - } -); - -export const LEARN_MORE = i18n.translate('xpack.securitySolution.kpiUser.learnMore', { - defaultMessage: 'Learn more about', -}); - -export const USER_RISK_DATA = i18n.translate('xpack.securitySolution.kpiUser.userRiskData', { - defaultMessage: 'user risk data', -}); diff --git a/x-pack/plugins/security_solution/server/endpoint/endpoint_app_context_services.ts b/x-pack/plugins/security_solution/server/endpoint/endpoint_app_context_services.ts index 06d54a4353958..6b6baf163dc90 100644 --- a/x-pack/plugins/security_solution/server/endpoint/endpoint_app_context_services.ts +++ b/x-pack/plugins/security_solution/server/endpoint/endpoint_app_context_services.ts @@ -40,7 +40,11 @@ import type { } from './services/fleet/endpoint_fleet_services_factory'; import { registerListsPluginEndpointExtensionPoints } from '../lists_integration'; import type { EndpointAuthz } from '../../common/endpoint/types/authz'; -import { calculateEndpointAuthz } from '../../common/endpoint/service/authz'; +import { + calculateEndpointAuthz, + calculatePermissionsFromPrivileges, + defaultEndpointPermissions, +} from '../../common/endpoint/service/authz'; import type { FeatureUsageService } from './services/feature_usage/service'; import type { ExperimentalFeatures } from '../../common/experimental_features'; @@ -162,14 +166,27 @@ export class EndpointAppContextService { public async getEndpointAuthz(request: KibanaRequest): Promise { const fleetAuthz = await this.getFleetAuthzService().fromRequest(request); - const userRoles = this.startDependencies?.security.authc.getCurrentUser(request)?.roles ?? []; + const userRoles = this.security?.authc.getCurrentUser(request)?.roles ?? []; const isEndpointRbacEnabled = this.experimentalFeatures.endpointRbacEnabled; + let endpointPermissions = defaultEndpointPermissions(); + if (this.security) { + const checkPrivileges = this.security.authz.checkPrivilegesDynamicallyWithRequest(request); + const { privileges } = await checkPrivileges({ + kibana: [ + this.security.authz.actions.ui.get('siem', 'crud'), + this.security.authz.actions.ui.get('siem', 'show'), + ], + }); + endpointPermissions = calculatePermissionsFromPrivileges(privileges.kibana); + } + return calculateEndpointAuthz( this.getLicenseService(), fleetAuthz, userRoles, - isEndpointRbacEnabled + isEndpointRbacEnabled, + endpointPermissions ); } diff --git a/x-pack/plugins/security_solution/server/endpoint/lib/metadata/check_metadata_transforms_task.test.ts b/x-pack/plugins/security_solution/server/endpoint/lib/metadata/check_metadata_transforms_task.test.ts index 84d124a398a93..dabd2feed57e2 100644 --- a/x-pack/plugins/security_solution/server/endpoint/lib/metadata/check_metadata_transforms_task.test.ts +++ b/x-pack/plugins/security_solution/server/endpoint/lib/metadata/check_metadata_transforms_task.test.ts @@ -277,7 +277,7 @@ describe('check metadata transforms task', () => { }); describe('transforms reinstall', () => { - let getRegistryPackageSpy: jest.SpyInstance; + let getPackageSpy: jest.SpyInstance; let reinstallEsAssetsSpy: jest.SpyInstance; let mockPackageClient: jest.Mocked; @@ -291,7 +291,7 @@ describe('check metadata transforms task', () => { mockPackageClient = mockEndpointAppContext.service.getInternalFleetServices() .packages as jest.Mocked; - getRegistryPackageSpy = jest.spyOn(mockPackageClient, 'getRegistryPackage'); + getPackageSpy = jest.spyOn(mockPackageClient, 'getPackage'); reinstallEsAssetsSpy = jest.spyOn(mockPackageClient, 'reinstallEsAssets'); const transformStatsResponseMock = { @@ -313,7 +313,7 @@ describe('check metadata transforms task', () => { packageInfo: { name: 'package name' }, paths: ['some/test/transform/path'], }; - getRegistryPackageSpy.mockResolvedValue(expectedArgs); + getPackageSpy.mockResolvedValue(expectedArgs); reinstallEsAssetsSpy.mockResolvedValue([{}]); await runTask(); @@ -338,7 +338,7 @@ describe('check metadata transforms task', () => { }); it('should return correct runAt', async () => { - getRegistryPackageSpy.mockResolvedValue({ + getPackageSpy.mockResolvedValue({ packageInfo: { name: 'package name' }, paths: ['some/test/transform/path'], }); diff --git a/x-pack/plugins/security_solution/server/endpoint/lib/metadata/check_metadata_transforms_task.ts b/x-pack/plugins/security_solution/server/endpoint/lib/metadata/check_metadata_transforms_task.ts index 64d37e07342c4..1c2d51510c3f6 100644 --- a/x-pack/plugins/security_solution/server/endpoint/lib/metadata/check_metadata_transforms_task.ts +++ b/x-pack/plugins/security_solution/server/endpoint/lib/metadata/check_metadata_transforms_task.ts @@ -256,7 +256,7 @@ export class CheckMetadataTransformsTask { const packageClient = this.endpointAppContext.service.getInternalFleetServices().packages; - const { packageInfo, paths } = await packageClient.getRegistryPackage( + const { packageInfo, paths } = await packageClient.getPackage( FLEET_ENDPOINT_PACKAGE, pkgVersion ); diff --git a/x-pack/plugins/security_solution/server/endpoint/mocks.ts b/x-pack/plugins/security_solution/server/endpoint/mocks.ts index 50785f9c29bf9..7639e73b0a36d 100644 --- a/x-pack/plugins/security_solution/server/endpoint/mocks.ts +++ b/x-pack/plugins/security_solution/server/endpoint/mocks.ts @@ -135,6 +135,10 @@ export const createMockEndpointAppContextServiceStartContract = securityMock.createMockAuthenticatedUser({ roles: ['superuser'] }) ); + security.authz.checkPrivilegesDynamicallyWithRequest.mockReturnValue( + jest.fn(() => ({ privileges: { kibana: [] } })) + ); + return { agentService, agentPolicyService, diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/actions/details.ts b/x-pack/plugins/security_solution/server/endpoint/routes/actions/details.ts index 9f087cc65b358..4a0c30c6d990c 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/actions/details.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/actions/details.ts @@ -35,7 +35,7 @@ export const registerActionDetailsRoutes = ( options: { authRequired: true, tags: ['access:securitySolution'] }, }, withEndpointAuthz( - { all: ['canAccessEndpointManagement'] }, + { all: ['canReadSecuritySolution'] }, endpointContext.logFactory.get('hostIsolationDetails'), getActionDetailsRequestHandler(endpointContext) ) diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/actions/list.test.ts b/x-pack/plugins/security_solution/server/endpoint/routes/actions/list.test.ts index 70c268d430382..c2a460fa88b79 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/actions/list.test.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/actions/list.test.ts @@ -117,14 +117,14 @@ describe('Action List Route', () => { }); describe('User auth level', () => { - it('allows user with canAccessEndpointManagement access to allow requests to API', async () => { + it('allows user with canReadSecuritySolution access to allow requests to API', async () => { await callApiRoute(ENDPOINTS_ACTION_LIST_ROUTE, {}); expect(mockResponse.ok).toBeCalled(); }); - it('does not allow user with canAccessEndpointManagement access to allow requests to API', async () => { + it('does not allow user without canReadSecuritySolution access to allow requests to API', async () => { await callApiRoute(ENDPOINTS_ACTION_LIST_ROUTE, { - authz: { canAccessEndpointManagement: false }, + authz: { canReadSecuritySolution: false }, }); expect(mockResponse.forbidden).toBeCalled(); }); diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/actions/list.ts b/x-pack/plugins/security_solution/server/endpoint/routes/actions/list.ts index 520fc19a85b9c..a8b3ff5d70749 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/actions/list.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/actions/list.ts @@ -33,7 +33,7 @@ export function registerActionListRoutes( options: { authRequired: true, tags: ['access:securitySolution'] }, }, withEndpointAuthz( - { all: ['canAccessEndpointManagement'] }, + { all: ['canReadSecuritySolution'] }, endpointContext.logFactory.get('endpointActionList'), actionListHandler(endpointContext) ) diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/actions/list_handler.ts b/x-pack/plugins/security_solution/server/endpoint/routes/actions/list_handler.ts index ea1409ce323f9..9566d84898b71 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/actions/list_handler.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/actions/list_handler.ts @@ -19,7 +19,7 @@ import type { SecuritySolutionRequestHandlerContext } from '../../../types'; import type { EndpointAppContext } from '../../types'; import { errorHandler } from '../error_handler'; import type { - ResponseActions, + ResponseActionsApiCommandNames, ResponseActionStatus, } from '../../../../common/endpoint/service/response_actions/constants'; import { doesLogsEndpointActionsIndexExist } from '../../utils'; @@ -28,8 +28,8 @@ const formatStringIds = (value: string | string[] | undefined): undefined | stri typeof value === 'string' ? [value] : value; const formatCommandValues = ( - value: ResponseActions | ResponseActions[] | undefined -): undefined | ResponseActions[] => (typeof value === 'string' ? [value] : value); + value: ResponseActionsApiCommandNames | ResponseActionsApiCommandNames[] | undefined +): undefined | ResponseActionsApiCommandNames[] => (typeof value === 'string' ? [value] : value); const formatStatusValues = ( value: ResponseActionStatus | ResponseActionStatus[] diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/actions/response_actions.test.ts b/x-pack/plugins/security_solution/server/endpoint/routes/actions/response_actions.test.ts index a0acd5927f5a8..8624bc375cd9f 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/actions/response_actions.test.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/actions/response_actions.test.ts @@ -43,6 +43,7 @@ import { GET_PROCESSES_ROUTE, ISOLATE_HOST_ROUTE, UNISOLATE_HOST_ROUTE, + GET_FILE_ROUTE, } from '../../../../common/endpoint/constants'; import type { ActionDetails, @@ -196,7 +197,7 @@ describe('Response actions', () => { ctx.core.elasticsearch.client.asInternalUser.index.mockResponseImplementation( () => withIdxResp ); - ctx.core.elasticsearch.client.asCurrentUser.search.mockResponseImplementation(() => { + ctx.core.elasticsearch.client.asInternalUser.search.mockResponseImplementation(() => { return { body: legacyMetadataSearchResponseMock(searchResponse), }; @@ -412,6 +413,17 @@ describe('Response actions', () => { expect(actionDoc.data.command).toEqual('running-processes'); }); + it('sends the get-file command payload from the get file route', async () => { + const ctx = await callRoute(GET_FILE_ROUTE, { + body: { endpoint_ids: ['XYZ'], parameters: { path: '/one/two/three' } }, + }); + const actionDoc: EndpointAction = ( + ctx.core.elasticsearch.client.asInternalUser.index.mock + .calls[0][0] as estypes.IndexRequest + ).body!; + expect(actionDoc.data.command).toEqual('get-file'); + }); + describe('With endpoint data streams', () => { it('handles unisolation', async () => { const ctx = await callRoute( @@ -553,6 +565,33 @@ describe('Response actions', () => { expect(responseBody.action).toBeUndefined(); }); + it('handles get-file', async () => { + const ctx = await callRoute( + GET_FILE_ROUTE, + { + body: { endpoint_ids: ['XYZ'], parameters: { path: '/one/two/three' } }, + }, + { endpointDsExists: true } + ); + const indexDoc = ctx.core.elasticsearch.client.asInternalUser.index; + const actionDocs: [ + { index: string; body?: LogsEndpointAction }, + { index: string; body?: EndpointAction } + ] = [ + indexDoc.mock.calls[0][0] as estypes.IndexRequest, + indexDoc.mock.calls[1][0] as estypes.IndexRequest, + ]; + + expect(actionDocs[0].index).toEqual(ENDPOINT_ACTIONS_INDEX); + expect(actionDocs[1].index).toEqual(AGENT_ACTIONS_INDEX); + expect(actionDocs[0].body!.EndpointActions.data.command).toEqual('get-file'); + expect(actionDocs[1].body!.data.command).toEqual('get-file'); + + expect(mockResponse.ok).toBeCalled(); + const responseBody = mockResponse.ok.mock.calls[0][0]?.body as ResponseActionApiResponse; + expect(responseBody.action).toBeUndefined(); + }); + it('handles errors', async () => { const ErrMessage = 'Uh oh!'; await callRoute( diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/actions/response_actions.ts b/x-pack/plugins/security_solution/server/endpoint/routes/actions/response_actions.ts index 7ff7a8253ba3d..1ddf38e390d10 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/actions/response_actions.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/actions/response_actions.ts @@ -18,6 +18,7 @@ import type { ResponseActionBodySchema } from '../../../../common/endpoint/schem import { NoParametersRequestSchema, KillOrSuspendProcessRequestSchema, + EndpointActionGetFileSchema, } from '../../../../common/endpoint/schema/actions'; import { APP_ID } from '../../../../common/constants'; import { @@ -32,6 +33,7 @@ import { ISOLATE_HOST_ROUTE, UNISOLATE_HOST_ROUTE, ENDPOINT_ACTIONS_INDEX, + GET_FILE_ROUTE, } from '../../../../common/endpoint/constants'; import type { EndpointAction, @@ -42,7 +44,7 @@ import type { LogsEndpointActionResponse, ResponseActionParametersWithPidOrEntityId, } from '../../../../common/endpoint/types'; -import type { ResponseActions } from '../../../../common/endpoint/service/response_actions/constants'; +import type { ResponseActionsApiCommandNames } from '../../../../common/endpoint/service/response_actions/constants'; import type { SecuritySolutionPluginRouter, SecuritySolutionRequestHandlerContext, @@ -157,21 +159,35 @@ export function registerResponseActionRoutes( responseActionRequestHandler(endpointContext, 'running-processes') ) ); + + router.post( + { + path: GET_FILE_ROUTE, + validate: EndpointActionGetFileSchema, + options: { authRequired: true, tags: ['access:securitySolution'] }, + }, + withEndpointAuthz( + { all: ['canWriteFileOperations'] }, + logger, + responseActionRequestHandler(endpointContext, 'get-file') + ) + ); } -const commandToFeatureKeyMap = new Map([ +const commandToFeatureKeyMap = new Map([ ['isolate', 'HOST_ISOLATION'], ['unisolate', 'HOST_ISOLATION'], ['kill-process', 'KILL_PROCESS'], ['suspend-process', 'SUSPEND_PROCESS'], ['running-processes', 'RUNNING_PROCESSES'], + ['get-file', 'GET_FILE'], ]); -const returnActionIdCommands: ResponseActions[] = ['isolate', 'unisolate']; +const returnActionIdCommands: ResponseActionsApiCommandNames[] = ['isolate', 'unisolate']; function responseActionRequestHandler( endpointContext: EndpointAppContext, - command: ResponseActions + command: ResponseActionsApiCommandNames ): RequestHandler< unknown, unknown, @@ -233,8 +249,7 @@ function responseActionRequestHandler, } as Omit, user: { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - id: user!.username, + id: user ? user.username : 'unknown', }, }; diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/actions/status.ts b/x-pack/plugins/security_solution/server/endpoint/routes/actions/status.ts index 5f648bf44704d..2660fcd37103e 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/actions/status.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/actions/status.ts @@ -32,7 +32,7 @@ export function registerActionStatusRoutes( options: { authRequired: true, tags: ['access:securitySolution'] }, }, withEndpointAuthz( - { all: ['canAccessEndpointManagement'] }, + { all: ['canReadSecuritySolution'] }, endpointContext.logFactory.get('hostIsolationStatus'), actionStatusRequestHandler(endpointContext) ) diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/handlers.ts b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/handlers.ts index 0cc0d4bb50e55..b9a187b592dbc 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/handlers.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/handlers.ts @@ -63,7 +63,7 @@ export function getMetadataListRequestHandler( > { return async (context, request, response) => { const endpointMetadataService = endpointAppContext.service.getEndpointMetadataService(); - const fleetServices = endpointAppContext.service.getScopedFleetServices(request); + const fleetServices = endpointAppContext.service.getInternalFleetServices(); const esClient = (await context.core).elasticsearch.client.asInternalUser; let doesUnitedIndexExist = false; @@ -142,7 +142,7 @@ export const getMetadataRequestHandler = function ( return response.ok({ body: await endpointMetadataService.getEnrichedHostMetadata( esClient.asInternalUser, - endpointAppContext.service.getScopedFleetServices(request), + endpointAppContext.service.getInternalFleetServices(), request.params.id ), }); diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/index.ts b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/index.ts index eba1c27d91f8d..d959add145663 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/index.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/index.ts @@ -57,7 +57,7 @@ export function registerEndpointRoutes( options: { authRequired: true, tags: ['access:securitySolution'] }, }, withEndpointAuthz( - { all: ['canAccessEndpointManagement'] }, + { all: ['canReadSecuritySolution'] }, logger, getMetadataListRequestHandler(endpointAppContext, logger) ) @@ -67,10 +67,10 @@ export function registerEndpointRoutes( { path: HOST_METADATA_GET_ROUTE, validate: GetMetadataRequestSchema, - options: { authRequired: true, tags: ['access:securitySolution'] }, + options: { authRequired: true }, }, withEndpointAuthz( - { all: ['canAccessEndpointManagement'] }, + { any: ['canReadSecuritySolution', 'canAccessFleet'] }, logger, getMetadataRequestHandler(endpointAppContext, logger) ) @@ -83,7 +83,7 @@ export function registerEndpointRoutes( options: { authRequired: true, tags: ['access:securitySolution'] }, }, withEndpointAuthz( - { all: ['canAccessEndpointManagement'] }, + { all: ['canReadSecuritySolution'] }, logger, getMetadataTransformStatsHandler(logger) ) diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/metadata.test.ts b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/metadata.test.ts index d03117225279a..86b57fcb85022 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/metadata.test.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/metadata.test.ts @@ -152,7 +152,7 @@ describe('test endpoint routes', () => { endpointAppContextService.start({ ...startContract, packageService: mockPackageService }); mockAgentService = startContract.agentService!; mockAgentClient = createMockAgentClient(); - mockAgentService.asScoped = () => mockAgentClient; + mockAgentService.asInternalUser = mockAgentClient; mockAgentPolicyService = startContract.agentPolicyService!; registerEndpointRoutes(routerMock, { @@ -629,6 +629,25 @@ describe('test endpoint routes', () => { expect(endpointResultList.pageSize).toEqual(10); }); }); + + it('should get forbidden if no security solution access', async () => { + const mockRequest = httpServerMock.createKibanaRequest(); + + [routeConfig, routeHandler] = routerMock.get.mock.calls.find(([{ path }]) => + path.startsWith(HOST_METADATA_LIST_ROUTE) + )!; + + const contextOverrides = { + endpointAuthz: getEndpointAuthzInitialStateMock({ canReadSecuritySolution: false }), + }; + await routeHandler( + createRouteHandlerContext(mockScopedClient, mockSavedObjectClient, contextOverrides), + mockRequest, + mockResponse + ); + + expect(mockResponse.forbidden).toBeCalled(); + }); }); describe('GET endpoint details route', () => { @@ -655,7 +674,6 @@ describe('test endpoint routes', () => { expect(esSearchMock).toHaveBeenCalledTimes(1); expect(routeConfig.options).toEqual({ authRequired: true, - tags: ['access:securitySolution'], }); expect(mockResponse.notFound).toBeCalled(); const message = mockResponse.notFound.mock.calls[0][0]?.body; @@ -687,7 +705,6 @@ describe('test endpoint routes', () => { expect(esSearchMock).toHaveBeenCalledTimes(1); expect(routeConfig.options).toEqual({ authRequired: true, - tags: ['access:securitySolution'], }); expect(mockResponse.ok).toBeCalled(); const result = mockResponse.ok.mock.calls[0][0]?.body as HostInfo; @@ -722,7 +739,6 @@ describe('test endpoint routes', () => { expect(esSearchMock).toHaveBeenCalledTimes(1); expect(routeConfig.options).toEqual({ authRequired: true, - tags: ['access:securitySolution'], }); expect(mockResponse.ok).toBeCalled(); const result = mockResponse.ok.mock.calls[0][0]?.body as HostInfo; @@ -759,7 +775,6 @@ describe('test endpoint routes', () => { expect(esSearchMock).toHaveBeenCalledTimes(1); expect(routeConfig.options).toEqual({ authRequired: true, - tags: ['access:securitySolution'], }); expect(mockResponse.ok).toBeCalled(); const result = mockResponse.ok.mock.calls[0][0]?.body as HostInfo; @@ -794,10 +809,62 @@ describe('test endpoint routes', () => { expect(esSearchMock).toHaveBeenCalledTimes(1); expect(mockResponse.badRequest).toBeCalled(); }); + + it('should work if no security solution access but has fleet access', async () => { + const response = legacyMetadataSearchResponseMock( + new EndpointDocGenerator().generateHostMetadata() + ); + const mockRequest = httpServerMock.createKibanaRequest({ + params: { id: response.hits.hits[0]._id }, + }); + const esSearchMock = mockScopedClient.asInternalUser.search; + + mockAgentClient.getAgent.mockResolvedValue(agentGenerator.generate({ status: 'online' })); + esSearchMock.mockResponseOnce(response); + + [routeConfig, routeHandler] = routerMock.get.mock.calls.find(([{ path }]) => + path.startsWith(HOST_METADATA_GET_ROUTE) + )!; + + const contextOverrides = { + endpointAuthz: getEndpointAuthzInitialStateMock({ + canReadSecuritySolution: false, + }), + }; + await routeHandler( + createRouteHandlerContext(mockScopedClient, mockSavedObjectClient, contextOverrides), + mockRequest, + mockResponse + ); + + expect(mockResponse.ok).toBeCalled(); + }); + + it('should get forbidden if no security solution or fleet access', async () => { + const mockRequest = httpServerMock.createKibanaRequest(); + + [routeConfig, routeHandler] = routerMock.get.mock.calls.find(([{ path }]) => + path.startsWith(HOST_METADATA_GET_ROUTE) + )!; + + const contextOverrides = { + endpointAuthz: getEndpointAuthzInitialStateMock({ + canAccessFleet: false, + canReadSecuritySolution: false, + }), + }; + await routeHandler( + createRouteHandlerContext(mockScopedClient, mockSavedObjectClient, contextOverrides), + mockRequest, + mockResponse + ); + + expect(mockResponse.forbidden).toBeCalled(); + }); }); describe('GET metadata transform stats route', () => { - it('should get forbidden if no fleet access', async () => { + it('should get forbidden if no security solution access', async () => { const mockRequest = httpServerMock.createKibanaRequest(); [routeConfig, routeHandler] = routerMock.get.mock.calls.find(([{ path }]) => @@ -805,7 +872,7 @@ describe('test endpoint routes', () => { )!; const contextOverrides = { - endpointAuthz: getEndpointAuthzInitialStateMock({ canAccessEndpointManagement: false }), + endpointAuthz: getEndpointAuthzInitialStateMock({ canReadSecuritySolution: false }), }; await routeHandler( createRouteHandlerContext(mockScopedClient, mockSavedObjectClient, contextOverrides), diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/policy/handlers.test.ts b/x-pack/plugins/security_solution/server/endpoint/routes/policy/handlers.test.ts index a9a7c7c4837e3..e92f316f7c125 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/policy/handlers.test.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/policy/handlers.test.ts @@ -55,7 +55,7 @@ describe('test policy response handler', () => { const response = createSearchResponse(new EndpointDocGenerator().generatePolicyResponse()); const hostPolicyResponseHandler = getHostPolicyResponseHandler(); - mockScopedClient.asCurrentUser.search.mockResponseOnce(response); + mockScopedClient.asInternalUser.search.mockResponseOnce(response); const mockRequest = httpServerMock.createKibanaRequest({ params: { agentId: 'id' }, }); @@ -78,7 +78,7 @@ describe('test policy response handler', () => { it('should return not found when there is no response policy for host', async () => { const hostPolicyResponseHandler = getHostPolicyResponseHandler(); - mockScopedClient.asCurrentUser.search.mockResponseOnce(createSearchResponse()); + mockScopedClient.asInternalUser.search.mockResponseOnce(createSearchResponse()); const mockRequest = httpServerMock.createKibanaRequest({ params: { agentId: 'id' }, diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/policy/index.ts b/x-pack/plugins/security_solution/server/endpoint/routes/policy/index.ts index 18eb1c961ee76..568a61d2691d8 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/policy/index.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/policy/index.ts @@ -30,7 +30,7 @@ export function registerPolicyRoutes(router: IRouter, endpointAppContext: Endpoi options: { authRequired: true }, }, withEndpointAuthz( - { all: ['canAccessEndpointManagement'] }, + { any: ['canReadSecuritySolution', 'canAccessFleet'] }, logger, getHostPolicyResponseHandler() ) diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/policy/service.ts b/x-pack/plugins/security_solution/server/endpoint/routes/policy/service.ts index c0639bcbcb848..1afafa2b61245 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/policy/service.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/policy/service.ts @@ -51,7 +51,7 @@ export async function getPolicyResponseByAgentId( dataClient: IScopedClusterClient ): Promise { const query = getESQueryPolicyResponseByAgentID(agentID, index); - const response = await dataClient.asCurrentUser.search(query); + const response = await dataClient.asInternalUser.search(query); if (response.hits.hits.length > 0 && response.hits.hits[0]._source != null) { return { diff --git a/x-pack/plugins/security_solution/server/endpoint/services/actions/utils.ts b/x-pack/plugins/security_solution/server/endpoint/services/actions/utils.ts index 036e9f0cc1edd..17f8be8c8811f 100644 --- a/x-pack/plugins/security_solution/server/endpoint/services/actions/utils.ts +++ b/x-pack/plugins/security_solution/server/endpoint/services/actions/utils.ts @@ -7,7 +7,7 @@ import type { ElasticsearchClient } from '@kbn/core/server'; import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; -import type { ResponseActions } from '../../../../common/endpoint/service/response_actions/constants'; +import type { ResponseActionsApiCommandNames } from '../../../../common/endpoint/service/response_actions/constants'; import { ENDPOINT_ACTIONS_DS, ENDPOINT_ACTION_RESPONSES_DS, @@ -55,7 +55,7 @@ interface NormalizedActionRequest { agents: string[]; createdBy: string; createdAt: string; - command: ResponseActions; + command: ResponseActionsApiCommandNames; comment?: string; parameters?: EndpointActionDataParameterTypes; } diff --git a/x-pack/plugins/security_solution/server/endpoint/services/feature_usage/service.ts b/x-pack/plugins/security_solution/server/endpoint/services/feature_usage/service.ts index 46c75cd6f73eb..d83066414add2 100644 --- a/x-pack/plugins/security_solution/server/endpoint/services/feature_usage/service.ts +++ b/x-pack/plugins/security_solution/server/endpoint/services/feature_usage/service.ts @@ -21,6 +21,7 @@ const FEATURES = { KILL_PROCESS: 'Kill process', SUSPEND_PROCESS: 'Suspend process', RUNNING_PROCESSES: 'Get running processes', + GET_FILE: 'Get file', ALERTS_BY_PROCESS_ANCESTRY: 'Get related alerts by process ancestry', } as const; diff --git a/x-pack/plugins/security_solution/server/endpoint/services/metadata/metadata.ts b/x-pack/plugins/security_solution/server/endpoint/services/metadata/metadata.ts index 1f68552e999ae..529903d97403e 100644 --- a/x-pack/plugins/security_solution/server/endpoint/services/metadata/metadata.ts +++ b/x-pack/plugins/security_solution/server/endpoint/services/metadata/metadata.ts @@ -18,7 +18,7 @@ export async function getMetadataForEndpoints( requestHandlerContext: SecuritySolutionRequestHandlerContext ): Promise { const query = getESQueryHostMetadataByIDs(endpointIDs); - const esClient = (await requestHandlerContext.core).elasticsearch.client.asCurrentUser; + const esClient = (await requestHandlerContext.core).elasticsearch.client.asInternalUser; const { body } = await esClient.search(query as estypes.SearchRequest, { meta: true, }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/fleet/get_installed_integrations/get_installed_integrations_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/fleet/get_installed_integrations/get_installed_integrations_route.ts index 50c89f989f990..9e9091e1b578c 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/fleet/get_installed_integrations/get_installed_integrations_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/fleet/get_installed_integrations/get_installed_integrations_route.ts @@ -50,7 +50,7 @@ export const getInstalledIntegrationsRoute = ( concurrency: MAX_CONCURRENT_REQUESTS_TO_PACKAGE_REGISTRY, items: set.getPackages(), executor: async (packageInfo) => { - const registryPackage = await fleet.packages.getRegistryPackage( + const registryPackage = await fleet.packages.getPackage( packageInfo.package_name, packageInfo.package_version ); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/fleet/get_installed_integrations/installed_integration_set.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/fleet/get_installed_integrations/installed_integration_set.ts index d55b8fdce3a3f..e124e0322192c 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/fleet/get_installed_integrations/installed_integration_set.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/fleet/get_installed_integrations/installed_integration_set.ts @@ -6,7 +6,7 @@ */ import { capitalize, flatten } from 'lodash'; -import type { PackagePolicy, RegistryPackage } from '@kbn/fleet-plugin/common'; +import type { PackagePolicy, ArchivePackage } from '@kbn/fleet-plugin/common'; import type { InstalledIntegration, InstalledIntegrationArray, @@ -18,7 +18,7 @@ import type { export interface IInstalledIntegrationSet { addPackagePolicy(policy: PackagePolicy): void; - addRegistryPackage(registryPackage: RegistryPackage): void; + addRegistryPackage(registryPackage: ArchivePackage): void; getPackages(): InstalledPackageArray; getIntegrations(): InstalledIntegrationArray; @@ -56,7 +56,7 @@ export const createInstalledIntegrationSet = (): IInstalledIntegrationSet => { } }; - const addRegistryPackage = (registryPackage: RegistryPackage): void => { + const addRegistryPackage = (registryPackage: ArchivePackage): void => { const policyTemplates = registryPackage.policy_templates ?? []; const packageKey = `${registryPackage.name}:${registryPackage.version}`; const existingPackageInfo = packageMap.get(packageKey); diff --git a/x-pack/plugins/security_solution/server/lists_integration/endpoint/validators/base_validator.ts b/x-pack/plugins/security_solution/server/lists_integration/endpoint/validators/base_validator.ts index 872d8da7cdb3d..ecc2ac7893336 100644 --- a/x-pack/plugins/security_solution/server/lists_integration/endpoint/validators/base_validator.ts +++ b/x-pack/plugins/security_solution/server/lists_integration/endpoint/validators/base_validator.ts @@ -10,6 +10,7 @@ import { schema } from '@kbn/config-schema'; import { isEqual } from 'lodash/fp'; import type { ExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types'; import { OperatingSystem } from '@kbn/securitysolution-utils'; +import type { EndpointAuthz } from '../../../../common/endpoint/types/authz'; import type { EndpointAppContextService } from '../../../endpoint/endpoint_app_context_services'; import type { ExceptionItemLikeOptions } from '../types'; import { getEndpointAuthzInitialState } from '../../../../common/endpoint/service/authz'; @@ -73,6 +74,12 @@ export class BaseValidator { } } + protected async validateHasPrivilege(privilege: keyof EndpointAuthz): Promise { + if (!(await this.endpointAuthzPromise)[privilege]) { + throw new EndpointArtifactExceptionValidationError('Endpoint authorization failure', 403); + } + } + protected isItemByPolicy(item: ExceptionItemLikeOptions): boolean { return isArtifactByPolicy(item); } diff --git a/x-pack/plugins/security_solution/server/lists_integration/endpoint/validators/trusted_app_validator.ts b/x-pack/plugins/security_solution/server/lists_integration/endpoint/validators/trusted_app_validator.ts index ebc3c05460923..86b11249af9bd 100644 --- a/x-pack/plugins/security_solution/server/lists_integration/endpoint/validators/trusted_app_validator.ts +++ b/x-pack/plugins/security_solution/server/lists_integration/endpoint/validators/trusted_app_validator.ts @@ -175,10 +175,18 @@ export class TrustedAppValidator extends BaseValidator { return item.listId === ENDPOINT_TRUSTED_APPS_LIST_ID; } + protected async validateHasWritePrivilege(): Promise { + return super.validateHasPrivilege('canWriteTrustedApplications'); + } + + protected async validateHasReadPrivilege(): Promise { + return super.validateHasPrivilege('canReadTrustedApplications'); + } + async validatePreCreateItem( item: CreateExceptionListItemOptions ): Promise { - await this.validateCanManageEndpointArtifacts(); + await this.validateHasWritePrivilege(); await this.validateTrustedAppData(item); await this.validateCanCreateByPolicyArtifacts(item); await this.validateByPolicyItem(item); @@ -187,27 +195,27 @@ export class TrustedAppValidator extends BaseValidator { } async validatePreDeleteItem(): Promise { - await this.validateCanManageEndpointArtifacts(); + await this.validateHasWritePrivilege(); } async validatePreGetOneItem(): Promise { - await this.validateCanManageEndpointArtifacts(); + await this.validateHasReadPrivilege(); } async validatePreMultiListFind(): Promise { - await this.validateCanManageEndpointArtifacts(); + await this.validateHasReadPrivilege(); } async validatePreExport(): Promise { - await this.validateCanManageEndpointArtifacts(); + await this.validateHasWritePrivilege(); } async validatePreSingleListFind(): Promise { - await this.validateCanManageEndpointArtifacts(); + await this.validateHasReadPrivilege(); } async validatePreGetListSummary(): Promise { - await this.validateCanManageEndpointArtifacts(); + await this.validateHasReadPrivilege(); } async validatePreUpdateItem( @@ -216,7 +224,7 @@ export class TrustedAppValidator extends BaseValidator { ): Promise { const updatedItem = _updatedItem as ExceptionItemLikeOptions; - await this.validateCanManageEndpointArtifacts(); + await this.validateHasWritePrivilege(); await this.validateTrustedAppData(updatedItem); try { diff --git a/x-pack/plugins/security_solution/server/request_context_factory.ts b/x-pack/plugins/security_solution/server/request_context_factory.ts index 730cbd259f50e..ecf56a988636d 100644 --- a/x-pack/plugins/security_solution/server/request_context_factory.ts +++ b/x-pack/plugins/security_solution/server/request_context_factory.ts @@ -27,6 +27,8 @@ import type { Immutable } from '../common/endpoint/types'; import type { EndpointAuthz } from '../common/endpoint/types/authz'; import { calculateEndpointAuthz, + calculatePermissionsFromPrivileges, + defaultEndpointPermissions, getEndpointAuthzInitialState, } from '../common/endpoint/service/authz'; import { licenseService } from './lib/license'; @@ -79,11 +81,21 @@ export class RequestContextFactory implements IRequestContextFactory { (await context.fleet)?.authz ?? (await startPlugins.fleet?.authz.fromRequest(request)); } - const isEndpointRbacEnabled = - endpointAppContextService.experimentalFeatures.endpointRbacEnabled; - const coreContext = await context.core; + let endpointPermissions = defaultEndpointPermissions(); + if (endpointAppContextService.security) { + const checkPrivileges = + endpointAppContextService.security.authz.checkPrivilegesDynamicallyWithRequest(request); + const { privileges } = await checkPrivileges({ + kibana: [ + endpointAppContextService.security.authz.actions.ui.get('siem', 'crud'), + endpointAppContextService.security.authz.actions.ui.get('siem', 'show'), + ], + }); + endpointPermissions = calculatePermissionsFromPrivileges(privileges.kibana); + } + return { core: coreContext, @@ -94,12 +106,15 @@ export class RequestContextFactory implements IRequestContextFactory { if (!startPlugins.fleet) { endpointAuthz = getEndpointAuthzInitialState(); } else { + const isEndpointRbacEnabled = + endpointAppContextService.experimentalFeatures.endpointRbacEnabled; const userRoles = security?.authc.getCurrentUser(request)?.roles ?? []; endpointAuthz = calculateEndpointAuthz( licenseService, fleetAuthz, userRoles, - isEndpointRbacEnabled + isEndpointRbacEnabled, + endpointPermissions ); } } diff --git a/x-pack/plugins/session_view/common/index.ts b/x-pack/plugins/session_view/common/index.ts new file mode 100644 index 0000000000000..5e24674c0b52d --- /dev/null +++ b/x-pack/plugins/session_view/common/index.ts @@ -0,0 +1,10 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ENTRY_SESSION_ENTITY_ID_PROPERTY } from './constants'; +import { EventAction } from './types/process_tree'; +export { ENTRY_SESSION_ENTITY_ID_PROPERTY, EventAction }; diff --git a/x-pack/plugins/session_view/public/index.ts b/x-pack/plugins/session_view/public/index.ts index a9f5fcaa858ac..74f55d7c143ba 100644 --- a/x-pack/plugins/session_view/public/index.ts +++ b/x-pack/plugins/session_view/public/index.ts @@ -5,9 +5,12 @@ * 2.0. */ +import { ENTRY_SESSION_ENTITY_ID_PROPERTY } from '../common/constants'; +import { EventAction } from '../common/types/process_tree'; import { SessionViewPlugin } from './plugin'; export type { SessionViewStart } from './types'; +export { ENTRY_SESSION_ENTITY_ID_PROPERTY, EventAction }; export function plugin() { return new SessionViewPlugin(); diff --git a/x-pack/plugins/spaces/public/advanced_settings/components/advanced_settings_subtitle/advanced_settings_subtitle.tsx b/x-pack/plugins/spaces/public/advanced_settings/components/advanced_settings_subtitle/advanced_settings_subtitle.tsx index a717bc837b522..61c7f063b3dae 100644 --- a/x-pack/plugins/spaces/public/advanced_settings/components/advanced_settings_subtitle/advanced_settings_subtitle.tsx +++ b/x-pack/plugins/spaces/public/advanced_settings/components/advanced_settings_subtitle/advanced_settings_subtitle.tsx @@ -32,15 +32,13 @@ export const AdvancedSettingsSubtitle = (props: Props) => { color="primary" iconType="spacesApp" title={ -

- {activeSpace.name}, - }} - /> -

+ {activeSpace.name}, + }} + /> } /> diff --git a/x-pack/plugins/stack_alerts/public/alert_types/es_query/expression/es_query_expression.tsx b/x-pack/plugins/stack_alerts/public/alert_types/es_query/expression/es_query_expression.tsx index caee77b9b720a..37369d60335a5 100644 --- a/x-pack/plugins/stack_alerts/public/alert_types/es_query/expression/es_query_expression.tsx +++ b/x-pack/plugins/stack_alerts/public/alert_types/es_query/expression/es_query_expression.tsx @@ -192,6 +192,7 @@ export const EsQueryExpression: React.FC< 0} error={errors.esQuery} @@ -208,7 +209,6 @@ export const EsQueryExpression: React.FC< languageId="xjson" width="100%" height="200px" - data-test-subj="queryJsonEditor" value={xJson} onChange={(xjson: string) => { setXJson(xjson); diff --git a/x-pack/plugins/stack_alerts/public/alert_types/threshold/expression.test.tsx b/x-pack/plugins/stack_alerts/public/alert_types/threshold/expression.test.tsx index 6fb83aad7287d..4b79a68f2125c 100644 --- a/x-pack/plugins/stack_alerts/public/alert_types/threshold/expression.test.tsx +++ b/x-pack/plugins/stack_alerts/public/alert_types/threshold/expression.test.tsx @@ -121,6 +121,7 @@ describe('IndexThresholdAlertTypeExpression', () => { expect(wrapper.find('[data-test-subj="forLastExpression"]').exists()).toBeTruthy(); expect(wrapper.find('[data-test-subj="visualizationPlaceholder"]').exists()).toBeTruthy(); expect(wrapper.find('[data-test-subj="thresholdVisualization"]').exists()).toBeFalsy(); + expect(wrapper.find('[data-test-subj="filterKuery"]').exists()).toBeTruthy(); }); test(`should render IndexThresholdAlertTypeExpression with expected components when aggType does require field`, async () => { @@ -133,6 +134,7 @@ describe('IndexThresholdAlertTypeExpression', () => { expect(wrapper.find('[data-test-subj="forLastExpression"]').exists()).toBeTruthy(); expect(wrapper.find('[data-test-subj="visualizationPlaceholder"]').exists()).toBeTruthy(); expect(wrapper.find('[data-test-subj="thresholdVisualization"]').exists()).toBeFalsy(); + expect(wrapper.find('[data-test-subj="filterKuery"]').exists()).toBeTruthy(); }); test(`should render IndexThresholdAlertTypeExpression with visualization when there are no expression errors`, async () => { @@ -175,6 +177,7 @@ describe('IndexThresholdAlertTypeExpression', () => { expect( wrapper.find('EuiEmptyPrompt[data-test-subj="visualizationPlaceholder"]').text() ).toEqual(`Complete the expression to generate a preview.`); + expect(wrapper.find('input[data-test-subj="filterKuery"]').text()).toEqual(''); }); test(`should use alert params when params are defined`, async () => { @@ -186,6 +189,7 @@ describe('IndexThresholdAlertTypeExpression', () => { const groupBy = 'top'; const termSize = '27'; const termField = 'host.name'; + const wrapper = await setup( getAlertParams({ aggType, diff --git a/x-pack/plugins/stack_alerts/public/alert_types/threshold/expression.tsx b/x-pack/plugins/stack_alerts/public/alert_types/threshold/expression.tsx index de8b1ec484afc..37ad715aae18b 100644 --- a/x-pack/plugins/stack_alerts/public/alert_types/threshold/expression.tsx +++ b/x-pack/plugins/stack_alerts/public/alert_types/threshold/expression.tsx @@ -5,10 +5,18 @@ * 2.0. */ -import React, { useState, Fragment, useEffect } from 'react'; +import React, { useState, Fragment, useEffect, useCallback, ChangeEvent } from 'react'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; -import { EuiSpacer, EuiCallOut, EuiEmptyPrompt, EuiText, EuiTitle } from '@elastic/eui'; +import { + EuiSpacer, + EuiCallOut, + EuiEmptyPrompt, + EuiText, + EuiTitle, + EuiFieldSearch, + EuiFormRow, +} from '@elastic/eui'; import { HttpSetup } from '@kbn/core/public'; import { useKibana } from '@kbn/kibana-react-plugin/public'; import { @@ -78,6 +86,7 @@ export const IndexThresholdAlertTypeExpression: React.FunctionComponent< threshold, timeWindowSize, timeWindowUnit, + filterKuery, } = ruleParams; const indexArray = indexParamToArray(index); @@ -133,6 +142,13 @@ export const IndexThresholdAlertTypeExpression: React.FunctionComponent< setEsFields(currentEsFields); }; + const handleFilterChange = useCallback( + (e: ChangeEvent) => { + setRuleParams('filterKuery', e.target.value || undefined); + }, + [setRuleParams] + ); + useEffect(() => { setDefaultExpressionValues(); // eslint-disable-next-line react-hooks/exhaustive-deps @@ -261,6 +277,33 @@ export const IndexThresholdAlertTypeExpression: React.FunctionComponent< } /> + +
+ +
+
+ + 0} + error={errors.filterKuery} + > + 0} + /> + +
{cannotShowVisualization ? ( diff --git a/x-pack/plugins/stack_alerts/public/alert_types/threshold/index_threshold_api.ts b/x-pack/plugins/stack_alerts/public/alert_types/threshold/index_threshold_api.ts index d1e5613c659f7..9dfcfa0bffc31 100644 --- a/x-pack/plugins/stack_alerts/public/alert_types/threshold/index_threshold_api.ts +++ b/x-pack/plugins/stack_alerts/public/alert_types/threshold/index_threshold_api.ts @@ -36,6 +36,7 @@ export async function getThresholdAlertVisualizationData({ termSize: model.termSize, timeWindowSize: model.timeWindowSize, timeWindowUnit: model.timeWindowUnit, + filterKuery: model.filterKuery, dateStart: new Date(visualizeOptions.rangeFrom).toISOString(), dateEnd: new Date(visualizeOptions.rangeTo).toISOString(), interval: visualizeOptions.interval, diff --git a/x-pack/plugins/stack_alerts/public/alert_types/threshold/types.ts b/x-pack/plugins/stack_alerts/public/alert_types/threshold/types.ts index ed6758e6d7326..20a4bd5c6a2c0 100644 --- a/x-pack/plugins/stack_alerts/public/alert_types/threshold/types.ts +++ b/x-pack/plugins/stack_alerts/public/alert_types/threshold/types.ts @@ -39,4 +39,5 @@ export interface IndexThresholdAlertParams extends RuleTypeParams { threshold: number[]; timeWindowSize: number; timeWindowUnit: string; + filterKuery?: string; } diff --git a/x-pack/plugins/stack_alerts/public/alert_types/threshold/validation.test.ts b/x-pack/plugins/stack_alerts/public/alert_types/threshold/validation.test.ts index 459949f18528e..d02afc87ad4f4 100644 --- a/x-pack/plugins/stack_alerts/public/alert_types/threshold/validation.test.ts +++ b/x-pack/plugins/stack_alerts/public/alert_types/threshold/validation.test.ts @@ -94,4 +94,21 @@ describe('expression params validation', () => { expect(validateExpression(initialParams).errors.threshold1.length).toBeGreaterThan(0); expect(validateExpression(initialParams).errors.threshold1[0]).toBe('Threshold1 is required.'); }); + + test('if filterKuery is invalid should return proper error message', () => { + const initialParams: IndexThresholdAlertParams = { + index: ['test'], + aggType: 'count', + groupBy: 'top', + threshold: [1], + timeWindowSize: 1, + timeWindowUnit: 's', + thresholdComparator: 'between', + filterKuery: 'group:', + }; + expect(validateExpression(initialParams).errors.filterKuery.length).toBeGreaterThan(0); + expect(validateExpression(initialParams).errors.filterKuery[0]).toBe( + 'Filter query is invalid.' + ); + }); }); diff --git a/x-pack/plugins/stack_alerts/public/alert_types/threshold/validation.ts b/x-pack/plugins/stack_alerts/public/alert_types/threshold/validation.ts index a7f695094ce31..3b92fe8ae2dbf 100644 --- a/x-pack/plugins/stack_alerts/public/alert_types/threshold/validation.ts +++ b/x-pack/plugins/stack_alerts/public/alert_types/threshold/validation.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { toElasticsearchQuery, fromKueryExpression } from '@kbn/es-query'; import { i18n } from '@kbn/i18n'; import { ValidationResult, @@ -26,6 +27,7 @@ export const validateExpression = (alertParams: IndexThresholdAlertParams): Vali threshold, timeWindowSize, thresholdComparator, + filterKuery, } = alertParams; const validationResult = { errors: {} }; const errors = { @@ -37,8 +39,22 @@ export const validateExpression = (alertParams: IndexThresholdAlertParams): Vali threshold1: new Array(), index: new Array(), timeField: new Array(), + filterKuery: new Array(), }; validationResult.errors = errors; + + if (!!filterKuery) { + try { + toElasticsearchQuery(fromKueryExpression(filterKuery as string)); + } catch (e) { + errors.filterKuery.push( + i18n.translate('xpack.stackAlerts.threshold.ui.validation.error.invalidKql', { + defaultMessage: 'Filter query is invalid.', + }) + ); + } + } + if (!index || index.length === 0) { errors.index.push( i18n.translate('xpack.stackAlerts.threshold.ui.validation.error.requiredIndexText', { 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 656a1e5f275e5..adb722ef094d2 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 @@ -104,6 +104,10 @@ describe('ruleType', () => { "description": "termField", "name": "termField", }, + Object { + "description": "filterKuery", + "name": "filterKuery", + }, Object { "description": "termSize", "name": "termSize", 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 3b3480407fcfc..32f30c2db437d 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 @@ -169,6 +169,7 @@ export function getRuleType( timeWindowSize: params.timeWindowSize, timeWindowUnit: params.timeWindowUnit, interval: undefined, + filterKuery: params.filterKuery, }; // console.log(`index_threshold: query: ${JSON.stringify(queryParams, null, 4)}`); const result = await ( diff --git a/x-pack/plugins/stack_connectors/README.md b/x-pack/plugins/stack_connectors/README.md index 38685950658d6..d92225a641e3d 100644 --- a/x-pack/plugins/stack_connectors/README.md +++ b/x-pack/plugins/stack_connectors/README.md @@ -332,6 +332,32 @@ The following table describes the properties of the `incident` object. | severity | The severity of the incident. | string _(optional)_ | --- +## Ospgenie + +Refer to the [Run connector API documentation](https://www.elastic.co/guide/en/kibana/master/execute-connector-api.html#execute-connector-api-request-body) +for the full list of properties. + +### `params` + +| Property | Description | Type | +| --------------- | ------------------------------------------------------------------ | ------ | +| subAction | The subaction to perform. It can be `createAlert` or `closeAlert`. | string | +| subActionParams | The parameters of the subaction. | object | + +`subActionParams (createAlert)` + +| Property | Description | Type | +| -------- | ------------------------------------------------------------------------------------------------------------- | --------------------- | +| message | The alert message. | string | + +The optional parameters `alias`, `description`, `responders`, `visibleTo`, `actions`, `tags`, `details`, `entity`, `source`, `priority`, `user`, and `note` are supported. See the [Opsgenie API documentation](https://docs.opsgenie.com/docs/alert-api#create-alert) for more information on their types. + +`subActionParams (closeAlert)` + +No parameters are required. For the definition of the optional parameters see the [Opsgenie API documentation](https://docs.opsgenie.com/docs/alert-api#close-alert). + +--- + # Developing New Connector Types When creating a new connector type, your plugin will eventually call `server.plugins.actions.setup.registerType()` to register the type with the `actions` plugin, but there are some additional things to think about about and implement. @@ -370,4 +396,4 @@ Instead of `schema.maybe()`, use `schema.nullable()`, which is the same as `sche ## User interface -To make this connector usable in the Kibana UI, you will need to provide all the UI editing aspects of the connector. The existing connector type user interfaces are defined in [`x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types`](../triggers_actions_ui/public/application/components/builtin_action_types). For more information, see the [UI documentation](../triggers_actions_ui/README.md#create-and-register-new-action-type-ui). \ No newline at end of file +To make this connector usable in the Kibana UI, you will need to provide all the UI editing aspects of the connector. The existing connector type user interfaces are defined in [`x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types`](../triggers_actions_ui/public/application/components/builtin_action_types). For more information, see the [UI documentation](../triggers_actions_ui/README.md#create-and-register-new-action-type-ui). 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 67a34dd285fe3..5aa352986939e 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/index.ts @@ -16,6 +16,7 @@ import { getSlackConnectorType, getTeamsConnectorType, getWebhookConnectorType, + getOpsgenieConnectorType, getXmattersConnectorType, } from './stack'; import { @@ -26,7 +27,6 @@ import { getServiceNowSIRConnectorType, getSwimlaneConnectorType, } from './cases'; - export type { EmailActionParams, IndexActionParams, @@ -46,6 +46,7 @@ export { SlackConnectorTypeId, TeamsConnectorTypeId, WebhookConnectorTypeId, + OpsgenieConnectorTypeId, XmattersConnectorTypeId, } from './stack'; export type { @@ -86,4 +87,5 @@ export function registerConnectorTypes({ actions.registerType(getJiraConnectorType({ logger })); actions.registerType(getResilientConnectorType({ logger })); actions.registerType(getTeamsConnectorType({ logger })); + actions.registerSubActionConnectorType(getOpsgenieConnectorType()); } diff --git a/x-pack/plugins/stack_connectors/server/connector_types/stack/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/stack/index.ts index 6fd7faeaf1729..1d7df7b21ed94 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/stack/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/stack/index.ts @@ -49,6 +49,8 @@ export { } from './webhook'; export type { ActionParamsType as WebhookActionParams } from './webhook'; +export { getOpsgenieConnectorType, OpsgenieConnectorTypeId } from './opsgenie'; + export { getConnectorType as getXmattersConnectorType, ConnectorTypeId as XmattersConnectorTypeId, diff --git a/x-pack/plugins/stack_connectors/server/connector_types/stack/opsgenie/connector.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/stack/opsgenie/connector.test.ts new file mode 100644 index 0000000000000..af9380b8ea75b --- /dev/null +++ b/x-pack/plugins/stack_connectors/server/connector_types/stack/opsgenie/connector.test.ts @@ -0,0 +1,150 @@ +/* + * 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 axios, { AxiosInstance } from 'axios'; +import crypto from 'crypto'; +import { ActionsConfigurationUtilities } from '@kbn/actions-plugin/server/actions_config'; +import { actionsConfigMock } from '@kbn/actions-plugin/server/actions_config.mock'; +import { actionsMock } from '@kbn/actions-plugin/server/mocks'; +import { loggingSystemMock } from '@kbn/core-logging-server-mocks'; +import { MockedLogger } from '@kbn/logging-mocks'; +import { OpsgenieConnectorTypeId } from '.'; +import { OpsgenieConnector } from './connector'; +import * as utils from '@kbn/actions-plugin/server/lib/axios_utils'; + +jest.mock('axios'); + +jest.mock('@kbn/actions-plugin/server/lib/axios_utils', () => { + const originalUtils = jest.requireActual('@kbn/actions-plugin/server/lib/axios_utils'); + return { + ...originalUtils, + request: jest.fn(), + }; +}); + +const axiosMock = axios as jest.Mocked; +const requestMock = utils.request as jest.Mock; + +describe('OpsgenieConnector', () => { + const axiosInstanceMock = jest.fn(); + + let connector: OpsgenieConnector; + let mockedActionsConfig: jest.Mocked; + let logger: MockedLogger; + let services: ReturnType; + + const defaultCreateAlertExpect = { + method: 'post', + url: 'https://example.com/v2/alerts', + headers: { Authorization: 'GenieKey 123', 'Content-Type': 'application/json' }, + }; + + const createCloseAlertExpect = (alias: string) => ({ + method: 'post', + url: `https://example.com/v2/alerts/${alias}/close?identifierType=alias`, + headers: { Authorization: 'GenieKey 123', 'Content-Type': 'application/json' }, + }); + + const ignoredRequestFields = { + axios: expect.anything(), + configurationUtilities: expect.anything(), + logger: expect.anything(), + }; + + beforeEach(() => { + jest.resetAllMocks(); + jest.clearAllMocks(); + requestMock.mockReturnValue({ data: { took: 5, requestId: '123', result: 'ok' } }); + axiosMock.create.mockImplementation(() => { + return axiosInstanceMock as unknown as AxiosInstance; + }); + + logger = loggingSystemMock.createLogger(); + services = actionsMock.createServices(); + mockedActionsConfig = actionsConfigMock.create(); + + connector = new OpsgenieConnector({ + configurationUtilities: mockedActionsConfig, + config: { apiUrl: 'https://example.com' }, + connector: { id: '1', type: OpsgenieConnectorTypeId }, + secrets: { apiKey: '123' }, + logger, + services, + }); + }); + + it('calls request with the correct arguments for creating an alert', async () => { + await connector.createAlert({ message: 'hello' }); + + expect(requestMock.mock.calls[0][0]).toEqual({ + data: { message: 'hello' }, + ...ignoredRequestFields, + ...defaultCreateAlertExpect, + }); + }); + + it('calls request without modifying the alias when it is less than 512 characters when creating an alert', async () => { + await connector.createAlert({ message: 'hello', alias: '111' }); + + expect(requestMock.mock.calls[0][0]).toEqual({ + ...ignoredRequestFields, + ...defaultCreateAlertExpect, + data: { message: 'hello', alias: '111' }, + }); + }); + + it('calls request without modifying the alias when it is equal to 512 characters when creating an alert', async () => { + const alias = 'a'.repeat(512); + await connector.createAlert({ message: 'hello', alias }); + + expect(requestMock.mock.calls[0][0]).toEqual({ + ...ignoredRequestFields, + ...defaultCreateAlertExpect, + data: { message: 'hello', alias }, + }); + }); + + it('calls request with the sha256 hash of the alias when it is greater than 512 characters when creating an alert', async () => { + const alias = 'a'.repeat(513); + + const hasher = crypto.createHash('sha256'); + const sha256Hash = hasher.update(alias); + + await connector.createAlert({ message: 'hello', alias }); + + expect(requestMock.mock.calls[0][0]).toEqual({ + ...ignoredRequestFields, + ...defaultCreateAlertExpect, + data: { message: 'hello', alias: `sha-${sha256Hash.digest('hex')}` }, + }); + }); + + it('calls request with the sha256 hash of the alias when it is greater than 512 characters when closing an alert', async () => { + const alias = 'a'.repeat(513); + + const hasher = crypto.createHash('sha256'); + const sha256Hash = hasher.update(alias); + + await connector.closeAlert({ alias }); + + expect(requestMock.mock.calls[0][0]).toEqual({ + ...ignoredRequestFields, + ...createCloseAlertExpect(`sha-${sha256Hash.digest('hex')}`), + data: {}, + }); + }); + + it('calls request with the correct arguments for closing an alert', async () => { + await connector.closeAlert({ user: 'sam', alias: '111' }); + + expect(requestMock.mock.calls[0][0]).toEqual({ + ...ignoredRequestFields, + ...createCloseAlertExpect('111'), + data: { user: 'sam' }, + }); + }); +}); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/stack/opsgenie/connector.ts b/x-pack/plugins/stack_connectors/server/connector_types/stack/opsgenie/connector.ts new file mode 100644 index 0000000000000..4c053c954a192 --- /dev/null +++ b/x-pack/plugins/stack_connectors/server/connector_types/stack/opsgenie/connector.ts @@ -0,0 +1,112 @@ +/* + * 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 crypto from 'crypto'; +import { ServiceParams, SubActionConnector } from '@kbn/actions-plugin/server'; +import { AxiosError } from 'axios'; +import { CloseAlertParamsSchema, CreateAlertParamsSchema, Response } from './schema'; +import { CloseAlertParams, Config, CreateAlertParams, Secrets } from './types'; +import * as i18n from './translations'; + +interface ErrorSchema { + message?: string; + errors?: { + message?: string; + }; +} + +export class OpsgenieConnector extends SubActionConnector { + constructor(params: ServiceParams) { + super(params); + + this.registerSubAction({ + method: this.createAlert.name, + name: 'createAlert', + schema: CreateAlertParamsSchema, + }); + + this.registerSubAction({ + method: this.closeAlert.name, + name: 'closeAlert', + schema: CloseAlertParamsSchema, + }); + } + + public getResponseErrorMessage(error: AxiosError) { + return `Message: ${ + error.response?.data.errors?.message ?? + error.response?.data.message ?? + error.message ?? + i18n.UNKNOWN_ERROR + }`; + } + + public async createAlert(params: CreateAlertParams) { + const res = await this.request({ + method: 'post', + url: this.concatPathToURL('v2/alerts').toString(), + data: { ...params, ...OpsgenieConnector.createAliasObj(params.alias) }, + headers: this.createHeaders(), + responseSchema: Response, + }); + + return res.data; + } + + private static createAliasObj(alias?: string) { + if (!alias) { + return {}; + } + + const newAlias = OpsgenieConnector.createAlias(alias); + + return { alias: newAlias }; + } + + private static createAlias(alias: string) { + // opsgenie v2 requires that the alias length be no more than 512 characters + // see their docs for more details https://docs.opsgenie.com/docs/alert-api#create-alert + if (alias.length <= 512) { + return alias; + } + + // To give preference to avoiding collisions we're using sha256 over of md5 but we are compromising on speed a bit here + const hasher = crypto.createHash('sha256'); + const sha256Hash = hasher.update(alias); + + return `sha-${sha256Hash.digest('hex')}`; + } + + private createHeaders() { + return { Authorization: `GenieKey ${this.secrets.apiKey}` }; + } + + public async closeAlert(params: CloseAlertParams) { + const newAlias = OpsgenieConnector.createAlias(params.alias); + + const fullURL = this.concatPathToURL(`v2/alerts/${newAlias}/close`); + fullURL.searchParams.set('identifierType', 'alias'); + + const { alias, ...paramsWithoutAlias } = params; + + const res = await this.request({ + method: 'post', + url: fullURL.toString(), + data: paramsWithoutAlias, + headers: this.createHeaders(), + responseSchema: Response, + }); + + return res.data; + } + + private concatPathToURL(path: string) { + const fullURL = new URL(path, this.config.apiUrl); + + return fullURL; + } +} diff --git a/x-pack/plugins/stack_connectors/server/connector_types/stack/opsgenie/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/stack/opsgenie/index.ts new file mode 100644 index 0000000000000..b5c453ae22e0b --- /dev/null +++ b/x-pack/plugins/stack_connectors/server/connector_types/stack/opsgenie/index.ts @@ -0,0 +1,39 @@ +/* + * 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 { + AlertingConnectorFeatureId, + SecurityConnectorFeatureId, + UptimeConnectorFeatureId, +} from '@kbn/actions-plugin/common'; +import { urlAllowListValidator } from '@kbn/actions-plugin/server'; +import { + SubActionConnectorType, + ValidatorType, +} from '@kbn/actions-plugin/server/sub_action_framework/types'; +import { OpsgenieConnector } from './connector'; +import { ConfigSchema, SecretsSchema } from './schema'; +import { Config, Secrets } from './types'; +import * as i18n from './translations'; + +export const OpsgenieConnectorTypeId = '.opsgenie'; + +export const getOpsgenieConnectorType = (): SubActionConnectorType => { + return { + Service: OpsgenieConnector, + minimumLicenseRequired: 'platinum', + name: i18n.OPSGENIE_NAME, + id: OpsgenieConnectorTypeId, + schema: { config: ConfigSchema, secrets: SecretsSchema }, + validators: [{ type: ValidatorType.CONFIG, validator: urlAllowListValidator('apiUrl') }], + supportedFeatureIds: [ + AlertingConnectorFeatureId, + UptimeConnectorFeatureId, + SecurityConnectorFeatureId, + ], + }; +}; diff --git a/x-pack/plugins/stack_connectors/server/connector_types/stack/opsgenie/schema.ts b/x-pack/plugins/stack_connectors/server/connector_types/stack/opsgenie/schema.ts new file mode 100644 index 0000000000000..23fbe6be32b97 --- /dev/null +++ b/x-pack/plugins/stack_connectors/server/connector_types/stack/opsgenie/schema.ts @@ -0,0 +1,118 @@ +/* + * 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'; + +export const ConfigSchema = schema.object({ + apiUrl: schema.string(), +}); + +export const SecretsSchema = schema.object({ + apiKey: schema.string(), +}); + +const responderTypes = schema.oneOf([ + schema.literal('team'), + schema.literal('user'), + schema.literal('escalation'), + schema.literal('schedule'), +]); + +export const CreateAlertParamsSchema = schema.object({ + message: schema.string({ maxLength: 130 }), + /** + * The max length here should be 512 according to Opsgenie's docs but we will sha256 hash the alias if it is longer than 512 + * so we'll not impose a limit on the schema otherwise it'll get rejected prematurely. + */ + alias: schema.maybe(schema.string()), + description: schema.maybe(schema.string({ maxLength: 15000 })), + responders: schema.maybe( + schema.arrayOf( + schema.oneOf([ + schema.object({ + name: schema.string(), + type: responderTypes, + }), + schema.object({ id: schema.string(), type: responderTypes }), + ]), + { maxSize: 50 } + ) + ), + visibleTo: schema.maybe( + schema.arrayOf( + schema.oneOf([ + schema.object({ + name: schema.string(), + type: schema.literal('team'), + }), + schema.object({ + id: schema.string(), + type: schema.literal('team'), + }), + schema.object({ + id: schema.string(), + type: schema.literal('user'), + }), + schema.object({ + username: schema.string(), + type: schema.literal('user'), + }), + ]), + { maxSize: 50 } + ) + ), + actions: schema.maybe(schema.arrayOf(schema.string({ maxLength: 50 }), { maxSize: 10 })), + tags: schema.maybe(schema.arrayOf(schema.string({ maxLength: 50 }), { maxSize: 20 })), + /** + * The validation requirement here is that the total characters between the key and value do not exceed 8000. Opsgenie + * will truncate the value if it would exceed the 8000 but it doesn't throw an error. Because of this I'm intentionally + * not validating the length of the keys and values here. + */ + details: schema.maybe(schema.recordOf(schema.string(), schema.string())), + entity: schema.maybe(schema.string({ maxLength: 512 })), + source: schema.maybe(schema.string({ maxLength: 100 })), + priority: schema.maybe( + schema.oneOf([ + schema.literal('P1'), + schema.literal('P2'), + schema.literal('P3'), + schema.literal('P4'), + schema.literal('P5'), + ]) + ), + user: schema.maybe(schema.string({ maxLength: 100 })), + note: schema.maybe(schema.string({ maxLength: 25000 })), +}); + +const SuccessfulResponse = schema.object( + { + took: schema.number(), + requestId: schema.string(), + result: schema.string(), + }, + { unknowns: 'allow' } +); + +const FailureResponse = schema.object( + { + took: schema.number(), + requestId: schema.string(), + message: schema.maybe(schema.string()), + result: schema.maybe(schema.string()), + errors: schema.maybe(schema.object({ message: schema.string() })), + }, + { unknowns: 'allow' } +); + +export const Response = schema.oneOf([SuccessfulResponse, FailureResponse]); + +export const CloseAlertParamsSchema = schema.object({ + alias: schema.string(), + user: schema.maybe(schema.string({ maxLength: 100 })), + source: schema.maybe(schema.string({ maxLength: 100 })), + note: schema.maybe(schema.string({ maxLength: 25000 })), +}); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/stack/opsgenie/translations.ts b/x-pack/plugins/stack_connectors/server/connector_types/stack/opsgenie/translations.ts new file mode 100644 index 0000000000000..d5cd24f10a329 --- /dev/null +++ b/x-pack/plugins/stack_connectors/server/connector_types/stack/opsgenie/translations.ts @@ -0,0 +1,16 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { i18n } from '@kbn/i18n'; + +export const UNKNOWN_ERROR = i18n.translate('xpack.stackConnectors.opsgenie.unknownError', { + defaultMessage: 'unknown error', +}); + +export const OPSGENIE_NAME = i18n.translate('xpack.stackConnectors.opsgenie.name', { + defaultMessage: 'Opsgenie', +}); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/stack/opsgenie/types.ts b/x-pack/plugins/stack_connectors/server/connector_types/stack/opsgenie/types.ts new file mode 100644 index 0000000000000..eaf436fbe256a --- /dev/null +++ b/x-pack/plugins/stack_connectors/server/connector_types/stack/opsgenie/types.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { TypeOf } from '@kbn/config-schema'; +import { + CloseAlertParamsSchema, + ConfigSchema, + CreateAlertParamsSchema, + SecretsSchema, +} from './schema'; + +export type Config = TypeOf; +export type Secrets = TypeOf; + +export type CreateAlertParams = TypeOf; +export type CloseAlertParams = TypeOf; diff --git a/x-pack/plugins/synthetics/common/constants/ui.ts b/x-pack/plugins/synthetics/common/constants/ui.ts index 226eda1986886..4fb8a374f944b 100644 --- a/x-pack/plugins/synthetics/common/constants/ui.ts +++ b/x-pack/plugins/synthetics/common/constants/ui.ts @@ -7,6 +7,10 @@ export const MONITOR_ROUTE = '/monitor/:monitorId?'; +export const MONITOR_HISTORY_ROUTE = '/monitor/:monitorId/history'; + +export const MONITOR_ERRORS_ROUTE = '/monitor/:monitorId/errors'; + export const MONITOR_ADD_ROUTE = '/add-monitor'; export const MONITOR_EDIT_ROUTE = '/edit-monitor/:monitorId'; diff --git a/x-pack/plugins/synthetics/e2e/journeys/data_view_permissions.ts b/x-pack/plugins/synthetics/e2e/journeys/data_view_permissions.ts index e5714234de690..5aa7ee96f25b1 100644 --- a/x-pack/plugins/synthetics/e2e/journeys/data_view_permissions.ts +++ b/x-pack/plugins/synthetics/e2e/journeys/data_view_permissions.ts @@ -6,8 +6,12 @@ */ import { journey, step, expect, before } from '@elastic/synthetics'; +import { + byTestId, + TIMEOUT_60_SEC, + waitForLoadingToFinish, +} from '@kbn/observability-plugin/e2e/utils'; import { callKibana } from '@kbn/apm-plugin/server/test_helpers/create_apm_users/helpers/call_kibana'; -import { byTestId, waitForLoadingToFinish } from '@kbn/observability-plugin/e2e/utils'; import { loginPageProvider } from '../page_objects/login'; journey('DataViewPermissions', async ({ page, params }) => { @@ -44,7 +48,7 @@ journey('DataViewPermissions', async ({ page, params }) => { step('Click explore data button', async () => { await page.click(byTestId('uptimeExploreDataButton')); await waitForLoadingToFinish({ page }); - await page.waitForSelector(`text=${permissionError}`); + await page.waitForSelector(`text=${permissionError}`, TIMEOUT_60_SEC); expect(await page.$(`text=${permissionError}`)).toBeTruthy(); }); }); diff --git a/x-pack/plugins/synthetics/e2e/journeys/index.ts b/x-pack/plugins/synthetics/e2e/journeys/index.ts index a33a5185fcac2..5651b092544de 100644 --- a/x-pack/plugins/synthetics/e2e/journeys/index.ts +++ b/x-pack/plugins/synthetics/e2e/journeys/index.ts @@ -5,9 +5,9 @@ * 2.0. */ +export * from './data_view_permissions'; export * from './synthetics'; export * from './alerts'; -export * from './data_view_permissions'; export * from './uptime.journey'; export * from './step_duration.journey'; export * from './read_only_user'; diff --git a/x-pack/plugins/synthetics/e2e/journeys/private_locations/add_monitor_private_location.ts b/x-pack/plugins/synthetics/e2e/journeys/private_locations/add_monitor_private_location.ts index f6c0fea485891..63fa0a78adfbd 100644 --- a/x-pack/plugins/synthetics/e2e/journeys/private_locations/add_monitor_private_location.ts +++ b/x-pack/plugins/synthetics/e2e/journeys/private_locations/add_monitor_private_location.ts @@ -47,9 +47,9 @@ journey('AddPrivateLocationMonitor', async ({ page, params: { kibanaUrl } }) => await page.click('[data-test-subj="superDatePickerApplyTimeButton"]'); }); - step('Click [placeholder="Find apps, content, and more. Ex: Discover"]', async () => { - await page.click('[placeholder="Find apps, content, and more. Ex: Discover"]'); - await page.fill('[placeholder="Find apps, content, and more. Ex: Discover"]', 'integ'); + step('Click [placeholder="Find apps, content, and more."]', async () => { + await page.click('[placeholder="Find apps, content, and more."]'); + await page.fill('[placeholder="Find apps, content, and more."]', 'integ'); await Promise.all([ page.waitForNavigation(/* { url: '${kibanaUrl}/app/integrations/browse' }*/), page.click('text=Integrations'), diff --git a/x-pack/plugins/synthetics/e2e/journeys/synthetics/index.ts b/x-pack/plugins/synthetics/e2e/journeys/synthetics/index.ts index 3c8869fab85a8..1b74aa6a05b42 100644 --- a/x-pack/plugins/synthetics/e2e/journeys/synthetics/index.ts +++ b/x-pack/plugins/synthetics/e2e/journeys/synthetics/index.ts @@ -7,3 +7,4 @@ export * from './getting_started.journey'; export * from './add_monitor.journey'; +export * from './monitor_selector.journey'; diff --git a/x-pack/plugins/synthetics/e2e/journeys/synthetics/monitor_selector.journey.ts b/x-pack/plugins/synthetics/e2e/journeys/synthetics/monitor_selector.journey.ts new file mode 100644 index 0000000000000..866df48d97e78 --- /dev/null +++ b/x-pack/plugins/synthetics/e2e/journeys/synthetics/monitor_selector.journey.ts @@ -0,0 +1,62 @@ +/* + * 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 { journey, step, expect, before } from '@elastic/synthetics'; +import { + addTestMonitor, + cleanTestMonitors, + enableMonitorManagedViaApi, +} from './services/add_monitor'; +import { syntheticsAppPageProvider } from '../../page_objects/synthetics_app'; + +journey(`MonitorSelector`, async ({ page, params }) => { + const syntheticsApp = syntheticsAppPageProvider({ page, kibanaUrl: params.kibanaUrl }); + const testMonitor1 = 'Test monitor 1'; + const testMonitor2 = 'Test monitor 2'; + const testMonitor3 = 'Test monitor 3'; + + before(async () => { + await enableMonitorManagedViaApi(params.kibanaUrl); + await cleanTestMonitors(params); + + await addTestMonitor(params.kibanaUrl, testMonitor1); + await addTestMonitor(params.kibanaUrl, testMonitor2); + await addTestMonitor(params.kibanaUrl, testMonitor3); + }); + + step('Go to monitor-management', async () => { + await syntheticsApp.navigateToMonitorManagement(); + }); + + step('login to Kibana', async () => { + await syntheticsApp.loginToKibana(); + const invalid = await page.locator(`text=Username or password is incorrect. Please try again.`); + expect(await invalid.isVisible()).toBeFalsy(); + }); + + step('go to monitor', async () => { + await page.click('text=' + testMonitor1); + }); + + step('shows recently viewed monitors', async () => { + await page.click('text=' + testMonitor1); + await page.click('[aria-label="Select a different monitor to view its details"]'); + await page.click('text=' + testMonitor2); + + await page.click('[aria-label="Select a different monitor to view its details"]'); + await page.click('text=Recently viewed'); + await page.click('text=Other monitors'); + await page.click('text=' + testMonitor3); + + await page.click('[aria-label="Select a different monitor to view its details"]'); + await page.click('[placeholder="Monitor name or tag"]'); + await page.fill('[placeholder="Monitor name or tag"]', '2'); + await page.click('text=' + testMonitor2); + + await page.click('[aria-label="Select a different monitor to view its details"]'); + }); +}); diff --git a/x-pack/plugins/synthetics/e2e/journeys/synthetics/services/add_monitor.ts b/x-pack/plugins/synthetics/e2e/journeys/synthetics/services/add_monitor.ts new file mode 100644 index 0000000000000..37078cb3c0676 --- /dev/null +++ b/x-pack/plugins/synthetics/e2e/journeys/synthetics/services/add_monitor.ts @@ -0,0 +1,96 @@ +/* + * 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 axios from 'axios'; + +export const enableMonitorManagedViaApi = async (kibanaUrl: string) => { + try { + await axios.post(kibanaUrl + '/internal/uptime/service/enablement', undefined, { + auth: { username: 'elastic', password: 'changeme' }, + headers: { 'kbn-xsrf': 'true' }, + }); + } catch (e) { + // eslint-disable-next-line no-console + console.log(e); + } +}; + +export const addTestMonitor = async (kibanaUrl: string, name: string) => { + data.name = name; + + try { + await axios.post(kibanaUrl + '/internal/uptime/service/monitors', data, { + auth: { username: 'elastic', password: 'changeme' }, + headers: { 'kbn-xsrf': 'true' }, + }); + } catch (e) { + // eslint-disable-next-line no-console + console.log(e); + } +}; + +export const cleanTestMonitors = async (params: Record) => { + const getService = params.getService; + const server = getService('kibanaServer'); + + try { + await server.savedObjects.clean({ types: ['synthetics-monitor'] }); + } catch (e) { + // eslint-disable-next-line no-console + console.log(e); + } +}; + +const data = { + type: 'browser', + form_monitor_type: 'single', + enabled: true, + schedule: { unit: 'm', number: '10' }, + 'service.name': '', + config_id: '', + tags: [], + timeout: '16', + name: 'Monitor 2', + locations: [{ id: 'us_central', isServiceManaged: true }], + namespace: 'default', + origin: 'ui', + journey_id: '', + project_id: '', + playwright_options: '', + __ui: { + script_source: { is_generated_script: false, file_name: '' }, + is_zip_url_tls_enabled: false, + }, + params: '', + 'url.port': null, + 'source.inline.script': + "step('Go to https://www.google.com', async () => {\n await page.goto('https://www.google.com');\n expect(await page.isVisible('text=Data')).toBeTruthy();\n });", + 'source.project.content': '', + 'source.zip_url.url': '', + 'source.zip_url.username': '', + 'source.zip_url.password': '', + 'source.zip_url.folder': '', + 'source.zip_url.proxy_url': '', + playwright_text_assertion: 'Data', + urls: 'https://www.google.com', + screenshots: 'on', + synthetics_args: [], + 'filter_journeys.match': '', + 'filter_journeys.tags': [], + ignore_https_errors: false, + 'throttling.is_enabled': true, + 'throttling.download_speed': '5', + 'throttling.upload_speed': '3', + 'throttling.latency': '20', + 'throttling.config': '5d/3u/20l', + 'ssl.certificate_authorities': '', + 'ssl.certificate': '', + 'ssl.key': '', + 'ssl.key_passphrase': '', + 'ssl.verification_mode': 'full', + 'ssl.supported_protocols': ['TLSv1.1', 'TLSv1.2', 'TLSv1.3'], +}; diff --git a/x-pack/plugins/synthetics/public/apps/locators/edit_monitor.ts b/x-pack/plugins/synthetics/public/apps/locators/edit_monitor.ts index 199ed93c4c393..81139421817e9 100644 --- a/x-pack/plugins/synthetics/public/apps/locators/edit_monitor.ts +++ b/x-pack/plugins/synthetics/public/apps/locators/edit_monitor.ts @@ -9,7 +9,7 @@ import { syntheticsEditMonitorLocatorID } from '@kbn/observability-plugin/common async function navigate({ monitorId }: { monitorId: string }) { return { - app: 'uptime', + app: 'synthetics', path: `/edit-monitor/${monitorId}`, state: {}, }; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/common/links/add_monitor.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/common/links/add_monitor.tsx new file mode 100644 index 0000000000000..41cf49f5703f4 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/common/links/add_monitor.tsx @@ -0,0 +1,25 @@ +/* + * 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 { EuiButtonEmpty } from '@elastic/eui'; +import React from 'react'; +import { i18n } from '@kbn/i18n'; +import { useSyntheticsSettingsContext } from '../../../contexts'; + +export const AddMonitorLink = () => { + const { basePath } = useSyntheticsSettingsContext(); + + return ( + + {CREATE_NEW_MONITOR} + + ); +}; + +const CREATE_NEW_MONITOR = i18n.translate('xpack.synthetics.monitorSummary.createNewMonitor', { + defaultMessage: 'Create monitor', +}); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/getting_started/use_simple_monitor.ts b/x-pack/plugins/synthetics/public/apps/synthetics/components/getting_started/use_simple_monitor.ts index d8d645451c18a..ec4c4e6507358 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/getting_started/use_simple_monitor.ts +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/getting_started/use_simple_monitor.ts @@ -62,7 +62,7 @@ export const useSimpleMonitor = ({ monitorData }: { monitorData?: SimpleFormData title: MONITOR_SUCCESS_LABEL, toastLifeTimeMs: 3000, }); - application?.navigateToApp('uptime', { path: `/monitor/${btoa(newMonitor.id)}` }); + application?.navigateToApp('synthetics', { path: `` }); } }, [application, data, loading, serviceLocations]); 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 new file mode 100644 index 0000000000000..2017109855bfb --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/hooks/use_monitor_latest_ping.tsx @@ -0,0 +1,55 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { useEffect } from 'react'; +import { useDispatch, useSelector } from 'react-redux'; +import { getMonitorRecentPingsAction, selectLatestPing, selectPingsLoading } from '../../../state'; +import { useSelectedLocation } from './use_selected_location'; +import { useSelectedMonitor } from './use_selected_monitor'; + +interface UseMonitorLatestPingParams { + monitorId?: string; + locationLabel?: string; +} + +export const useMonitorLatestPing = (params?: UseMonitorLatestPingParams) => { + const dispatch = useDispatch(); + + const { monitor } = useSelectedMonitor(); + const location = useSelectedLocation(); + + const monitorId = params?.monitorId ?? monitor?.id; + const locationLabel = params?.locationLabel ?? location?.label; + + const latestPing = useSelector(selectLatestPing); + const pingsLoading = useSelector(selectPingsLoading); + + const isUpToDate = + latestPing && + latestPing.monitor.id === monitorId && + latestPing.observer?.geo?.name === locationLabel; + + useEffect(() => { + if (monitorId && locationLabel && !isUpToDate) { + dispatch(getMonitorRecentPingsAction.get({ monitorId, locationId: locationLabel })); + } + }, [dispatch, monitorId, locationLabel, isUpToDate]); + + if (!monitorId || !locationLabel) { + return { loading: pingsLoading, latestPing: null }; + } + + if (!latestPing) { + return { loading: pingsLoading, latestPing: null }; + } + + if (latestPing.monitor.id !== monitorId || latestPing.observer?.geo?.name !== locationLabel) { + return { loading: pingsLoading, latestPing: null }; + } + + return { loading: pingsLoading, latestPing }; +}; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/last_run_info.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/last_run_info.tsx deleted file mode 100644 index d69cde15f734d..0000000000000 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/last_run_info.tsx +++ /dev/null @@ -1,85 +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 from 'react'; -import { EuiBadge, EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui'; -import moment from 'moment'; -import { i18n } from '@kbn/i18n'; -import { useTheme } from '@kbn/observability-plugin/public'; -import { Ping } from '../../../../../common/runtime_types'; -import { useSelectedLocation } from './hooks/use_selected_location'; - -export const MonitorSummaryLastRunInfo = ({ ping }: { ping: Ping }) => { - const selectedLocation = useSelectedLocation(); - const isBrowserType = ping.monitor.type === 'browser'; - const theme = useTheme(); - - return ( - - - {ping.monitor.status === 'up' ? ( - - {isBrowserType ? SUCCESS_LABEL : UP_LABEL} - - ) : ping.monitor.status === 'down' ? ( - - {isBrowserType ? FAILED_LABEL : DOWN_LABEL} - - ) : ( - {PENDING_LABEL} - )} - - - - {i18n.translate('xpack.synthetics.monitorSummary.lastRunLocation', { - defaultMessage: 'in {loc}.', - values: { - // empty value will be replaced with value from location select - loc: selectedLocation?.label ?? '--', - }, - })} - - - - - {ping.timestamp - ? i18n.translate('xpack.synthetics.monitorSummary.lastRunTime', { - defaultMessage: 'Last run on {time}', - values: { - time: moment(ping.timestamp).format('LLL'), - }, - }) - : WAITING} - - - - ); -}; - -const FAILED_LABEL = i18n.translate('xpack.synthetics.monitorSummary.failed', { - defaultMessage: 'Failed', -}); - -const PENDING_LABEL = i18n.translate('xpack.synthetics.monitorSummary.pending', { - defaultMessage: 'Pending', -}); - -const SUCCESS_LABEL = i18n.translate('xpack.synthetics.monitorSummary.succeeded', { - defaultMessage: 'Succeeded', -}); - -const UP_LABEL = i18n.translate('xpack.synthetics.monitorSummary.up', { - defaultMessage: 'Up', -}); - -const DOWN_LABEL = i18n.translate('xpack.synthetics.monitorSummary.down', { - defaultMessage: 'Down', -}); - -const WAITING = i18n.translate('xpack.synthetics.monitorSummary.waiting', { - defaultMessage: 'Waiting for test run result.', -}); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_details_last_run.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_details_last_run.tsx new file mode 100644 index 0000000000000..891421e1158d3 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_details_last_run.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import React from 'react'; +import moment from 'moment'; +import { EuiDescriptionList, EuiLoadingSpinner } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; + +import { useSelectedMonitor } from './hooks/use_selected_monitor'; +import { useMonitorLatestPing } from './hooks/use_monitor_latest_ping'; + +export const MonitorDetailsLastRun: React.FC = () => { + const { monitor } = useSelectedMonitor(); + const { latestPing, loading: pingsLoading } = useMonitorLatestPing(); + + if (!monitor) { + return null; + } + + const description = pingsLoading ? ( + + ) : latestPing ? ( + moment(latestPing.timestamp).fromNow() + ) : ( + '--' + ); + + return ; +}; + +const LAST_RUN_LABEL = i18n.translate('xpack.synthetics.monitorLastRun.lastRunLabel', { + defaultMessage: 'Last run', +}); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_details_location.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_details_location.tsx new file mode 100644 index 0000000000000..2966aee8e53b7 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_details_location.tsx @@ -0,0 +1,131 @@ +/* + * 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 { + EuiContextMenuItem, + EuiContextMenuPanel, + EuiDescriptionList, + EuiHealth, + EuiIcon, + EuiLink, + EuiPopover, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { useKibana } from '@kbn/kibana-react-plugin/public'; +import { useTheme } from '@kbn/observability-plugin/public'; +import React, { useMemo, useState, useCallback } from 'react'; + +import { PLUGIN } from '../../../../../common/constants/plugin'; +import { useLocations } from '../../hooks'; +import { useStatusByLocation } from '../../hooks'; +import { useSelectedLocation } from './hooks/use_selected_location'; +import { useSelectedMonitor } from './hooks/use_selected_monitor'; + +export const MonitorDetailsLocation: React.FC = () => { + const { monitor } = useSelectedMonitor(); + const { services } = useKibana(); + const { locations } = useLocations(); + const theme = useTheme(); + + const { locations: locationsStatus, loading: loadingLocationsStatus } = useStatusByLocation(); + const selectedLocation = useSelectedLocation(); + + const [isLocationListOpen, setIsLocationListOpen] = useState(false); + const openLocationList = useCallback(() => setIsLocationListOpen(true), []); + const closeLocationList = useCallback(() => setIsLocationListOpen(false), []); + + const locationList = useMemo(() => { + if (!selectedLocation || !monitor) { + return ''; + } + + if (monitor?.locations && monitor.locations.length > 1) { + const button = ( + + {selectedLocation.label} + + ); + + const menuItems = loadingLocationsStatus + ? [Loading...] + : monitor.locations + .map((location) => { + const fullLocation = locations.find((l) => l.id === location.id); + if (!fullLocation) { + return; + } + + const locationStatus = locationsStatus.find( + (ls) => ls.observer?.geo?.name === fullLocation.label + ); + + const locationHealthColor = + typeof locationStatus === 'undefined' + ? 'subdued' + : (locationStatus?.summary?.down ?? 0) > 0 + ? theme.eui.euiColorVis9 // down + : theme.eui.euiColorVis0; // up + + return ( + } + onClick={() => { + closeLocationList(); + services.application!.navigateToApp(PLUGIN.SYNTHETICS_PLUGIN_ID, { + path: `/monitor/${monitor.id}?locationId=${fullLocation.id}`, + }); + }} + > + {fullLocation.label} + + ); + }) + .filter((l): l is JSX.Element => typeof l !== undefined); + + return ( + + + + ); + } else { + return selectedLocation.label; + } + }, [ + closeLocationList, + isLocationListOpen, + loadingLocationsStatus, + locations, + locationsStatus, + monitor, + openLocationList, + selectedLocation, + services.application, + theme, + ]); + + if (!selectedLocation || !monitor) { + return null; + } + + return ; +}; + +const LOCATION_LABEL = i18n.translate('xpack.synthetics.monitorLocation.locationLabel', { + defaultMessage: 'Location', +}); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_details_page.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_details_page.tsx index ee9ba46c561bb..cdf4ba1cfb2ce 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_details_page.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_details_page.tsx @@ -5,30 +5,12 @@ * 2.0. */ -import React, { useEffect } from 'react'; -import { useDispatch } from 'react-redux'; -import { useParams } from 'react-router-dom'; +import React from 'react'; import { useSelectedMonitor } from './hooks/use_selected_monitor'; -import { useSelectedLocation } from './hooks/use_selected_location'; -import { getMonitorAction, getMonitorRecentPingsAction } from '../../state/monitor_details'; import { useMonitorListBreadcrumbs } from '../monitors_page/hooks/use_breadcrumbs'; -export const MonitorDetailsPage = () => { - const { monitor } = useSelectedMonitor(); +export const MonitorDetailsPage: React.FC<{ children: React.ReactElement }> = ({ children }) => { + const { monitor } = useSelectedMonitor(); useMonitorListBreadcrumbs([{ text: monitor?.name ?? '' }]); - - const dispatch = useDispatch(); - - const selectedLocation = useSelectedLocation(); - const { monitorId } = useParams<{ monitorId: string }>(); - - useEffect(() => { - dispatch(getMonitorAction.get({ monitorId })); - - if (selectedLocation) { - dispatch(getMonitorRecentPingsAction.get({ monitorId, locationId: selectedLocation.id })); - } - }, [dispatch, monitorId, selectedLocation]); - - return <>; + return children; }; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_details_page_title.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_details_page_title.tsx index 954ecc77c26c0..abe1a496df1a6 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_details_page_title.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_details_page_title.tsx @@ -5,51 +5,19 @@ * 2.0. */ -import React, { useEffect } from 'react'; -import { useDispatch, useSelector } from 'react-redux'; -import { useParams } from 'react-router-dom'; -import { EuiFlexGroup, EuiFlexItem, EuiLoadingContent, EuiText } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; +import React from 'react'; +import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import { MonitorSelector } from './monitor_selector/monitor_selector'; import { useSelectedMonitor } from './hooks/use_selected_monitor'; -import { useSelectedLocation } from './hooks/use_selected_location'; -import { getMonitorRecentPingsAction, selectLatestPing, selectPingsLoading } from '../../state'; -import { MonitorSummaryLastRunInfo } from './last_run_info'; export const MonitorDetailsPageTitle = () => { - const dispatch = useDispatch(); - - const latestPing = useSelector(selectLatestPing); - const pingsLoading = useSelector(selectPingsLoading); - - const { monitorId } = useParams<{ monitorId: string }>(); const { monitor } = useSelectedMonitor(); - const location = useSelectedLocation(); - - useEffect(() => { - const locationId = location?.label; - if (monitorId && locationId) { - dispatch(getMonitorRecentPingsAction.get({ monitorId, locationId })); - } - }, [dispatch, monitorId, location]); return ( - - {monitor?.name} - - {pingsLoading || (latestPing && latestPing.monitor.id !== monitorId) ? ( - - ) : latestPing ? ( - - ) : ( - - {i18n.translate('xpack.synthetics.monitorSummary.noLastRunInformationAvailable', { - defaultMessage: 'No last run information available for {location} yet.', - values: { - location: location?.label, - }, - })} - - )} + + {monitor?.name} + + ); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_details_status.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_details_status.tsx new file mode 100644 index 0000000000000..ac2ae19700e41 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_details_status.tsx @@ -0,0 +1,62 @@ +/* + * 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 { EuiBadge, EuiDescriptionList, EuiLoadingSpinner } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { useTheme } from '@kbn/observability-plugin/public'; + +import { useSelectedMonitor } from './hooks/use_selected_monitor'; +import { useMonitorLatestPing } from './hooks/use_monitor_latest_ping'; + +export const MonitorDetailsStatus: React.FC = () => { + const theme = useTheme(); + const { latestPing, loading: pingsLoading } = useMonitorLatestPing(); + + const { monitor } = useSelectedMonitor(); + + if (!monitor) { + return null; + } + + const isBrowserType = monitor.type === 'browser'; + + const badge = pingsLoading ? ( + + ) : !latestPing ? ( + {PENDING_LABEL} + ) : latestPing.monitor.status === 'up' ? ( + {isBrowserType ? SUCCESS_LABEL : UP_LABEL} + ) : ( + {isBrowserType ? FAILED_LABEL : DOWN_LABEL} + ); + + return ; +}; + +const STATUS_LABEL = i18n.translate('xpack.synthetics.monitorStatus.statusLabel', { + defaultMessage: 'Status', +}); + +const FAILED_LABEL = i18n.translate('xpack.synthetics.monitorStatus.failedLabel', { + defaultMessage: 'Failed', +}); + +const PENDING_LABEL = i18n.translate('xpack.synthetics.monitorStatus.pendingLabel', { + defaultMessage: 'Pending', +}); + +const SUCCESS_LABEL = i18n.translate('xpack.synthetics.monitorStatus.succeededLabel', { + defaultMessage: 'Succeeded', +}); + +const UP_LABEL = i18n.translate('xpack.synthetics.monitorStatus.upLabel', { + defaultMessage: 'Up', +}); + +const DOWN_LABEL = i18n.translate('xpack.synthetics.monitorStatus.downLabel', { + defaultMessage: 'Down', +}); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_detials_tabs.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_detials_tabs.tsx deleted file mode 100644 index 6667034da5fdf..0000000000000 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_detials_tabs.tsx +++ /dev/null @@ -1,70 +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 { EuiIcon, EuiSpacer, EuiTabbedContent } from '@elastic/eui'; -import React from 'react'; -import { i18n } from '@kbn/i18n'; -import { ErrorsTabContent } from './monitor_errors/monitor_errors'; -import { HistoryTabContent } from './monitor_history/monitor_history'; -import { MonitorSummary } from './monitor_summary/monitor_summary'; - -export const MonitorDetailsTabs = () => { - const tabs = [ - { - id: 'summary', - name: SUMMARY_LABEL, - content: ( - <> - - - - ), - }, - { - id: 'history', - name: HISTORY_LABEL, - content: ( - <> - - - - ), - }, - { - id: 'errors', - name: ERRORS_LABEL, - prepend: , - content: ( - <> - - - - ), - }, - ]; - - return ( - {}} - /> - ); -}; - -const SUMMARY_LABEL = i18n.translate('xpack.synthetics.monitorSummary.summary', { - defaultMessage: 'Summary', -}); - -const HISTORY_LABEL = i18n.translate('xpack.synthetics.monitorSummary.history', { - defaultMessage: 'History', -}); - -const ERRORS_LABEL = i18n.translate('xpack.synthetics.monitorSummary.errors', { - defaultMessage: 'Errors', -}); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_errors/monitor_errors.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_errors/monitor_errors.tsx index 75fb0d7ccf3ae..479aa6ac72bfb 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_errors/monitor_errors.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_errors/monitor_errors.tsx @@ -7,6 +7,6 @@ import { EuiText } from '@elastic/eui'; import React from 'react'; -export const ErrorsTabContent = () => { +export const MonitorErrors = () => { return Monitor errors tabs content; }; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_history/monitor_history.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_history/monitor_history.tsx index 5b90c2c2d73e1..a1522f58047da 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_history/monitor_history.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_history/monitor_history.tsx @@ -7,6 +7,6 @@ import { EuiText } from '@elastic/eui'; import React from 'react'; -export const HistoryTabContent = () => { +export const MonitorHistory = () => { return Monitor history tab content; }; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_selector/monitor_selector.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_selector/monitor_selector.tsx new file mode 100644 index 0000000000000..3fb4ff71aaf74 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_selector/monitor_selector.tsx @@ -0,0 +1,160 @@ +/* + * 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, { Fragment, useEffect, useState } from 'react'; +import { + EuiPopover, + EuiPopoverTitle, + EuiSelectable, + EuiButtonIcon, + EuiSelectableOption, + EuiHighlight, + EuiLink, + EuiText, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { useHistory } from 'react-router-dom'; +import { AddMonitorLink } from '../../common/links/add_monitor'; +import { useRecentlyViewedMonitors } from './use_recently_viewed_monitors'; +import { useSyntheticsSettingsContext } from '../../../contexts'; +import { useMonitorName } from './use_monitor_name'; +import { useSelectedLocation } from '../hooks/use_selected_location'; + +export const MonitorSelector = () => { + const history = useHistory(); + + const [options, setOptions] = useState([]); + const [searchValue, setSearchValue] = useState(''); + const [isPopoverOpen, setIsPopoverOpen] = useState(false); + + const selectedLocation = useSelectedLocation(); + + const { basePath } = useSyntheticsSettingsContext(); + + const { values, loading } = useMonitorName({ search: searchValue }); + + const recentlyViewed = useRecentlyViewedMonitors(); + + useEffect(() => { + const newOptions: EuiSelectableOption[] = []; + if (recentlyViewed.length > 0 && !searchValue) { + const otherMonitors = values.filter((value) => + recentlyViewed.every((recent) => recent.key !== value.key) + ); + + if (otherMonitors.length > 0) { + newOptions.push({ key: 'monitors', label: OTHER_MONITORS, isGroupLabel: true }); + } + + setOptions([...recentlyViewed, ...newOptions, ...otherMonitors]); + } else { + setOptions(values); + } + }, [recentlyViewed, searchValue, values]); + + const onButtonClick = () => { + setIsPopoverOpen(!isPopoverOpen); + }; + + const closePopover = () => { + setIsPopoverOpen(false); + }; + + const button = ( + + ); + + return ( + + + {GO_TO_MONITOR} + setSearchValue(val), + autoFocus: true, + }} + options={options} + onChange={(selectedOptions) => { + setOptions(selectedOptions); + const option = selectedOptions.find((opt) => opt.checked === 'on'); + if (option) { + history.push(`/monitor/${option.key}?locationId=${selectedLocation?.id}`); + } + closePopover(); + }} + singleSelection={true} + listProps={{ + showIcons: false, + }} + renderOption={(option, search) => ( + + {option.label} + + )} + noMatchesMessage={NO_RESULT_FOUND} + emptyMessage={} + loadingMessage={LOADING_MONITORS} + > + {(list, search) => ( +
+ + {options.length > 0 || searchValue ? ( + search + ) : ( + + {NO_OTHER_MONITORS_EXISTS} + + )} + + {list} +
+ )} +
+
+
+ ); +}; + +const GO_TO_MONITOR = i18n.translate('xpack.synthetics.monitorSummary.goToMonitor', { + defaultMessage: 'Go to monitor', +}); + +const NO_RESULT_FOUND = i18n.translate('xpack.synthetics.monitorSummary.noResultsFound', { + defaultMessage: 'No monitors found. Try modifying your query.', +}); + +const PLACEHOLDER = i18n.translate('xpack.synthetics.monitorSummary.placeholderSearch', { + defaultMessage: 'Monitor name or tag', +}); + +const SELECT_MONITOR = i18n.translate('xpack.synthetics.monitorSummary.selectMonitor', { + defaultMessage: 'Select a different monitor to view its details', +}); + +const OTHER_MONITORS = i18n.translate('xpack.synthetics.monitorSummary.otherMonitors', { + defaultMessage: 'Other monitors', +}); + +const LOADING_MONITORS = i18n.translate('xpack.synthetics.monitorSummary.loadingMonitors', { + defaultMessage: 'Loading monitors', +}); + +const NO_OTHER_MONITORS_EXISTS = i18n.translate('xpack.synthetics.monitorSummary.noOtherMonitors', { + defaultMessage: 'No other monitors exist.', +}); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_selector/use_monitor_name.ts b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_selector/use_monitor_name.ts new file mode 100644 index 0000000000000..cb097b0f99342 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_selector/use_monitor_name.ts @@ -0,0 +1,35 @@ +/* + * 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 { useMemo } from 'react'; +import { useFetcher } from '@kbn/observability-plugin/public'; +import { useParams } from 'react-router-dom'; +import { fetchMonitorManagementList } from '../../../state'; + +export const useMonitorName = ({ search = '' }: { search?: string }) => { + const { data, loading } = useFetcher(() => { + return fetchMonitorManagementList({ + pageSize: 100, + pageIndex: 0, + sortField: 'name.keyword', + sortOrder: 'asc', + query: search, + }); + }, [search]); + + const { monitorId } = useParams<{ monitorId: string }>(); + + return useMemo(() => { + const { monitors = [] } = data ?? {}; + const values = monitors.map((monitor) => ({ + label: monitor.attributes.name as string, + key: monitor.id, + })); + + return { values: values.filter((val) => val.key !== monitorId), loading }; + }, [data, loading, monitorId]); +}; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_selector/use_recently_viewed_monitors.test.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_selector/use_recently_viewed_monitors.test.tsx new file mode 100644 index 0000000000000..8c5922f4acc7a --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_selector/use_recently_viewed_monitors.test.tsx @@ -0,0 +1,83 @@ +/* + * 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 { renderHook } from '@testing-library/react-hooks'; +import { useRecentlyViewedMonitors } from './use_recently_viewed_monitors'; +import { mockCore, WrappedHelper } from '../../../utils/testing'; +import { syntheticsMonitorType } from '../../../../../../common/types/saved_objects'; +import { MONITOR_ROUTE } from '../../../../../../common/constants'; + +const resultData = { + resolved_objects: [ + { + saved_object: { + id: 'c9322230-2a11-11ed-962b-d3e7eeedf9d1', + + attributes: { + name: 'Test Monitor', + }, + }, + }, + ], +}; + +describe('useRecentlyViewedMonitors', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('returns expected result', () => { + const WrapperWithState = ({ children }: { children: React.ReactElement }) => { + return ( + + {children} + + ); + }; + + const { result } = renderHook(() => useRecentlyViewedMonitors(), { wrapper: WrapperWithState }); + expect(result.current).toEqual([]); + }); + + it('returns the result when found', async () => { + const core = mockCore(); + + core.savedObjects!.client.bulkResolve = jest.fn().mockResolvedValue(resultData); + + const WrapperWithState = ({ children }: { children: React.ReactElement }) => { + return ( + + {children} + + ); + }; + + const { result, waitForNextUpdate } = renderHook(() => useRecentlyViewedMonitors(), { + wrapper: WrapperWithState, + }); + expect(result.current).toEqual([]); + + expect(core.savedObjects?.client.bulkResolve).toHaveBeenCalledTimes(1); + expect(core.savedObjects?.client.bulkResolve).toHaveBeenLastCalledWith([ + { id: '1', type: syntheticsMonitorType }, + ]); + + await waitForNextUpdate(); + + expect(result.current).toEqual([ + { + isGroupLabel: true, + key: 'recently_viewed', + label: 'Recently viewed', + }, + { + key: 'c9322230-2a11-11ed-962b-d3e7eeedf9d1', + label: 'Test Monitor', + }, + ]); + }); +}); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_selector/use_recently_viewed_monitors.ts b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_selector/use_recently_viewed_monitors.ts new file mode 100644 index 0000000000000..64f7a60c28c7a --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_selector/use_recently_viewed_monitors.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 useLocalStorage from 'react-use/lib/useLocalStorage'; +import { i18n } from '@kbn/i18n'; +import { useParams } from 'react-router-dom'; +import { useEffect, useMemo } from 'react'; +import { useKibana } from '@kbn/kibana-react-plugin/public'; +import { useFetcher } from '@kbn/observability-plugin/public'; +import { MonitorFields } from '../../../../../../common/runtime_types'; +import { syntheticsMonitorType } from '../../../../../../common/types/saved_objects'; + +export const useRecentlyViewedMonitors = () => { + const [recentlyViewed, setRecentlyViewed] = useLocalStorage( + 'xpack.synthetics.recentlyViewedMonitors', + [] + ); + const { monitorId } = useParams<{ monitorId: string }>(); + + const { savedObjects } = useKibana().services; + + useEffect(() => { + const newRecentlyViewed = [ + ...new Set([...(monitorId ? [monitorId] : []), ...(recentlyViewed ?? [])]), + ].slice(0, 5); + + if ( + newRecentlyViewed?.[0] !== recentlyViewed?.[0] || + newRecentlyViewed.length !== recentlyViewed?.length + ) { + setRecentlyViewed(newRecentlyViewed); + } + }, [monitorId, recentlyViewed, setRecentlyViewed]); + + const { data } = useFetcher(async () => { + const monitorsList = recentlyViewed ?? []; + + const { resolved_objects: monitorObjects } = await savedObjects!.client.bulkResolve( + monitorsList.map((monId) => ({ + type: syntheticsMonitorType, + id: monId, + })) + ); + + const missingMonitors = monitorObjects + .filter((mon) => mon.saved_object.error?.statusCode === 404) + .map((mon) => mon.saved_object.id); + + if (missingMonitors.length > 0) { + setRecentlyViewed(monitorsList.filter((monId) => !missingMonitors.includes(monId))); + } + + return monitorObjects + .filter( + ({ saved_object: monitor }) => Boolean(monitor.attributes) && monitor.id !== monitorId + ) + .map(({ saved_object: monitor }) => ({ + key: monitor.id, + label: (monitor.attributes as MonitorFields).name, + })); + }, [monitorId, recentlyViewed]); + + return useMemo(() => { + if ((data ?? []).length === 0) { + return []; + } + return [ + { key: 'recently_viewed', label: RECENTLY_VIEWED, isGroupLabel: true }, + ...(data ?? []), + ]; + }, [data]); +}; + +const RECENTLY_VIEWED = i18n.translate('xpack.synthetics.monitorSummary.recentlyViewed', { + defaultMessage: 'Recently viewed', +}); 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 3a9cfcf72812a..bc05d8fcc7a51 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 @@ -31,7 +31,7 @@ export const AvailabilitySparklines = () => { attributes={[ { seriesType: 'area', - time: { from: 'now-15m/m', to: 'now' }, + time: { from: 'now-30d/d', to: 'now' }, name: 'Monitor availability', dataType: 'synthetics', selectedMetricField: 'monitor_availability', diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_summary/duration_sparklines.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_summary/duration_sparklines.tsx new file mode 100644 index 0000000000000..f388decd14ddb --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_summary/duration_sparklines.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 { 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'; + +export const DurationSparklines = () => { + const { + services: { + observability: { ExploratoryViewEmbeddable }, + }, + } = useKibana(); + const { monitorId } = useParams<{ monitorId: string }>(); + + const theme = useTheme(); + + return ( + <> + + + ); +}; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_summary/monitor_errors_count.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_summary/monitor_errors_count.tsx new file mode 100644 index 0000000000000..9c5bf090607c9 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_summary/monitor_errors_count.tsx @@ -0,0 +1,39 @@ +/* + * 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 { useKibana } from '@kbn/kibana-react-plugin/public'; +import React from 'react'; +import { ReportTypes } from '@kbn/observability-plugin/public'; +import { useParams } from 'react-router-dom'; +import { ClientPluginsStart } from '../../../../../plugin'; + +export const MonitorErrorsCount = () => { + const { observability } = useKibana().services; + + const { ExploratoryViewEmbeddable } = observability; + + const { monitorId } = useParams<{ monitorId: string }>(); + + return ( + + ); +}; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_summary/monitor_summary.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_summary/monitor_summary.tsx index 0349b3e96cea1..6d4dd6018acaf 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_summary/monitor_summary.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_summary/monitor_summary.tsx @@ -17,6 +17,7 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; +import { DurationSparklines } from './duration_sparklines'; import { MonitorDurationTrend } from './duration_trend'; import { StepDurationPanel } from './step_duration_panel'; import { AvailabilityPanel } from './availability_panel'; @@ -25,6 +26,7 @@ import { MonitorDetailsPanel } from './monitor_details_panel'; import { AvailabilitySparklines } from './availability_sparklines'; import { LastTestRun } from './last_test_run'; import { LastTenTestRuns } from './last_ten_test_runs'; +import { MonitorErrorsCount } from './monitor_errors_count'; export const MonitorSummary = () => { const { euiTheme } = useEuiTheme(); @@ -55,8 +57,13 @@ export const MonitorSummary = () => { - {/* TODO: Add duration metric sparkline*/} - {/* TODO: Add error metric and sparkline*/} + + + + + + + {/* TODO: Add error sparkline*/}
diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/run_test_manually.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/run_test_manually.tsx index 7ff4754fc9001..475436d6577db 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/run_test_manually.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/run_test_manually.tsx @@ -11,7 +11,7 @@ import { i18n } from '@kbn/i18n'; export const RunTestManually = () => { return ( - + {RUN_TEST_LABEL} ); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/routes.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/routes.tsx index 3c1081f9f1f04..92ec0afce43ff 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/routes.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/routes.tsx @@ -7,17 +7,24 @@ import { EuiThemeComputed } from '@elastic/eui/src/services/theme/types'; import React, { FC, useEffect } from 'react'; -import { EuiFlexGroup, EuiFlexItem, EuiLink, useEuiTheme } from '@elastic/eui'; -import { Route, Switch, useHistory } from 'react-router-dom'; +import { + EuiFlexGroup, + EuiFlexItem, + EuiIcon, + EuiLink, + EuiPageHeaderProps, + useEuiTheme, +} from '@elastic/eui'; +import { Route, Switch, useHistory, useRouteMatch } from 'react-router-dom'; import { OutPortal } from 'react-reverse-portal'; import { FormattedMessage } from '@kbn/i18n-react'; import { i18n } from '@kbn/i18n'; import { APP_WRAPPER_CLASS } from '@kbn/core/public'; +import { useKibana } from '@kbn/kibana-react-plugin/public'; import { useInspectorContext } from '@kbn/observability-plugin/public'; import type { LazyObservabilityPageTemplateProps } from '@kbn/observability-plugin/public'; import { MonitorAddPage } from './components/monitor_add_edit/monitor_add_page'; import { MonitorEditPage } from './components/monitor_add_edit/monitor_edit_page'; -import { MonitorDetailsPageHeader } from './components/monitor_details/monitor_details_page_header'; import { MonitorDetailsPageTitle } from './components/monitor_details/monitor_details_page_title'; import { MonitorDetailsPage } from './components/monitor_details/monitor_details_page'; import { GettingStartedPage } from './components/getting_started/getting_started_page'; @@ -31,15 +38,25 @@ import { MonitorDetailsLinkPortalNode, } from './components/monitor_add_edit/portals'; import { + GETTING_STARTED_ROUTE, + MONITORS_ROUTE, MONITOR_ADD_ROUTE, MONITOR_EDIT_ROUTE, - MONITORS_ROUTE, - OVERVIEW_ROUTE, - GETTING_STARTED_ROUTE, + MONITOR_ERRORS_ROUTE, + MONITOR_HISTORY_ROUTE, MONITOR_ROUTE, + OVERVIEW_ROUTE, } from '../../../common/constants'; +import { PLUGIN } from '../../../common/constants/plugin'; import { MonitorPage } from './components/monitors_page/monitor_page'; import { apiService } from '../../utils/api_service'; +import { RunTestManually } from './components/monitor_details/run_test_manually'; +import { MonitorDetailsStatus } from './components/monitor_details/monitor_details_status'; +import { MonitorDetailsLocation } from './components/monitor_details/monitor_details_location'; +import { MonitorDetailsLastRun } from './components/monitor_details/monitor_details_last_run'; +import { MonitorSummary } from './components/monitor_details/monitor_summary/monitor_summary'; +import { MonitorHistory } from './components/monitor_details/monitor_history/monitor_history'; +import { MonitorErrors } from './components/monitor_details/monitor_errors/monitor_errors'; type RouteProps = LazyObservabilityPageTemplateProps & { path: string; @@ -61,7 +78,8 @@ export const MONITOR_MANAGEMENT_LABEL = i18n.translate( const getRoutes = ( euiTheme: EuiThemeComputed, - history: ReturnType + history: ReturnType, + syntheticsPath: string ): RouteProps[] => { return [ { @@ -83,13 +101,41 @@ const getRoutes = ( values: { baseTitle }, }), path: MONITOR_ROUTE, - component: () => , + component: () => ( + + + + ), dataTestSubj: 'syntheticsMonitorDetailsPage', - pageHeader: { - children: , - pageTitle: , - // rightSideItems: [], - }, + pageHeader: getMonitorSummaryHeader(history, syntheticsPath, 'summary'), + }, + { + title: i18n.translate('xpack.synthetics.monitorHistory.title', { + defaultMessage: 'Synthetics Monitor History | {baseTitle}', + values: { baseTitle }, + }), + path: MONITOR_HISTORY_ROUTE, + component: () => ( + + + + ), + dataTestSubj: 'syntheticsMonitorHistoryPage', + pageHeader: getMonitorSummaryHeader(history, syntheticsPath, 'history'), + }, + { + title: i18n.translate('xpack.synthetics.monitorErrors.title', { + defaultMessage: 'Synthetics Monitor Errors | {baseTitle}', + values: { baseTitle }, + }), + path: MONITOR_ERRORS_ROUTE, + component: () => ( + + + + ), + dataTestSubj: 'syntheticsMonitorHistoryPage', + pageHeader: getMonitorSummaryHeader(history, syntheticsPath, 'errors'), }, { title: i18n.translate('xpack.synthetics.overviewRoute.title', { @@ -130,10 +176,7 @@ const getRoutes = ( defaultMessage="Management" /> ), - onClick: () => - history.push({ - pathname: MONITORS_ROUTE, - }), + href: `${syntheticsPath}${MONITORS_ROUTE}`, }, ], }, @@ -162,10 +205,7 @@ const getRoutes = ( defaultMessage="Overview" /> ), - onClick: () => - history.push({ - pathname: OVERVIEW_ROUTE, - }), + href: `${syntheticsPath}${OVERVIEW_ROUTE}`, }, { label: ( @@ -246,6 +286,72 @@ const getRoutes = ( ]; }; +const getMonitorSummaryHeader = ( + history: ReturnType, + syntheticsPath: string, + selectedTab: 'summary' | 'history' | 'errors' +): EuiPageHeaderProps => { + // Not a component, but it doesn't matter. Hooks are just functions + const match = useRouteMatch<{ monitorId: string }>(MONITOR_ROUTE); // eslint-disable-line react-hooks/rules-of-hooks + + if (!match) { + return {}; + } + + const search = history.location.search; + const monitorId = match.params.monitorId; + + return { + pageTitle: , + breadcrumbs: [ + { + text: ( + <> + {' '} + + + ), + color: 'primary', + 'aria-current': false, + href: `${syntheticsPath}${MONITORS_ROUTE}`, + }, + ], + rightSideItems: [ + , + , + , + , + ], + tabs: [ + { + label: i18n.translate('xpack.synthetics.monitorSummaryTab.title', { + defaultMessage: 'Summary', + }), + isSelected: selectedTab === 'summary', + href: `${syntheticsPath}${MONITOR_ROUTE.replace(':monitorId?', monitorId)}${search}`, + }, + { + label: i18n.translate('xpack.synthetics.monitorHistoryTab.title', { + defaultMessage: 'History', + }), + isSelected: selectedTab === 'history', + href: `${syntheticsPath}${MONITOR_HISTORY_ROUTE.replace(':monitorId', monitorId)}${search}`, + }, + { + label: i18n.translate('xpack.synthetics.monitorErrorsTab.title', { + defaultMessage: 'Errors', + }), + prepend: , + isSelected: selectedTab === 'errors', + href: `${syntheticsPath}${MONITOR_ERRORS_ROUTE.replace(':monitorId', monitorId)}${search}`, + }, + ], + }; +}; + const RouteInit: React.FC> = ({ path, title }) => { useEffect(() => { document.title = title; @@ -254,10 +360,15 @@ const RouteInit: React.FC> = ({ path, title } }; export const PageRouter: FC = () => { + const { services } = useKibana(); const { addInspectorRequest } = useInspectorContext(); const { euiTheme } = useEuiTheme(); const history = useHistory(); - const routes = getRoutes(euiTheme, history); + const routes = getRoutes( + euiTheme, + history, + services.application!.getUrlForApp(PLUGIN.SYNTHETICS_PLUGIN_ID) + ); apiService.addInspectorRequest = addInspectorRequest; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/utils/testing/rtl_helpers.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/utils/testing/rtl_helpers.tsx index 1e0a277d2c654..55ae549a032b3 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/utils/testing/rtl_helpers.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/utils/testing/rtl_helpers.tsx @@ -226,6 +226,10 @@ export function WrappedHelper({ }: RenderRouterOptions & { children: ReactElement; useRealStore?: boolean }) { const testState: AppState = merge({}, mockState, state); + if (url) { + history = getHistoryFromUrl(url); + } + return ( diff --git a/x-pack/plugins/synthetics/server/routes/synthetics_service/test_now_monitor.ts b/x-pack/plugins/synthetics/server/routes/synthetics_service/test_now_monitor.ts index 82ce2ffdc5cce..0a2c3f599ff62 100644 --- a/x-pack/plugins/synthetics/server/routes/synthetics_service/test_now_monitor.ts +++ b/x-pack/plugins/synthetics/server/routes/synthetics_service/test_now_monitor.ts @@ -56,7 +56,7 @@ export const testNowMonitorRoute: SyntheticsRestApiRouteFactory = () => ({ const testRunId = uuidv4(); - const errors = await syntheticsService.triggerConfigs(request, [ + const errors = await syntheticsService.runOnceConfigs([ formatHeartbeatRequest({ // making it enabled, even if it's disabled in the UI monitor: { ...normalizedMonitor.attributes, enabled: true }, diff --git a/x-pack/plugins/synthetics/server/synthetics_service/get_api_key.ts b/x-pack/plugins/synthetics/server/synthetics_service/get_api_key.ts index e3794af2873c4..5984bcb3b8aca 100644 --- a/x-pack/plugins/synthetics/server/synthetics_service/get_api_key.ts +++ b/x-pack/plugins/synthetics/server/synthetics_service/get_api_key.ts @@ -30,6 +30,7 @@ export const serviceApiKeyPrivileges = { 'view_index_metadata', 'create_doc', 'auto_configure', + 'read', ] as SecurityIndexPrivilege[], }, ], diff --git a/x-pack/plugins/synthetics/server/synthetics_service/synthetics_service.test.ts b/x-pack/plugins/synthetics/server/synthetics_service/synthetics_service.test.ts index 5c935aba57dd1..472d9792a37bf 100644 --- a/x-pack/plugins/synthetics/server/synthetics_service/synthetics_service.test.ts +++ b/x-pack/plugins/synthetics/server/synthetics_service/synthetics_service.test.ts @@ -157,23 +157,6 @@ describe('SyntheticsService', () => { }); describe('pushConfigs', () => { - it('does not include the isEdit flag on normal push requests', async () => { - const { service, locations } = getMockedService(); - - (axios as jest.MockedFunction).mockResolvedValue({} as AxiosResponse); - - const payload = getFakePayload([locations[0]]); - - await service.pushConfigs([payload] as HeartbeatConfig[]); - - expect(axios).toHaveBeenCalledTimes(1); - expect(axios).toHaveBeenCalledWith( - expect.objectContaining({ - data: expect.objectContaining({ is_edit: false }), - }) - ); - }); - it('includes the isEdit flag on edit requests', async () => { const { service, locations } = getMockedService(); @@ -181,7 +164,7 @@ describe('SyntheticsService', () => { const payload = getFakePayload([locations[0]]); - await service.pushConfigs([payload] as HeartbeatConfig[], true); + await service.editConfig([payload] as HeartbeatConfig[]); expect(axios).toHaveBeenCalledTimes(1); expect(axios).toHaveBeenCalledWith( diff --git a/x-pack/plugins/synthetics/server/synthetics_service/synthetics_service.ts b/x-pack/plugins/synthetics/server/synthetics_service/synthetics_service.ts index c0f977758f6da..457d4e79e418e 100644 --- a/x-pack/plugins/synthetics/server/synthetics_service/synthetics_service.ts +++ b/x-pack/plugins/synthetics/server/synthetics_service/synthetics_service.ts @@ -8,13 +8,14 @@ /* eslint-disable max-classes-per-file */ import { SavedObject } from '@kbn/core/server'; -import { KibanaRequest, Logger } from '@kbn/core/server'; +import { Logger } from '@kbn/core/server'; import { ConcreteTaskInstance, TaskManagerSetupContract, TaskManagerStartContract, TaskInstance, } from '@kbn/task-manager-plugin/server'; +import { Subject } from 'rxjs'; import { sendErrorTelemetryEvents } from '../routes/telemetry/monitor_upgrade_sender'; import { UptimeServerSetup } from '../legacy_uptime/lib/adapters'; import { installSyntheticsIndexTemplates } from '../routes/synthetics_service/install_index_templates'; @@ -170,7 +171,7 @@ export class SyntheticsService { if (service.isAllowed) { service.setupIndexTemplates(); - service.syncErrors = await service.pushConfigs(); + await service.pushConfigs(); } } catch (e) { sendErrorTelemetryEvents(service.logger, service.server.telemetry, { @@ -306,65 +307,44 @@ export class SyntheticsService { } } - async pushConfigs(configs?: HeartbeatConfig[], isEdit?: boolean) { - const monitorConfigs = configs ?? (await this.getMonitorConfigs()); - const monitors = this.formatConfigs(monitorConfigs); - - if (monitors.length === 0) { - this.logger.debug('No monitor found which can be pushed to service.'); - return null; - } - - this.apiKey = await this.getApiKey(); - - if (!this.apiKey) { - return null; - } + async pushConfigs() { + const service = this; + const subject = new Subject(); - const data = { - monitors, - output: await this.getOutput(this.apiKey), - isEdit: !!isEdit, - }; + subject.subscribe(async (monitorConfigs) => { + const monitors = this.formatConfigs(monitorConfigs); - this.logger.debug(`${monitors.length} monitors will be pushed to synthetics service.`); + if (monitors.length === 0) { + this.logger.debug('No monitor found which can be pushed to service.'); + return null; + } - try { - this.syncErrors = await this.apiClient.put(data); - return this.syncErrors; - } catch (e) { - this.logger.error(e); - throw e; - } - } + this.apiKey = await this.getApiKey(); - async runOnceConfigs(configs?: HeartbeatConfig[]) { - const monitors = this.formatConfigs(configs || (await this.getMonitorConfigs())); - if (monitors.length === 0) { - return; - } + if (!this.apiKey) { + return null; + } - this.apiKey = await this.getApiKey(); + const data = { + monitors, + output: await this.getOutput(this.apiKey), + }; - if (!this.apiKey) { - return null; - } + this.logger.debug(`${monitors.length} monitors will be pushed to synthetics service.`); - const data = { - monitors, - output: await this.getOutput(this.apiKey), - }; + try { + service.syncErrors = await this.apiClient.put(data); + } catch (e) { + this.logger.error(e); + throw e; + } + }); - try { - return await this.apiClient.runOnce(data); - } catch (e) { - this.logger.error(e); - throw e; - } + await this.getMonitorConfigs(subject); } - async triggerConfigs(request?: KibanaRequest, configs?: HeartbeatConfig[]) { - const monitors = this.formatConfigs(configs || (await this.getMonitorConfigs())); + async runOnceConfigs(configs: HeartbeatConfig[]) { + const monitors = this.formatConfigs(configs); if (monitors.length === 0) { return; } @@ -401,81 +381,92 @@ export class SyntheticsService { }; const result = await this.apiClient.delete(data); if (this.syncErrors && this.syncErrors?.length > 0) { - this.syncErrors = await this.pushConfigs(); + await this.pushConfigs(); } return result; } async deleteAllConfigs() { - const configs = await this.getMonitorConfigs(); - return await this.deleteConfigs(configs); + const subject = new Subject(); + + subject.subscribe(async (monitors) => { + await this.deleteConfigs(monitors); + }); + + await this.getMonitorConfigs(subject); } - async getMonitorConfigs() { - const savedObjectsClient = this.server.savedObjectsClient; + async getMonitorConfigs(subject: Subject) { + const soClient = this.server.savedObjectsClient; const encryptedClient = this.server.encryptedSavedObjects.getClient(); - if (!savedObjectsClient?.find) { + if (!soClient?.find) { return [] as SyntheticsMonitorWithId[]; } - const { saved_objects: encryptedMonitors } = await savedObjectsClient.find({ + const finder = soClient.createPointInTimeFinder({ type: syntheticsMonitorType, + perPage: 500, namespaces: ['*'], - perPage: 10000, }); const start = performance.now(); - const monitors: Array> = ( - await Promise.all( - encryptedMonitors.map( - (monitor) => - new Promise((resolve) => { - encryptedClient - .getDecryptedAsInternalUser( - syntheticsMonitor.name, - monitor.id, - { - namespace: monitor.namespaces?.[0], - } - ) - .then((decryptedMonitor) => resolve(decryptedMonitor)) - .catch((e) => { - this.logger.error(e); - sendErrorTelemetryEvents(this.logger, this.server.telemetry, { - reason: 'Failed to decrypt monitor', - message: e?.message, - type: 'runTaskError', - code: e?.code, - status: e.status, - kibanaVersion: this.server.kibanaVersion, + for await (const result of finder.find()) { + const encryptedMonitors = result.saved_objects; + + const monitors: Array> = ( + await Promise.all( + encryptedMonitors.map( + (monitor) => + new Promise((resolve) => { + encryptedClient + .getDecryptedAsInternalUser( + syntheticsMonitor.name, + monitor.id, + { + namespace: monitor.namespaces?.[0], + } + ) + .then((decryptedMonitor) => resolve(decryptedMonitor)) + .catch((e) => { + this.logger.error(e); + sendErrorTelemetryEvents(this.logger, this.server.telemetry, { + reason: 'Failed to decrypt monitor', + message: e?.message, + type: 'runTaskError', + code: e?.code, + status: e.status, + kibanaVersion: this.server.kibanaVersion, + }); + resolve(null); }); - resolve(null); - }); - }) + }) + ) ) - ) - ).filter((monitor) => monitor !== null) as Array>; - - const end = performance.now(); - const duration = end - start; + ).filter((monitor) => monitor !== null) as Array>; - this.logger.debug(`Decrypted ${monitors.length} monitors. Took ${duration} milliseconds`, { - event: { - duration, - }, - monitors: monitors.length, - }); + const end = performance.now(); + const duration = end - start; - return (monitors ?? []).map((monitor) => { - const attributes = monitor.attributes as unknown as MonitorFields; - return formatHeartbeatRequest({ - monitor: normalizeSecrets(monitor).attributes, - monitorId: monitor.id, - customHeartbeatId: attributes[ConfigKey.CUSTOM_HEARTBEAT_ID], + this.logger.debug(`Decrypted ${monitors.length} monitors. Took ${duration} milliseconds`, { + event: { + duration, + }, + monitors: monitors.length, }); - }); + + subject.next( + (monitors ?? []).map((monitor) => { + const attributes = monitor.attributes as unknown as MonitorFields; + return formatHeartbeatRequest({ + monitor: normalizeSecrets(monitor).attributes, + monitorId: monitor.id, + customHeartbeatId: attributes[ConfigKey.CUSTOM_HEARTBEAT_ID], + }); + }) + ); + } } formatConfigs(configs: SyntheticsMonitorWithId[]) { diff --git a/x-pack/plugins/threat_intelligence/public/common/mocks/mock_indicators_filters_context.tsx b/x-pack/plugins/threat_intelligence/public/common/mocks/mock_indicators_filters_context.tsx index 0be85bea8ccf1..b93a67bd0a5c2 100644 --- a/x-pack/plugins/threat_intelligence/public/common/mocks/mock_indicators_filters_context.tsx +++ b/x-pack/plugins/threat_intelligence/public/common/mocks/mock_indicators_filters_context.tsx @@ -6,7 +6,7 @@ */ import { FilterManager } from '@kbn/data-plugin/public'; -import { IndicatorsFiltersContextValue } from '../../modules/indicators/containers/indicators_filters/context'; +import { IndicatorsFiltersContextValue } from '../../modules/indicators'; export const mockTimeRange = { from: '2022-10-03T07:48:31.498Z', to: '2022-10-03T07:48:31.498Z' }; diff --git a/x-pack/plugins/threat_intelligence/public/common/mocks/story_providers.tsx b/x-pack/plugins/threat_intelligence/public/common/mocks/story_providers.tsx index 7cea653c45e5f..f1f5e3c215eb2 100644 --- a/x-pack/plugins/threat_intelligence/public/common/mocks/story_providers.tsx +++ b/x-pack/plugins/threat_intelligence/public/common/mocks/story_providers.tsx @@ -16,7 +16,7 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { mockIndicatorsFiltersContext } from './mock_indicators_filters_context'; import { SecuritySolutionContext } from '../../containers/security_solution_context'; import { getSecuritySolutionContextMock } from './mock_security_context'; -import { IndicatorsFiltersContext } from '../../modules/indicators/containers/indicators_filters/context'; +import { IndicatorsFiltersContext } from '../../modules/indicators'; import { FieldTypesContext } from '../../containers/field_types_provider'; import { generateFieldTypeMap } from './mock_field_type_map'; import { mockUiSettingsService } from './mock_kibana_ui_settings_service'; diff --git a/x-pack/plugins/threat_intelligence/public/common/mocks/test_providers.tsx b/x-pack/plugins/threat_intelligence/public/common/mocks/test_providers.tsx index c41f8972fd605..38eca1caad028 100644 --- a/x-pack/plugins/threat_intelligence/public/common/mocks/test_providers.tsx +++ b/x-pack/plugins/threat_intelligence/public/common/mocks/test_providers.tsx @@ -24,7 +24,7 @@ import { SecuritySolutionPluginContext } from '../../types'; import { getSecuritySolutionContextMock } from './mock_security_context'; import { mockUiSetting } from './mock_kibana_ui_settings_service'; import { SecuritySolutionContext } from '../../containers/security_solution_context'; -import { IndicatorsFiltersContext } from '../../modules/indicators/containers/indicators_filters/context'; +import { IndicatorsFiltersContext } from '../../modules/indicators'; import { mockIndicatorsFiltersContext } from './mock_indicators_filters_context'; import { FieldTypesContext } from '../../containers/field_types_provider'; import { generateFieldTypeMap } from './mock_field_type_map'; diff --git a/x-pack/plugins/threat_intelligence/public/containers/field_types_provider.tsx b/x-pack/plugins/threat_intelligence/public/containers/field_types_provider.tsx index 050ecb4a3fe10..109ad335d30a8 100644 --- a/x-pack/plugins/threat_intelligence/public/containers/field_types_provider.tsx +++ b/x-pack/plugins/threat_intelligence/public/containers/field_types_provider.tsx @@ -5,9 +5,8 @@ * 2.0. */ -import React, { createContext, useMemo } from 'react'; -import { FC } from 'react'; -import { useSourcererDataView } from '../modules/indicators/hooks/use_sourcerer_data_view'; +import React, { createContext, FC, useMemo } from 'react'; +import { useSourcererDataView } from '../modules/indicators'; export type FieldTypesContextValue = Record; diff --git a/x-pack/plugins/threat_intelligence/public/containers/integrations_guard/integrations_guard.test.tsx b/x-pack/plugins/threat_intelligence/public/containers/integrations_guard/integrations_guard.test.tsx index fe3c88d6479e1..099559f8651b9 100644 --- a/x-pack/plugins/threat_intelligence/public/containers/integrations_guard/integrations_guard.test.tsx +++ b/x-pack/plugins/threat_intelligence/public/containers/integrations_guard/integrations_guard.test.tsx @@ -11,9 +11,9 @@ import { IntegrationsGuard } from '.'; import { TestProvidersComponent } from '../../common/mocks/test_providers'; import { useTIDocumentationLink } from '../../hooks/use_documentation_link'; import { useIntegrationsPageLink } from '../../hooks/use_integrations_page_link'; -import { useIndicatorsTotalCount } from '../../modules/indicators/hooks/use_indicators_total_count'; +import { useIndicatorsTotalCount } from '../../modules/indicators'; -jest.mock('../../modules/indicators/hooks/use_indicators_total_count'); +jest.mock('../../modules/indicators/hooks/use_total_count'); jest.mock('../../hooks/use_integrations_page_link'); jest.mock('../../hooks/use_documentation_link'); diff --git a/x-pack/plugins/threat_intelligence/public/containers/integrations_guard/integrations_guard.tsx b/x-pack/plugins/threat_intelligence/public/containers/integrations_guard/integrations_guard.tsx index 82a8d05470da2..eb639d6c50f75 100644 --- a/x-pack/plugins/threat_intelligence/public/containers/integrations_guard/integrations_guard.tsx +++ b/x-pack/plugins/threat_intelligence/public/containers/integrations_guard/integrations_guard.tsx @@ -6,10 +6,9 @@ */ import { EuiLoadingLogo } from '@elastic/eui'; -import React from 'react'; -import { FC } from 'react'; +import React, { FC } from 'react'; import { EmptyPage } from '../../modules/empty_page'; -import { useIndicatorsTotalCount } from '../../modules/indicators/hooks/use_indicators_total_count'; +import { useIndicatorsTotalCount } from '../../modules/indicators'; import { SecuritySolutionPluginTemplateWrapper } from '../security_solution_plugin_template_wrapper'; /** diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/barchart/legend_action/legend_action.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/barchart/legend_action/legend_action.tsx index b63e33fbe51e8..9572e41846048 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/barchart/legend_action/legend_action.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/barchart/legend_action/legend_action.tsx @@ -9,9 +9,8 @@ import React, { useState, VFC } from 'react'; import { EuiButtonIcon, EuiContextMenuPanel, EuiPopover, EuiToolTip } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { CopyToClipboardContextMenu } from '../../copy_to_clipboard'; -import { FilterInContextMenu } from '../../../../query_bar/components/filter_in'; -import { FilterOutContextMenu } from '../../../../query_bar/components/filter_out'; -import { AddToTimelineContextMenu } from '../../../../timeline/components/add_to_timeline'; +import { FilterInContextMenu, FilterOutContextMenu } from '../../../../query_bar'; +import { AddToTimelineContextMenu } from '../../../../timeline'; export const POPOVER_BUTTON_TEST_ID = 'tiBarchartPopoverButton'; export const TIMELINE_BUTTON_TEST_ID = 'tiBarchartTimelineButton'; diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_field_label/indicator_field_label.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/field_label/field_label.tsx similarity index 100% rename from x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_field_label/indicator_field_label.tsx rename to x-pack/plugins/threat_intelligence/public/modules/indicators/components/field_label/field_label.tsx diff --git a/x-pack/plugins/threat_intelligence/public/modules/query_bar/hooks/use_filters/index.ts b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/field_label/index.ts similarity index 89% rename from x-pack/plugins/threat_intelligence/public/modules/query_bar/hooks/use_filters/index.ts rename to x-pack/plugins/threat_intelligence/public/modules/indicators/components/field_label/index.ts index d24069f8a04ab..20bfa1be1286b 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/query_bar/hooks/use_filters/index.ts +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/field_label/index.ts @@ -5,4 +5,4 @@ * 2.0. */ -export * from './use_filters'; +export * from './field_label'; diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_field_value/__snapshots__/indicator_field.test.tsx.snap b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/field_value/__snapshots__/field.test.tsx.snap similarity index 100% rename from x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_field_value/__snapshots__/indicator_field.test.tsx.snap rename to x-pack/plugins/threat_intelligence/public/modules/indicators/components/field_value/__snapshots__/field.test.tsx.snap diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_field_value/indicator_field.stories.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/field_value/field.stories.tsx similarity index 94% rename from x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_field_value/indicator_field.stories.tsx rename to x-pack/plugins/threat_intelligence/public/modules/indicators/components/field_value/field.stories.tsx index 9548691e49ec5..da56583404a15 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_field_value/indicator_field.stories.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/field_value/field.stories.tsx @@ -8,7 +8,7 @@ import React from 'react'; import { StoryProvidersComponent } from '../../../../common/mocks/story_providers'; import { generateMockIndicator } from '../../../../../common/types/indicator'; -import { IndicatorFieldValue } from './indicator_field_value'; +import { IndicatorFieldValue } from '.'; export default { component: IndicatorFieldValue, diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_field_value/indicator_field.test.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/field_value/field.test.tsx similarity index 95% rename from x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_field_value/indicator_field.test.tsx rename to x-pack/plugins/threat_intelligence/public/modules/indicators/components/field_value/field.test.tsx index c695a2c4ebe84..3142b6cd68dac 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_field_value/indicator_field.test.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/field_value/field.test.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { render } from '@testing-library/react'; -import { IndicatorFieldValue } from './indicator_field_value'; +import { IndicatorFieldValue } from '.'; import { generateMockIndicator } from '../../../../../common/types/indicator'; import { EMPTY_VALUE } from '../../../../../common/constants'; import { TestProvidersComponent } from '../../../../common/mocks/test_providers'; diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_field_value/indicator_field_value.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/field_value/field_value.tsx similarity index 96% rename from x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_field_value/indicator_field_value.tsx rename to x-pack/plugins/threat_intelligence/public/modules/indicators/components/field_value/field_value.tsx index 55dfa883c30ad..699ccee505562 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_field_value/indicator_field_value.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/field_value/field_value.tsx @@ -10,7 +10,7 @@ import { useFieldTypes } from '../../../../hooks/use_field_types'; import { EMPTY_VALUE } from '../../../../../common/constants'; import { Indicator, RawIndicatorFieldId } from '../../../../../common/types/indicator'; import { DateFormatter } from '../../../../components/date_formatter'; -import { unwrapValue } from '../../utils/unwrap_value'; +import { unwrapValue } from '../../utils'; export interface IndicatorFieldValueProps { /** diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_field_value/index.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/field_value/index.ts similarity index 86% rename from x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_field_value/index.tsx rename to x-pack/plugins/threat_intelligence/public/modules/indicators/components/field_value/index.ts index 724caf3c75243..377ac4a266b0b 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_field_value/index.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/field_value/index.ts @@ -5,4 +5,4 @@ * 2.0. */ -export * from './indicator_field_value'; +export * from './field_value'; diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/flyout/fields_table/fields_table.stories.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/flyout/fields_table/fields_table.stories.tsx index eb0ed8fb045ed..80bd24d59adc9 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/flyout/fields_table/fields_table.stories.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/flyout/fields_table/fields_table.stories.tsx @@ -10,7 +10,7 @@ import { mockIndicatorsFiltersContext } from '../../../../../common/mocks/mock_i import { IndicatorFieldsTable } from '.'; import { generateMockIndicator } from '../../../../../../common/types/indicator'; import { StoryProvidersComponent } from '../../../../../common/mocks/story_providers'; -import { IndicatorsFiltersContext } from '../../../containers/indicators_filters'; +import { IndicatorsFiltersContext } from '../../../containers/filters'; export default { component: IndicatorFieldsTable, diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/flyout/fields_table/fields_table.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/flyout/fields_table/fields_table.tsx index eb5b2d0ca2589..3fe1f62599059 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/flyout/fields_table/fields_table.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/flyout/fields_table/fields_table.tsx @@ -9,7 +9,7 @@ import { EuiBasicTableColumn, EuiInMemoryTable, EuiInMemoryTableProps } from '@e import { FormattedMessage } from '@kbn/i18n-react'; import React, { useMemo, VFC } from 'react'; import { Indicator } from '../../../../../../common/types/indicator'; -import { IndicatorFieldValue } from '../../indicator_field_value'; +import { IndicatorFieldValue } from '../../field_value'; import { IndicatorValueActions } from '../indicator_value_actions'; export interface IndicatorFieldsTableProps { diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/flyout/flyout.stories.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/flyout/flyout.stories.tsx index 69236e778178b..88f6762aab0d4 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/flyout/flyout.stories.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/flyout/flyout.stories.tsx @@ -14,7 +14,7 @@ import { mockUiSettingsService } from '../../../../common/mocks/mock_kibana_ui_s import { mockKibanaTimelinesService } from '../../../../common/mocks/mock_kibana_timelines_service'; import { generateMockIndicator, Indicator } from '../../../../../common/types/indicator'; import { IndicatorsFlyout } from '.'; -import { IndicatorsFiltersContext } from '../../containers/indicators_filters'; +import { IndicatorsFiltersContext } from '../../containers/filters'; export default { component: IndicatorsFlyout, diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/flyout/flyout.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/flyout/flyout.tsx index 11102df797017..485ba92f61932 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/flyout/flyout.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/flyout/flyout.tsx @@ -21,12 +21,12 @@ import { useGeneratedHtmlId, } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; -import { InvestigateInTimelineButton } from '../../../timeline/components/investigate_in_timeline'; +import { InvestigateInTimelineButton } from '../../../timeline'; import { DateFormatter } from '../../../../components/date_formatter/date_formatter'; import { Indicator, RawIndicatorFieldId } from '../../../../../common/types/indicator'; import { IndicatorsFlyoutJson } from './json_tab'; import { IndicatorsFlyoutTable } from './table_tab'; -import { unwrapValue } from '../../utils/unwrap_value'; +import { unwrapValue } from '../../utils'; import { IndicatorsFlyoutOverview } from './overview_tab'; export const TITLE_TEST_ID = 'tiIndicatorFlyoutTitle'; diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/flyout/indicator_value_actions/indicator_value_actions.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/flyout/indicator_value_actions/indicator_value_actions.tsx index 473bc5d0088f7..4d4f1d94d84e5 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/flyout/indicator_value_actions/indicator_value_actions.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/flyout/indicator_value_actions/indicator_value_actions.tsx @@ -15,10 +15,9 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { Indicator } from '../../../../../../common/types/indicator'; -import { FilterInButtonIcon } from '../../../../query_bar/components/filter_in'; -import { FilterOutButtonIcon } from '../../../../query_bar/components/filter_out'; -import { AddToTimelineContextMenu } from '../../../../timeline/components/add_to_timeline'; -import { fieldAndValueValid, getIndicatorFieldAndValue } from '../../../utils/field_value'; +import { FilterInButtonIcon, FilterOutButtonIcon } from '../../../../query_bar'; +import { AddToTimelineContextMenu } from '../../../../timeline'; +import { fieldAndValueValid, getIndicatorFieldAndValue } from '../../../utils'; import { CopyToClipboardContextMenu } from '../../copy_to_clipboard'; export const TIMELINE_BUTTON_TEST_ID = 'TimelineButton'; diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/flyout/overview_tab/block/block.stories.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/flyout/overview_tab/block/block.stories.tsx index e30d352c2644f..0ae9c8b962d9a 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/flyout/overview_tab/block/block.stories.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/flyout/overview_tab/block/block.stories.tsx @@ -6,7 +6,7 @@ */ import React from 'react'; -import { IndicatorsFiltersContext } from '../../../../containers/indicators_filters'; +import { IndicatorsFiltersContext } from '../../../../containers/filters'; import { StoryProvidersComponent } from '../../../../../../common/mocks/story_providers'; import { generateMockIndicator } from '../../../../../../../common/types/indicator'; import { IndicatorBlock } from '.'; diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/flyout/overview_tab/block/block.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/flyout/overview_tab/block/block.tsx index 0866edde505bf..3baa182530b86 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/flyout/overview_tab/block/block.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/flyout/overview_tab/block/block.tsx @@ -9,8 +9,8 @@ import { EuiPanel, EuiSpacer, EuiText } from '@elastic/eui'; import React, { VFC } from 'react'; import { css, euiStyled } from '@kbn/kibana-react-plugin/common'; import { Indicator } from '../../../../../../../common/types/indicator'; -import { IndicatorFieldValue } from '../../../indicator_field_value'; -import { IndicatorFieldLabel } from '../../../indicator_field_label'; +import { IndicatorFieldValue } from '../../../field_value'; +import { IndicatorFieldLabel } from '../../../field_label'; import { IndicatorValueActions } from '../../indicator_value_actions'; /** diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/flyout/overview_tab/highlighted_values_table/highlighted_values_table.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/flyout/overview_tab/highlighted_values_table/highlighted_values_table.tsx index 7ccbbdf2f1c99..5c60ed4684d9b 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/flyout/overview_tab/highlighted_values_table/highlighted_values_table.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/flyout/overview_tab/highlighted_values_table/highlighted_values_table.tsx @@ -7,7 +7,7 @@ import React, { useMemo, VFC } from 'react'; import { Indicator, RawIndicatorFieldId } from '../../../../../../../common/types/indicator'; -import { unwrapValue } from '../../../../utils/unwrap_value'; +import { unwrapValue } from '../../../../utils'; import { IndicatorFieldsTable } from '../../fields_table'; /** diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/flyout/overview_tab/overview_tab.stories.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/flyout/overview_tab/overview_tab.stories.tsx index 005edd9c4201d..4c74ea25330d7 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/flyout/overview_tab/overview_tab.stories.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/flyout/overview_tab/overview_tab.stories.tsx @@ -10,7 +10,7 @@ import { Story } from '@storybook/react'; import { StoryProvidersComponent } from '../../../../../common/mocks/story_providers'; import { generateMockIndicator, Indicator } from '../../../../../../common/types/indicator'; import { IndicatorsFlyoutOverview } from '.'; -import { IndicatorsFiltersContext } from '../../../containers/indicators_filters'; +import { IndicatorsFiltersContext } from '../../../containers/filters'; export default { component: IndicatorsFlyoutOverview, diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/flyout/overview_tab/overview_tab.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/flyout/overview_tab/overview_tab.tsx index 7abbc1508fb58..8dc7f6a466574 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/flyout/overview_tab/overview_tab.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/flyout/overview_tab/overview_tab.tsx @@ -18,7 +18,7 @@ import { FormattedMessage } from '@kbn/i18n-react'; import React, { useMemo, VFC } from 'react'; import { EMPTY_VALUE } from '../../../../../../common/constants'; import { Indicator, RawIndicatorFieldId } from '../../../../../../common/types/indicator'; -import { unwrapValue } from '../../../utils/unwrap_value'; +import { unwrapValue } from '../../../utils'; import { IndicatorEmptyPrompt } from '../empty_prompt'; import { IndicatorBlock } from './block'; import { HighlightedValuesTable } from './highlighted_values_table'; diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/flyout/table_tab/table_tab.stories.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/flyout/table_tab/table_tab.stories.tsx index 60808a46356a8..1842d52171db3 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/flyout/table_tab/table_tab.stories.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/flyout/table_tab/table_tab.stories.tsx @@ -14,7 +14,7 @@ import { mockUiSettingsService } from '../../../../../common/mocks/mock_kibana_u import { mockKibanaTimelinesService } from '../../../../../common/mocks/mock_kibana_timelines_service'; import { generateMockIndicator, Indicator } from '../../../../../../common/types/indicator'; import { IndicatorsFlyoutTable } from '.'; -import { IndicatorsFiltersContext } from '../../../containers/indicators_filters'; +import { IndicatorsFiltersContext } from '../../../containers/filters'; export default { component: IndicatorsFlyoutTable, diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/flyout/table_tab/table_tab.test.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/flyout/table_tab/table_tab.test.tsx index 8503bcdace2cc..aae9aa41cbf2f 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/flyout/table_tab/table_tab.test.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/flyout/table_tab/table_tab.test.tsx @@ -14,7 +14,7 @@ import { RawIndicatorFieldId, } from '../../../../../../common/types/indicator'; import { IndicatorsFlyoutTable, TABLE_TEST_ID } from '.'; -import { unwrapValue } from '../../../utils/unwrap_value'; +import { unwrapValue } from '../../../utils'; import { EMPTY_PROMPT_TEST_ID } from '../empty_prompt'; const mockIndicator: Indicator = generateMockIndicator(); diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/table/components/actions_row_cell.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/table/components/actions_row_cell.tsx index 34a4d3cfee753..e8a58f2797669 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/table/components/actions_row_cell.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/table/components/actions_row_cell.tsx @@ -7,7 +7,7 @@ import React, { useContext, VFC } from 'react'; import { EuiFlexGroup } from '@elastic/eui'; -import { InvestigateInTimelineButtonIcon } from '../../../../timeline/components/investigate_in_timeline'; +import { InvestigateInTimelineButtonIcon } from '../../../../timeline'; import { Indicator } from '../../../../../../common/types/indicator'; import { OpenIndicatorFlyoutButton } from './open_flyout_button'; import { IndicatorsTableContext } from '../contexts'; diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/table/components/cell_actions.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/table/components/cell_actions.tsx index baed5eda31478..2f606df1a8f12 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/table/components/cell_actions.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/table/components/cell_actions.tsx @@ -8,11 +8,10 @@ import React, { VFC } from 'react'; import { EuiDataGridColumnCellActionProps } from '@elastic/eui/src/components/datagrid/data_grid_types'; import { Indicator } from '../../../../../../common/types/indicator'; -import { AddToTimelineCellAction } from '../../../../timeline/components/add_to_timeline'; -import { FilterInCellAction } from '../../../../query_bar/components/filter_in'; -import { FilterOutCellAction } from '../../../../query_bar/components/filter_out'; -import { fieldAndValueValid, getIndicatorFieldAndValue } from '../../../utils/field_value'; -import type { Pagination } from '../../../services/fetch_indicators'; +import { AddToTimelineCellAction } from '../../../../timeline'; +import { FilterInCellAction, FilterOutCellAction } from '../../../../query_bar'; +import { fieldAndValueValid, getIndicatorFieldAndValue } from '../../../utils'; +import type { Pagination } from '../../../services'; export const CELL_TIMELINE_BUTTON_TEST_ID = 'tiIndicatorsTableCellTimelineButton'; export const CELL_FILTER_IN_BUTTON_TEST_ID = 'tiIndicatorsTableCellFilterInButton'; diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/table/components/cell_popover_renderer.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/table/components/cell_popover_renderer.tsx index f86c3b5b35df8..eba86eb4e8c35 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/table/components/cell_popover_renderer.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/table/components/cell_popover_renderer.tsx @@ -13,9 +13,8 @@ import { } from '@elastic/eui'; import React from 'react'; import { CopyToClipboardButtonEmpty } from '../../copy_to_clipboard/copy_to_clipboard'; -import { FilterInButtonEmpty } from '../../../../query_bar/components/filter_in'; -import { FilterOutButtonEmpty } from '../../../../query_bar/components/filter_out'; -import { AddToTimelineButtonEmpty } from '../../../../timeline/components/add_to_timeline'; +import { FilterInButtonEmpty, FilterOutButtonEmpty } from '../../../../query_bar'; +import { AddToTimelineButtonEmpty } from '../../../../timeline'; import { fieldAndValueValid, getIndicatorFieldAndValue } from '../../../utils/field_value'; import { Indicator } from '../../../../../../common/types/indicator'; import { Pagination } from '../../../services/fetch_indicators'; diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/table/components/cell_renderer.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/table/components/cell_renderer.tsx index 97c37c1598ccd..d4b52a0c82af6 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/table/components/cell_renderer.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/table/components/cell_renderer.tsx @@ -10,7 +10,7 @@ import React, { useContext, useEffect } from 'react'; import { euiDarkVars as themeDark, euiLightVars as themeLight } from '@kbn/ui-theme'; import { useKibana } from '../../../../../hooks/use_kibana'; import { Indicator } from '../../../../../../common/types/indicator'; -import { IndicatorFieldValue } from '../../indicator_field_value'; +import { IndicatorFieldValue } from '../../field_value'; import { IndicatorsTableContext } from '../contexts'; import { ActionsRowCell } from '.'; diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/table/hooks/use_column_settings.ts b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/table/hooks/use_column_settings.ts index ff61c9d525616..05c58ac4b2fcf 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/table/hooks/use_column_settings.ts +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/table/hooks/use_column_settings.ts @@ -10,7 +10,7 @@ import { useCallback, useEffect, useMemo, useState } from 'react'; import negate from 'lodash/negate'; import { RawIndicatorFieldId } from '../../../../../../common/types/indicator'; import { useKibana } from '../../../../../hooks/use_kibana'; -import { translateFieldLabel } from '../../indicator_field_label'; +import { translateFieldLabel } from '../../field_label'; export const DEFAULT_COLUMNS: EuiDataGridColumn[] = [ RawIndicatorFieldId.TimeStamp, diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/table/table.stories.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/table/table.stories.tsx index f11977145d7a4..4822d403e3f4b 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/table/table.stories.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/table/table.stories.tsx @@ -11,7 +11,7 @@ import { mockIndicatorsFiltersContext } from '../../../../common/mocks/mock_indi import { StoryProvidersComponent } from '../../../../common/mocks/story_providers'; import { generateMockIndicator, Indicator } from '../../../../../common/types/indicator'; import { IndicatorsTable } from '.'; -import { IndicatorsFiltersContext } from '../../containers/indicators_filters/context'; +import { IndicatorsFiltersContext } from '../../containers/filters/context'; import { DEFAULT_COLUMNS } from './hooks'; export default { diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/table/table.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/table/table.tsx index 78fe1aaab2ea0..e5c4b7c205d58 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/table/table.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/table/table.tsx @@ -27,8 +27,8 @@ import { IndicatorsTableContext, IndicatorsTableContextValue } from './contexts' import { IndicatorsFlyout } from '../flyout'; import { ColumnSettingsValue, useToolbarOptions } from './hooks'; import { useFieldTypes } from '../../../../hooks/use_field_types'; -import { getFieldSchema } from '../../utils/get_field_schema'; -import { Pagination } from '../../services/fetch_indicators'; +import { getFieldSchema } from '../../utils'; +import { Pagination } from '../../services'; export interface IndicatorsTableProps { indicators: Indicator[]; diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/containers/indicators_filters/context.ts b/x-pack/plugins/threat_intelligence/public/modules/indicators/containers/filters/context.ts similarity index 100% rename from x-pack/plugins/threat_intelligence/public/modules/indicators/containers/indicators_filters/context.ts rename to x-pack/plugins/threat_intelligence/public/modules/indicators/containers/filters/context.ts diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/containers/indicators_filters/indicators_filters.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/containers/filters/filters.tsx similarity index 98% rename from x-pack/plugins/threat_intelligence/public/modules/indicators/containers/indicators_filters/indicators_filters.tsx rename to x-pack/plugins/threat_intelligence/public/modules/indicators/containers/filters/filters.tsx index 2253b1c548968..8d4b986ffd509 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/containers/indicators_filters/indicators_filters.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/containers/filters/filters.tsx @@ -8,7 +8,7 @@ import React, { FC, useMemo } from 'react'; import { useKibana } from '../../../../hooks/use_kibana'; import { useSecurityContext } from '../../../../hooks/use_security_context'; -import { IndicatorsFiltersContext, IndicatorsFiltersContextValue } from './context'; +import { IndicatorsFiltersContext, IndicatorsFiltersContextValue } from '.'; /** * Container used to wrap components and share the {@link FilterManager} through React context. diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/containers/indicators_filters/index.ts b/x-pack/plugins/threat_intelligence/public/modules/indicators/containers/filters/index.ts similarity index 87% rename from x-pack/plugins/threat_intelligence/public/modules/indicators/containers/indicators_filters/index.ts rename to x-pack/plugins/threat_intelligence/public/modules/indicators/containers/filters/index.ts index 4ef23e3e95001..2eafda804a6c1 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/containers/indicators_filters/index.ts +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/containers/filters/index.ts @@ -5,6 +5,5 @@ * 2.0. */ -export * from './indicators_filters'; - +export * from './filters'; export * from './context'; diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/hooks/index.ts b/x-pack/plugins/threat_intelligence/public/modules/indicators/hooks/index.ts index 23461fc809957..124171ce2d0a6 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/hooks/index.ts +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/hooks/index.ts @@ -6,6 +6,7 @@ */ export * from './use_aggregated_indicators'; -export * from './use_indicators_filters_context'; -export * from './use_indicators_total_count'; +export * from './use_filters_context'; +export * from './use_indicators'; export * from './use_sourcerer_data_view'; +export * from './use_total_count'; diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/hooks/use_indicators_filters_context.ts b/x-pack/plugins/threat_intelligence/public/modules/indicators/hooks/use_filters_context.ts similarity index 93% rename from x-pack/plugins/threat_intelligence/public/modules/indicators/hooks/use_indicators_filters_context.ts rename to x-pack/plugins/threat_intelligence/public/modules/indicators/hooks/use_filters_context.ts index e4c7c48d03d1b..8fec9d03852b2 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/hooks/use_indicators_filters_context.ts +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/hooks/use_filters_context.ts @@ -9,7 +9,7 @@ import { useContext } from 'react'; import { IndicatorsFiltersContext, IndicatorsFiltersContextValue, -} from '../containers/indicators_filters/context'; +} from '../containers/filters/context'; /** * Hook to retrieve {@link IndicatorsFiltersContext} (contains FilterManager) diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/hooks/use_indicators.test.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/hooks/use_indicators.test.tsx index 40d64636fa346..9292321658e86 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/hooks/use_indicators.test.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/hooks/use_indicators.test.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import { renderHook, act } from '@testing-library/react-hooks'; +import { act, renderHook } from '@testing-library/react-hooks'; import { useIndicators, UseIndicatorsParams, UseIndicatorsValue } from './use_indicators'; import { TestProvidersComponent } from '../../../common/mocks/test_providers'; import { createFetchIndicators } from '../services/fetch_indicators'; diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/hooks/use_indicators_total_count.test.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/hooks/use_total_count.test.tsx similarity index 92% rename from x-pack/plugins/threat_intelligence/public/modules/indicators/hooks/use_indicators_total_count.test.tsx rename to x-pack/plugins/threat_intelligence/public/modules/indicators/hooks/use_total_count.test.tsx index 7b5afb43e9311..af7ece94a6f51 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/hooks/use_indicators_total_count.test.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/hooks/use_total_count.test.tsx @@ -5,10 +5,10 @@ * 2.0. */ -import { TestProvidersComponent, mockedSearchService } from '../../../common/mocks/test_providers'; +import { mockedSearchService, TestProvidersComponent } from '../../../common/mocks/test_providers'; import { act, renderHook } from '@testing-library/react-hooks'; import { BehaviorSubject } from 'rxjs'; -import { useIndicatorsTotalCount } from './use_indicators_total_count'; +import { useIndicatorsTotalCount } from '.'; const indicatorsResponse = { rawResponse: { hits: { hits: [], total: 0 } } }; diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/hooks/use_indicators_total_count.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/hooks/use_total_count.tsx similarity index 100% rename from x-pack/plugins/threat_intelligence/public/modules/indicators/hooks/use_indicators_total_count.tsx rename to x-pack/plugins/threat_intelligence/public/modules/indicators/hooks/use_total_count.tsx diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/index.ts b/x-pack/plugins/threat_intelligence/public/modules/indicators/index.ts new file mode 100644 index 0000000000000..73affbb6e8a63 --- /dev/null +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/index.ts @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export * from './containers/filters/context'; +export * from './hooks/use_filters_context'; +export * from './hooks/use_sourcerer_data_view'; +export * from './hooks/use_total_count'; +export * from './utils/field_value'; +export * from './utils/unwrap_value'; diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_field_label/index.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/pages/index.ts similarity index 86% rename from x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_field_label/index.tsx rename to x-pack/plugins/threat_intelligence/public/modules/indicators/pages/index.ts index a2f2520c9541b..b4e67e7869557 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_field_label/index.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/pages/index.ts @@ -5,4 +5,4 @@ * 2.0. */ -export * from './indicator_field_label'; +export * from './indicators'; diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/indicators_page.test.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/pages/indicators.test.tsx similarity index 76% rename from x-pack/plugins/threat_intelligence/public/modules/indicators/indicators_page.test.tsx rename to x-pack/plugins/threat_intelligence/public/modules/indicators/pages/indicators.test.tsx index 527507584f0e1..d51410857c26e 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/indicators_page.test.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/pages/indicators.test.tsx @@ -7,18 +7,17 @@ import React from 'react'; import { render } from '@testing-library/react'; -import { IndicatorsPage } from './indicators_page'; -import { useIndicators } from './hooks/use_indicators'; -import { useAggregatedIndicators } from './hooks/use_aggregated_indicators'; -import { useFilters } from '../query_bar/hooks/use_filters'; +import { IndicatorsPage } from '.'; +import { useAggregatedIndicators, useIndicators } from '../hooks'; +import { useFilters } from '../../query_bar/hooks/use_filters'; import moment from 'moment'; -import { TestProvidersComponent } from '../../common/mocks/test_providers'; -import { TABLE_TEST_ID } from './components/table'; -import { mockTimeRange } from '../../common/mocks/mock_indicators_filters_context'; +import { TestProvidersComponent } from '../../../common/mocks/test_providers'; +import { TABLE_TEST_ID } from '../components/table'; +import { mockTimeRange } from '../../../common/mocks/mock_indicators_filters_context'; -jest.mock('../query_bar/hooks/use_filters'); -jest.mock('./hooks/use_indicators'); -jest.mock('./hooks/use_aggregated_indicators'); +jest.mock('../../query_bar/hooks/use_filters'); +jest.mock('../hooks/use_indicators'); +jest.mock('../hooks/use_aggregated_indicators'); const stub = () => {}; diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/indicators_page.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/pages/indicators.tsx similarity index 76% rename from x-pack/plugins/threat_intelligence/public/modules/indicators/indicators_page.tsx rename to x-pack/plugins/threat_intelligence/public/modules/indicators/pages/indicators.tsx index 195bd74238241..1e1f713957fb8 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/indicators_page.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/pages/indicators.tsx @@ -7,20 +7,20 @@ import React, { FC, VFC } from 'react'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; -import { IndicatorsBarChartWrapper } from './components/barchart'; -import { IndicatorsTable } from './components/table'; -import { useIndicators } from './hooks/use_indicators'; -import { DefaultPageLayout } from '../../components/layout'; -import { useFilters } from '../query_bar/hooks/use_filters'; -import { FiltersGlobal } from '../../containers/filters_global'; -import { useSourcererDataView } from './hooks/use_sourcerer_data_view'; -import { FieldTypesProvider } from '../../containers/field_types_provider'; -import { InspectorProvider } from '../../containers/inspector'; -import { useColumnSettings } from './components/table/hooks'; -import { useAggregatedIndicators } from './hooks/use_aggregated_indicators'; -import { IndicatorsFilters } from './containers/indicators_filters'; -import { useSecurityContext } from '../../hooks/use_security_context'; -import { UpdateStatus } from '../../components/update_status'; +import { IndicatorsBarChartWrapper } from '../components/barchart'; +import { IndicatorsTable } from '../components/table'; +import { useIndicators } from '../hooks/use_indicators'; +import { DefaultPageLayout } from '../../../components/layout'; +import { useFilters } from '../../query_bar'; +import { FiltersGlobal } from '../../../containers/filters_global'; +import { useSourcererDataView } from '../hooks/use_sourcerer_data_view'; +import { FieldTypesProvider } from '../../../containers/field_types_provider'; +import { InspectorProvider } from '../../../containers/inspector'; +import { useColumnSettings } from '../components/table/hooks'; +import { useAggregatedIndicators } from '../hooks/use_aggregated_indicators'; +import { IndicatorsFilters } from '../containers/filters'; +import { useSecurityContext } from '../../../hooks/use_security_context'; +import { UpdateStatus } from '../../../components/update_status'; const queryClient = new QueryClient(); diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/services/fetch_aggregated_indicators.ts b/x-pack/plugins/threat_intelligence/public/modules/indicators/services/fetch_aggregated_indicators.ts index 0edc0cca34e5c..f69d28e663bc2 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/services/fetch_aggregated_indicators.ts +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/services/fetch_aggregated_indicators.ts @@ -11,8 +11,7 @@ import type { Filter, Query, TimeRange } from '@kbn/es-query'; import { RequestAdapter } from '@kbn/inspector-plugin/common'; import { calculateBarchartColumnTimeInterval } from '../../../common/utils/dates'; import { RawIndicatorFieldId } from '../../../../common/types/indicator'; -import { getIndicatorQueryParams } from '../utils/get_indicator_query_params'; -import { search } from '../utils/search'; +import { getIndicatorQueryParams, search } from '../utils'; const TIMESTAMP_FIELD = RawIndicatorFieldId.TimeStamp; diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/services/fetch_indicators.ts b/x-pack/plugins/threat_intelligence/public/modules/indicators/services/fetch_indicators.ts index f06038c320116..babf442a5f3fb 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/services/fetch_indicators.ts +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/services/fetch_indicators.ts @@ -9,8 +9,7 @@ import { ISearchStart } from '@kbn/data-plugin/public'; import type { Filter, Query, TimeRange } from '@kbn/es-query'; import { RequestAdapter } from '@kbn/inspector-plugin/common'; import { Indicator } from '../../../../common/types/indicator'; -import { getIndicatorQueryParams } from '../utils/get_indicator_query_params'; -import { search } from '../utils/search'; +import { getIndicatorQueryParams, search } from '../utils'; export interface RawIndicatorsResponse { hits: { diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/utils/index.ts b/x-pack/plugins/threat_intelligence/public/modules/indicators/utils/index.ts new file mode 100644 index 0000000000000..9a542d2960bd1 --- /dev/null +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/utils/index.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export * from './display_name'; +export * from './field_value'; +export * from './get_field_schema'; +export * from './get_indicator_query_params'; +export * from './get_runtime_mappings'; +export * from './search'; +export * from './unwrap_value'; diff --git a/x-pack/plugins/threat_intelligence/public/modules/query_bar/components/filter_in/filter_in.stories.tsx b/x-pack/plugins/threat_intelligence/public/modules/query_bar/components/filter_in/filter_in.stories.tsx index d32adf70ee103..b808f37f02486 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/query_bar/components/filter_in/filter_in.stories.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/query_bar/components/filter_in/filter_in.stories.tsx @@ -11,8 +11,8 @@ import { EuiContextMenuPanel, EuiDataGrid, EuiDataGridColumn } from '@elastic/eu import { EuiDataGridColumnVisibility } from '@elastic/eui/src/components/datagrid/data_grid_types'; import { mockIndicatorsFiltersContext } from '../../../../common/mocks/mock_indicators_filters_context'; import { generateMockIndicator, Indicator } from '../../../../../common/types/indicator'; -import { FilterInButtonIcon, FilterInContextMenu, FilterInCellAction } from '.'; -import { IndicatorsFiltersContext } from '../../../indicators/containers/indicators_filters/context'; +import { FilterInButtonIcon, FilterInCellAction, FilterInContextMenu } from '.'; +import { IndicatorsFiltersContext } from '../../../indicators'; export default { title: 'FilterIn', diff --git a/x-pack/plugins/threat_intelligence/public/modules/query_bar/components/filter_in/filter_in.test.tsx b/x-pack/plugins/threat_intelligence/public/modules/query_bar/components/filter_in/filter_in.test.tsx index 29349b5442790..18d555da85013 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/query_bar/components/filter_in/filter_in.test.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/query_bar/components/filter_in/filter_in.test.tsx @@ -9,7 +9,7 @@ import React, { FunctionComponent } from 'react'; import { render } from '@testing-library/react'; import { EuiButtonIcon } from '@elastic/eui'; import { generateMockIndicator, Indicator } from '../../../../../common/types/indicator'; -import { useIndicatorsFiltersContext } from '../../../indicators/hooks/use_indicators_filters_context'; +import { useIndicatorsFiltersContext } from '../../../indicators'; import { mockIndicatorsFiltersContext } from '../../../../common/mocks/mock_indicators_filters_context'; import { FilterInButtonEmpty, @@ -18,7 +18,7 @@ import { FilterInContextMenu, } from '.'; -jest.mock('../../../indicators/hooks/use_indicators_filters_context'); +jest.mock('../../../indicators/hooks/use_filters_context'); const mockIndicator: Indicator = generateMockIndicator(); diff --git a/x-pack/plugins/threat_intelligence/public/modules/query_bar/components/filter_in/filter_in.tsx b/x-pack/plugins/threat_intelligence/public/modules/query_bar/components/filter_in/filter_in.tsx index 0147e79285b0c..f87bb0813249d 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/query_bar/components/filter_in/filter_in.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/query_bar/components/filter_in/filter_in.tsx @@ -8,8 +8,8 @@ import React, { VFC } from 'react'; import { i18n } from '@kbn/i18n'; import { EuiButtonEmpty, EuiButtonIcon, EuiContextMenuItem, EuiToolTip } from '@elastic/eui'; -import { useFilterInOut } from '../../hooks/use_filter_in_out'; -import { FilterIn } from '../../utils/filter'; +import { useFilterInOut } from '../../hooks'; +import { FilterIn } from '../../utils'; import { Indicator } from '../../../../../common/types/indicator'; import { useStyles } from './styles'; diff --git a/x-pack/plugins/threat_intelligence/public/modules/query_bar/components/filter_in/index.tsx b/x-pack/plugins/threat_intelligence/public/modules/query_bar/components/filter_in/index.ts similarity index 100% rename from x-pack/plugins/threat_intelligence/public/modules/query_bar/components/filter_in/index.tsx rename to x-pack/plugins/threat_intelligence/public/modules/query_bar/components/filter_in/index.ts diff --git a/x-pack/plugins/threat_intelligence/public/modules/query_bar/components/filter_out/filter_out.stories.tsx b/x-pack/plugins/threat_intelligence/public/modules/query_bar/components/filter_out/filter_out.stories.tsx index 463b249998eb2..5553a62e8118d 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/query_bar/components/filter_out/filter_out.stories.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/query_bar/components/filter_out/filter_out.stories.tsx @@ -11,8 +11,8 @@ import { EuiContextMenuPanel, EuiDataGrid, EuiDataGridColumn } from '@elastic/eu import { EuiDataGridColumnVisibility } from '@elastic/eui/src/components/datagrid/data_grid_types'; import { mockIndicatorsFiltersContext } from '../../../../common/mocks/mock_indicators_filters_context'; import { generateMockIndicator, Indicator } from '../../../../../common/types/indicator'; -import { FilterOutButtonIcon, FilterOutContextMenu, FilterOutCellAction } from '.'; -import { IndicatorsFiltersContext } from '../../../indicators/containers/indicators_filters/context'; +import { FilterOutButtonIcon, FilterOutCellAction, FilterOutContextMenu } from '.'; +import { IndicatorsFiltersContext } from '../../../indicators'; export default { title: 'FilterOut', diff --git a/x-pack/plugins/threat_intelligence/public/modules/query_bar/components/filter_out/filter_out.test.tsx b/x-pack/plugins/threat_intelligence/public/modules/query_bar/components/filter_out/filter_out.test.tsx index 68c08cbebd0fc..c35416d5a3128 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/query_bar/components/filter_out/filter_out.test.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/query_bar/components/filter_out/filter_out.test.tsx @@ -9,7 +9,7 @@ import React, { FunctionComponent } from 'react'; import { render } from '@testing-library/react'; import { EuiButtonIcon } from '@elastic/eui'; import { generateMockIndicator, Indicator } from '../../../../../common/types/indicator'; -import { useIndicatorsFiltersContext } from '../../../indicators/hooks/use_indicators_filters_context'; +import { useIndicatorsFiltersContext } from '../../../indicators'; import { mockIndicatorsFiltersContext } from '../../../../common/mocks/mock_indicators_filters_context'; import { FilterOutButtonEmpty, @@ -18,7 +18,7 @@ import { FilterOutContextMenu, } from '.'; -jest.mock('../../../indicators/hooks/use_indicators_filters_context'); +jest.mock('../../../indicators/hooks/use_filters_context'); const mockIndicator: Indicator = generateMockIndicator(); diff --git a/x-pack/plugins/threat_intelligence/public/modules/query_bar/components/filter_out/filter_out.tsx b/x-pack/plugins/threat_intelligence/public/modules/query_bar/components/filter_out/filter_out.tsx index 518850d9dc242..590cee62b1e26 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/query_bar/components/filter_out/filter_out.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/query_bar/components/filter_out/filter_out.tsx @@ -8,8 +8,8 @@ import React, { VFC } from 'react'; import { i18n } from '@kbn/i18n'; import { EuiButtonEmpty, EuiButtonIcon, EuiContextMenuItem, EuiToolTip } from '@elastic/eui'; -import { useFilterInOut } from '../../hooks/use_filter_in_out'; -import { FilterOut } from '../../utils/filter'; +import { useFilterInOut } from '../../hooks'; +import { FilterOut } from '../../utils'; import { Indicator } from '../../../../../common/types/indicator'; import { useStyles } from './styles'; diff --git a/x-pack/plugins/threat_intelligence/public/modules/query_bar/components/filter_out/index.tsx b/x-pack/plugins/threat_intelligence/public/modules/query_bar/components/filter_out/index.ts similarity index 100% rename from x-pack/plugins/threat_intelligence/public/modules/query_bar/components/filter_out/index.tsx rename to x-pack/plugins/threat_intelligence/public/modules/query_bar/components/filter_out/index.ts diff --git a/x-pack/plugins/threat_intelligence/public/modules/query_bar/hooks/index.ts b/x-pack/plugins/threat_intelligence/public/modules/query_bar/hooks/index.ts new file mode 100644 index 0000000000000..93d692c0bf6b9 --- /dev/null +++ b/x-pack/plugins/threat_intelligence/public/modules/query_bar/hooks/index.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export * from './use_filter_in_out'; +export * from './use_filters'; diff --git a/x-pack/plugins/threat_intelligence/public/modules/query_bar/hooks/use_filter_in_out.test.ts b/x-pack/plugins/threat_intelligence/public/modules/query_bar/hooks/use_filter_in_out.test.ts index 6099ed8486670..369c6758df278 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/query_bar/hooks/use_filter_in_out.test.ts +++ b/x-pack/plugins/threat_intelligence/public/modules/query_bar/hooks/use_filter_in_out.test.ts @@ -5,15 +5,15 @@ * 2.0. */ -import { renderHook, RenderHookResult, Renderer } from '@testing-library/react-hooks'; +import { Renderer, renderHook, RenderHookResult } from '@testing-library/react-hooks'; import { generateMockIndicator, generateMockUrlIndicator, Indicator, } from '../../../../common/types/indicator'; import { TestProvidersComponent } from '../../../common/mocks/test_providers'; -import { useFilterInOut, UseFilterInValue } from './use_filter_in_out'; -import { FilterIn } from '../utils/filter'; +import { useFilterInOut, UseFilterInValue } from '.'; +import { FilterIn } from '../utils'; describe('useFilterInOut()', () => { let hookResult: RenderHookResult<{}, UseFilterInValue, Renderer>; diff --git a/x-pack/plugins/threat_intelligence/public/modules/query_bar/hooks/use_filter_in_out.ts b/x-pack/plugins/threat_intelligence/public/modules/query_bar/hooks/use_filter_in_out.ts index d44bb8528afab..bb25de98587df 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/query_bar/hooks/use_filter_in_out.ts +++ b/x-pack/plugins/threat_intelligence/public/modules/query_bar/hooks/use_filter_in_out.ts @@ -7,9 +7,12 @@ import { useCallback } from 'react'; import { Filter } from '@kbn/es-query'; -import { useIndicatorsFiltersContext } from '../../indicators/hooks/use_indicators_filters_context'; -import { fieldAndValueValid, getIndicatorFieldAndValue } from '../../indicators/utils/field_value'; -import { FilterIn, FilterOut, updateFiltersArray } from '../utils/filter'; +import { + fieldAndValueValid, + getIndicatorFieldAndValue, + useIndicatorsFiltersContext, +} from '../../indicators'; +import { FilterIn, FilterOut, updateFiltersArray } from '../utils'; import { Indicator } from '../../../../common/types/indicator'; export interface UseFilterInParam { diff --git a/x-pack/plugins/threat_intelligence/public/modules/query_bar/hooks/use_filters/use_filters.ts b/x-pack/plugins/threat_intelligence/public/modules/query_bar/hooks/use_filters.ts similarity index 84% rename from x-pack/plugins/threat_intelligence/public/modules/query_bar/hooks/use_filters/use_filters.ts rename to x-pack/plugins/threat_intelligence/public/modules/query_bar/hooks/use_filters.ts index c50a10c17b709..24e368e5a2f8e 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/query_bar/hooks/use_filters/use_filters.ts +++ b/x-pack/plugins/threat_intelligence/public/modules/query_bar/hooks/use_filters.ts @@ -6,10 +6,7 @@ */ import { useContext } from 'react'; -import { - IndicatorsFiltersContext, - IndicatorsFiltersContextValue, -} from '../../../indicators/containers/indicators_filters'; +import { IndicatorsFiltersContext, IndicatorsFiltersContextValue } from '../../indicators'; export type UseFiltersValue = IndicatorsFiltersContextValue; diff --git a/x-pack/plugins/threat_intelligence/public/modules/query_bar/index.ts b/x-pack/plugins/threat_intelligence/public/modules/query_bar/index.ts new file mode 100644 index 0000000000000..0ed4dd8883318 --- /dev/null +++ b/x-pack/plugins/threat_intelligence/public/modules/query_bar/index.ts @@ -0,0 +1,10 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export * from './components/filter_in/filter_in'; +export * from './components/filter_out/filter_out'; +export * from './hooks/use_filters'; diff --git a/x-pack/plugins/threat_intelligence/public/modules/query_bar/utils/filter.test.ts b/x-pack/plugins/threat_intelligence/public/modules/query_bar/utils/filter.test.ts index fefe488e5e53f..aaa2373f868bf 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/query_bar/utils/filter.test.ts +++ b/x-pack/plugins/threat_intelligence/public/modules/query_bar/utils/filter.test.ts @@ -6,7 +6,7 @@ */ import { Filter } from '@kbn/es-query'; -import { FilterIn, FilterOut, updateFiltersArray } from './filter'; +import { FilterIn, FilterOut, updateFiltersArray } from '.'; describe('updateFiltersArray', () => { it('should add new filter', () => { diff --git a/x-pack/plugins/threat_intelligence/public/modules/query_bar/utils/index.ts b/x-pack/plugins/threat_intelligence/public/modules/query_bar/utils/index.ts new file mode 100644 index 0000000000000..c87b618b087cd --- /dev/null +++ b/x-pack/plugins/threat_intelligence/public/modules/query_bar/utils/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 * from './filter'; diff --git a/x-pack/plugins/threat_intelligence/public/modules/timeline/components/add_to_timeline/add_to_timeline.stories.tsx b/x-pack/plugins/threat_intelligence/public/modules/timeline/components/add_to_timeline/add_to_timeline.stories.tsx index beefdafd9d59f..eef3b90782f6b 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/timeline/components/add_to_timeline/add_to_timeline.stories.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/timeline/components/add_to_timeline/add_to_timeline.stories.tsx @@ -12,7 +12,7 @@ import { createKibanaReactContext } from '@kbn/kibana-react-plugin/public'; import { EuiContextMenuPanel } from '@elastic/eui'; import { mockKibanaTimelinesService } from '../../../../common/mocks/mock_kibana_timelines_service'; import { generateMockIndicator, Indicator } from '../../../../../common/types/indicator'; -import { AddToTimelineButtonIcon, AddToTimelineContextMenu } from './add_to_timeline'; +import { AddToTimelineButtonIcon, AddToTimelineContextMenu } from '.'; export default { title: 'AddToTimeline', diff --git a/x-pack/plugins/threat_intelligence/public/modules/timeline/components/add_to_timeline/add_to_timeline.test.tsx b/x-pack/plugins/threat_intelligence/public/modules/timeline/components/add_to_timeline/add_to_timeline.test.tsx index 85e581bc8dc17..c2a997f49ab96 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/timeline/components/add_to_timeline/add_to_timeline.test.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/timeline/components/add_to_timeline/add_to_timeline.test.tsx @@ -9,7 +9,7 @@ import React from 'react'; import { render } from '@testing-library/react'; import { generateMockIndicator, Indicator } from '../../../../../common/types/indicator'; import { EMPTY_VALUE } from '../../../../../common/constants'; -import { AddToTimelineButtonIcon } from './add_to_timeline'; +import { AddToTimelineButtonIcon } from '.'; import { TestProvidersComponent } from '../../../../common/mocks/test_providers'; describe('', () => { diff --git a/x-pack/plugins/threat_intelligence/public/modules/timeline/components/add_to_timeline/add_to_timeline.tsx b/x-pack/plugins/threat_intelligence/public/modules/timeline/components/add_to_timeline/add_to_timeline.tsx index 211d37dc6b4e4..97327bd67a304 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/timeline/components/add_to_timeline/add_to_timeline.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/timeline/components/add_to_timeline/add_to_timeline.tsx @@ -16,15 +16,12 @@ import { EuiToolTip, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { generateDataProvider } from '../../utils/data_provider'; -import { - fieldAndValueValid, - getIndicatorFieldAndValue, -} from '../../../indicators/utils/field_value'; +import { generateDataProvider } from '../../utils'; +import { fieldAndValueValid, getIndicatorFieldAndValue } from '../../../indicators'; import { useKibana } from '../../../../hooks/use_kibana'; import { Indicator } from '../../../../../common/types/indicator'; import { useStyles } from './styles'; -import { useAddToTimeline } from '../../hooks/use_add_to_timeline'; +import { useAddToTimeline } from '../../hooks'; const ICON_TYPE = 'timeline'; const TITLE = i18n.translate('xpack.threatIntelligence.timeline.addToTimeline', { diff --git a/x-pack/plugins/threat_intelligence/public/modules/timeline/components/investigate_in_timeline/investigate_in_timeline.tsx b/x-pack/plugins/threat_intelligence/public/modules/timeline/components/investigate_in_timeline/investigate_in_timeline.tsx index cd1f7ce2a2d97..c99c02ac8f8a2 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/timeline/components/investigate_in_timeline/investigate_in_timeline.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/timeline/components/investigate_in_timeline/investigate_in_timeline.tsx @@ -9,7 +9,7 @@ import React, { VFC } from 'react'; import { EuiButton, EuiButtonIcon, EuiToolTip } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import { i18n } from '@kbn/i18n'; -import { useInvestigateInTimeline } from '../../hooks/use_investigate_in_timeline'; +import { useInvestigateInTimeline } from '../../hooks'; import { Indicator } from '../../../../../common/types/indicator'; const BUTTON_ICON_LABEL: string = i18n.translate( diff --git a/x-pack/plugins/threat_intelligence/public/modules/timeline/hooks/use_add_to_timeline.test.tsx b/x-pack/plugins/threat_intelligence/public/modules/timeline/hooks/use_add_to_timeline.test.tsx index a92c75227310e..70a54e37d6c91 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/timeline/hooks/use_add_to_timeline.test.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/timeline/hooks/use_add_to_timeline.test.tsx @@ -6,14 +6,14 @@ */ import { EMPTY_VALUE } from '../../../../common/constants'; -import { renderHook, RenderHookResult, Renderer } from '@testing-library/react-hooks'; +import { Renderer, renderHook, RenderHookResult } from '@testing-library/react-hooks'; import { generateMockIndicator, generateMockUrlIndicator, Indicator, } from '../../../../common/types/indicator'; import { TestProvidersComponent } from '../../../common/mocks/test_providers'; -import { useAddToTimeline, UseAddToTimelineValue } from './use_add_to_timeline'; +import { useAddToTimeline, UseAddToTimelineValue } from '.'; describe('useInvestigateInTimeline()', () => { let hookResult: RenderHookResult<{}, UseAddToTimelineValue, Renderer>; diff --git a/x-pack/plugins/threat_intelligence/public/modules/timeline/hooks/use_add_to_timeline.ts b/x-pack/plugins/threat_intelligence/public/modules/timeline/hooks/use_add_to_timeline.ts index ab69481d3b528..f23866ac5e3ea 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/timeline/hooks/use_add_to_timeline.ts +++ b/x-pack/plugins/threat_intelligence/public/modules/timeline/hooks/use_add_to_timeline.ts @@ -7,8 +7,8 @@ import { DataProvider } from '@kbn/timelines-plugin/common'; import { AddToTimelineButtonProps } from '@kbn/timelines-plugin/public'; -import { generateDataProvider } from '../utils/data_provider'; -import { fieldAndValueValid, getIndicatorFieldAndValue } from '../../indicators/utils/field_value'; +import { generateDataProvider } from '../utils'; +import { fieldAndValueValid, getIndicatorFieldAndValue } from '../../indicators'; import { Indicator } from '../../../../common/types/indicator'; export interface UseAddToTimelineParam { diff --git a/x-pack/plugins/threat_intelligence/public/modules/timeline/hooks/use_investigate_in_timeline.test.tsx b/x-pack/plugins/threat_intelligence/public/modules/timeline/hooks/use_investigate_in_timeline.test.tsx index 30c42d7096f2f..b8c45e2095204 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/timeline/hooks/use_investigate_in_timeline.test.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/timeline/hooks/use_investigate_in_timeline.test.tsx @@ -5,11 +5,8 @@ * 2.0. */ -import { renderHook, RenderHookResult, Renderer } from '@testing-library/react-hooks'; -import { - useInvestigateInTimeline, - UseInvestigateInTimelineValue, -} from './use_investigate_in_timeline'; +import { Renderer, renderHook, RenderHookResult } from '@testing-library/react-hooks'; +import { useInvestigateInTimeline, UseInvestigateInTimelineValue } from '.'; import { generateMockIndicator, generateMockUrlIndicator, diff --git a/x-pack/plugins/threat_intelligence/public/modules/timeline/hooks/use_investigate_in_timeline.ts b/x-pack/plugins/threat_intelligence/public/modules/timeline/hooks/use_investigate_in_timeline.ts index efae8b441a673..d656976cfa4b2 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/timeline/hooks/use_investigate_in_timeline.ts +++ b/x-pack/plugins/threat_intelligence/public/modules/timeline/hooks/use_investigate_in_timeline.ts @@ -8,10 +8,9 @@ import { useContext } from 'react'; import moment from 'moment'; import { DataProvider } from '@kbn/timelines-plugin/common'; -import { generateDataProvider } from '../utils/data_provider'; +import { generateDataProvider } from '../utils'; import { SecuritySolutionContext } from '../../../containers/security_solution_context'; -import { fieldAndValueValid, getIndicatorFieldAndValue } from '../../indicators/utils/field_value'; -import { unwrapValue } from '../../indicators/utils/unwrap_value'; +import { fieldAndValueValid, getIndicatorFieldAndValue, unwrapValue } from '../../indicators'; import { Indicator, IndicatorFieldEventEnrichmentMap, diff --git a/x-pack/plugins/threat_intelligence/public/modules/timeline/index.ts b/x-pack/plugins/threat_intelligence/public/modules/timeline/index.ts new file mode 100644 index 0000000000000..9024311cd9f9c --- /dev/null +++ b/x-pack/plugins/threat_intelligence/public/modules/timeline/index.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export * from './components/add_to_timeline'; +export * from './components/investigate_in_timeline'; diff --git a/x-pack/plugins/threat_intelligence/public/modules/timeline/utils/index.ts b/x-pack/plugins/threat_intelligence/public/modules/timeline/utils/index.ts new file mode 100644 index 0000000000000..dc6c4590b786e --- /dev/null +++ b/x-pack/plugins/threat_intelligence/public/modules/timeline/utils/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 * from './data_provider'; diff --git a/x-pack/plugins/threat_intelligence/public/plugin.tsx b/x-pack/plugins/threat_intelligence/public/plugin.tsx index 0ec3064c5052b..4af2f41af9c4f 100755 --- a/x-pack/plugins/threat_intelligence/public/plugin.tsx +++ b/x-pack/plugins/threat_intelligence/public/plugin.tsx @@ -12,11 +12,11 @@ import React, { Suspense, VFC } from 'react'; import { __IntlProvider as IntlProvider } from '@kbn/i18n-react'; import { KibanaContextProvider } from './hooks/use_kibana'; import { + SecuritySolutionPluginContext, Services, ThreatIntelligencePluginSetup, ThreatIntelligencePluginStart, ThreatIntelligencePluginStartDeps, - SecuritySolutionPluginContext, } from './types'; import { SecuritySolutionContext } from './containers/security_solution_context'; import { EnterpriseGuard } from './containers/enterprise_guard'; @@ -27,7 +27,7 @@ interface AppProps { securitySolutionContext: SecuritySolutionPluginContext; } -const LazyIndicatorsPage = React.lazy(() => import('./modules/indicators/indicators_page')); +const LazyIndicatorsPage = React.lazy(() => import('./modules/indicators/pages/indicators')); const IndicatorsPage: VFC = () => ( diff --git a/x-pack/plugins/timelines/public/components/hover_actions/actions/add_to_timeline.test.tsx b/x-pack/plugins/timelines/public/components/hover_actions/actions/add_to_timeline.test.tsx index 26300400dbcfd..905852b8f182d 100644 --- a/x-pack/plugins/timelines/public/components/hover_actions/actions/add_to_timeline.test.tsx +++ b/x-pack/plugins/timelines/public/components/hover_actions/actions/add_to_timeline.test.tsx @@ -9,7 +9,11 @@ import { EuiButtonEmpty } from '@elastic/eui'; import { act, fireEvent, render, screen } from '@testing-library/react'; import React from 'react'; -import AddToTimelineButton, { ADD_TO_TIMELINE_KEYBOARD_SHORTCUT } from './add_to_timeline'; +import AddToTimelineButton, { + ADD_TO_TIMELINE_KEYBOARD_SHORTCUT, + SuccessMessageProps, + AddSuccessMessage, +} from './add_to_timeline'; import { DataProvider, IS_OPERATOR } from '../../../../common/types'; import { useDeepEqualSelector } from '../../../hooks/use_selector'; import { TestProviders } from '../../../mock'; @@ -391,7 +395,11 @@ describe('add to timeline', () => { fireEvent.click(screen.getByRole('button')); - expect(mockAddSuccess).toBeCalledWith('Added a to timeline'); + const message: SuccessMessageProps = { + children: i18n.ADDED_TO_TIMELINE_OR_TEMPLATE_MESSAGE(providerA.name, true), + }; + const wrapper = render(); + expect(wrapper.container.textContent).toBe('Added a to timeline'); }); test('Add success is called with "template" if timeline type is template', () => { @@ -405,7 +413,11 @@ describe('add to timeline', () => { fireEvent.click(screen.getByRole('button')); - expect(mockAddSuccess).toBeCalledWith('Added a to template'); + const message: SuccessMessageProps = { + children: i18n.ADDED_TO_TIMELINE_OR_TEMPLATE_MESSAGE(providerA.name, false), + }; + const wrapper = render(); + expect(wrapper.container.textContent).toBe('Added a to template'); }); }); }); diff --git a/x-pack/plugins/timelines/public/components/hover_actions/actions/add_to_timeline.tsx b/x-pack/plugins/timelines/public/components/hover_actions/actions/add_to_timeline.tsx index 6cbfee6bec99f..f3a37563ebfe0 100644 --- a/x-pack/plugins/timelines/public/components/hover_actions/actions/add_to_timeline.tsx +++ b/x-pack/plugins/timelines/public/components/hover_actions/actions/add_to_timeline.tsx @@ -11,6 +11,7 @@ import { DraggableId } from 'react-beautiful-dnd'; import { useDispatch } from 'react-redux'; import { isEmpty } from 'lodash'; +import { toMountPoint } from '@kbn/kibana-react-plugin/public'; import { stopPropagationAndPreventDefault } from '../../../../common/utils/accessibility'; import { DataProvider, TimelineId } from '../../../../common/types'; import { useDeepEqualSelector } from '../../../hooks/use_selector'; @@ -46,6 +47,17 @@ const useGetHandleStartDragToTimeline = ({ return handleStartDragToTimeline; }; +export interface SuccessMessageProps { + children: React.ReactChild; +} +export const AddSuccessMessage = (props: SuccessMessageProps) => { + return ( + + {props.children} + + ); +}; + export interface AddToTimelineButtonProps extends HoverActionComponentProps { /** `Component` is only used with `EuiDataGrid`; the grid keeps a reference to `Component` for show / hide functionality */ Component?: typeof EuiButtonEmpty | typeof EuiButtonIcon | typeof EuiContextMenuItem; @@ -88,9 +100,16 @@ const AddToTimelineButton: React.FC = React.memo( dataProvider: provider, }) ); - addSuccess( - i18n.ADDED_TO_TIMELINE_OR_TEMPLATE_MESSAGE(provider.name, timelineType === 'default') - ); + addSuccess({ + title: toMountPoint( + + {i18n.ADDED_TO_TIMELINE_OR_TEMPLATE_MESSAGE( + provider.name, + timelineType === 'default' + )} + + ), + }); } }); } diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index 976c14d76903b..eba4c64dc818d 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -7500,7 +7500,6 @@ "xpack.apm.serviceDetails.metrics.errorsList.title": "Erreurs", "xpack.apm.serviceDetails.metrics.memoryUsageChartTitle": "Utilisation mémoire système", "xpack.apm.serviceDetails.metricsTabLabel": "Indicateurs", - "xpack.apm.serviceDetails.nodesTabLabel": "JVM", "xpack.apm.serviceDetails.overviewTabLabel": "Aperçu", "xpack.apm.serviceDetails.transactionsTabLabel": "Transactions", "xpack.apm.serviceGroup.allServices.title": "Tous les services", @@ -9280,10 +9279,6 @@ "xpack.cases.connecors.get.missingCaseConnectorErrorMessage": "Le type d'objet \"{id}\" n'est pas enregistré.", "xpack.cases.connecors.register.duplicateCaseConnectorErrorMessage": "Le type d'objet \"{id}\" est déjà enregistré.", "xpack.cases.connectors.card.createCommentWarningDesc": "Configurez les champs Create Comment URL et Create Comment Objects pour que le connecteur {connectorName} puisse partager les commentaires.", - "xpack.cases.connectors.cases.externalIncidentAdded": "(ajouté le {date} par {user})", - "xpack.cases.connectors.cases.externalIncidentCreated": "(créé le {date} par {user})", - "xpack.cases.connectors.cases.externalIncidentDefault": "(créé le {date} par {user})", - "xpack.cases.connectors.cases.externalIncidentUpdated": "(mis à jour le {date} par {user})", "xpack.cases.connectors.jira.unableToGetIssueMessage": "Impossible d'obtenir le problème ayant l'ID {id}", "xpack.cases.containers.pushToExternalService": "Envoyé avec succès à { serviceName }", "xpack.cases.containers.syncCase": "Les alertes de \"{caseTitle}\" ont été synchronisées", @@ -9307,7 +9302,6 @@ "xpack.cases.casesStats.mttr": "Temps moyen avant fermeture", "xpack.cases.casesStats.mttrDescription": "La durée moyenne (de la création à la clôture) de vos cas en cours", "xpack.cases.caseTable.bulkActions": "Actions groupées", - "xpack.cases.caseTable.bulkActions.deleteSelectedTitle": "Supprimer la sélection", "xpack.cases.caseTable.changeStatus": "Modifier le statut", "xpack.cases.caseTable.closed": "Fermé", "xpack.cases.caseTable.closedCases": "Cas fermés", @@ -9563,10 +9557,7 @@ "xpack.cases.severity.medium": "Moyenne", "xpack.cases.severity.title": "Sévérité", "xpack.cases.status.all": "Tous les statuts", - "xpack.cases.status.closed": "Fermé", "xpack.cases.status.iconAria": "Modifier le statut", - "xpack.cases.status.inProgress": "En cours", - "xpack.cases.status.open": "Ouvrir", "xpack.cases.userActions.attachmentNotRegisteredErrorMsg": "Le type de pièce jointe n'est pas enregistré", "xpack.cases.userActions.defaultEventAttachmentTitle": "ajouté une pièce jointe de type", "xpack.crossClusterReplication.app.deniedPermissionDescription": "Pour utiliser la réplication inter-clusters, vous devez disposer de {clusterPrivilegesCount, plural, one {ce privilège de cluster} other {ces privilèges de cluster}} : {clusterPrivileges}.", @@ -11365,11 +11356,6 @@ "xpack.enterpriseSearch.content.callout.dismissButton": "Rejeter", "xpack.enterpriseSearch.content.callout.title": "Présentation des index Elasticsearch dans Enterprise Search", "xpack.enterpriseSearch.content.description": "Enterprise Search offre un certain nombre de moyens de rendre vos données facilement interrogeables. Vous pouvez choisir entre le robot d'indexation, les indices Elasticsearch, l'API, les téléchargements directs ou les connecteurs tiers.", - "xpack.enterpriseSearch.content.index.createAppSearchEngine.button": "Créer un moteur App Search", - "xpack.enterpriseSearch.content.index.dismiss.button": "Rejeter", - "xpack.enterpriseSearch.content.index.indexCreatedCallout.info": "Vous pouvez utiliser des moteurs App Search pour créer une expérience de recherche pour votre nouvel index Elasticsearch.", - "xpack.enterpriseSearch.content.index.indexCreatedCallout.title": "Index Elasticsearch créé avec succès", - "xpack.enterpriseSearch.content.index.readDocumentation.link": "Lire la documentation", "xpack.enterpriseSearch.content.index.searchEngines.createEngine": "Créer un moteur App Search", "xpack.enterpriseSearch.content.index.searchEngines.label": "Moteurs de recherche", "xpack.enterpriseSearch.content.index.searchEngines.viewEngines": "Afficher les moteurs App Search", @@ -13443,12 +13429,6 @@ "xpack.fleet.externallyManagedLabel": "Ceci est une politique d'intégration gérée de manière externe.", "xpack.fleet.featureCatalogueDescription": "Ajouter et gérer des intégrations avec Elastic Agent", "xpack.fleet.featureCatalogueTitle": "Ajouter des intégrations Elastic Agent", - "xpack.fleet.featuredObsDesc": "Surveillez, détectez et diagnostiquez des problèmes complexes de performances des applications.", - "xpack.fleet.featuredObsTitle": "Elastic APM", - "xpack.fleet.featuredSearchDesc": "Ajoutez la recherche à votre site web avec le robot d'indexation Enterprise Search.", - "xpack.fleet.featuredSearchTitle": "Robot d'indexation", - "xpack.fleet.featuredSecurityDesc": "Protégez vos hôtes et vos charges de travail cloud grâce à la prévention des menaces, la détection et la visibilité des données en profondeur en toute sécurité.", - "xpack.fleet.featuredSecurityTitle": "Sécurité du cloud et des points de terminaison", "xpack.fleet.fleetServerCloudRequiredCallout.cloudDeploymentLink": "déploiement sur le cloud", "xpack.fleet.fleetServerCloudRequiredCallout.editDeploymentButtonLabel": "Modifier le déploiement", "xpack.fleet.fleetServerCloudRequiredCallout.guideLink": "Guide de Fleet et d’Elastic Agent", @@ -28492,9 +28472,6 @@ "xpack.securitySolution.inspectPatternDifferent": "Cet élément possède un modèle d'indexation unique séparé du paramètre de vue de données.", "xpack.securitySolution.investigationEnrichment.requestError": "Une erreur est survenue lors de la demande de Threat Intelligence", "xpack.securitySolution.ja3.fingerprint.ja3.fingerprintLabel": "ja3", - "xpack.securitySolution.kpiHost.enableHostRiskText": "Activer le module de risque de l'hôte pour afficher davantage de données", - "xpack.securitySolution.kpiHost.hostRiskData": "données de risque de l'hôte", - "xpack.securitySolution.kpiHost.learnMore": "Découvrez", "xpack.securitySolution.kpiHosts.hosts.title": "Hôtes", "xpack.securitySolution.kpiHosts.riskyHosts.errorMessage": "Erreur lors de la récupération de l'API d'hôtes à risque", "xpack.securitySolution.kpiHosts.riskyHosts.inspectTitle": "Hôtes à risque", @@ -28518,9 +28495,6 @@ "xpack.securitySolution.kpiNetwork.uniquePrivateIps.sourceChartLabel": "Src.", "xpack.securitySolution.kpiNetwork.uniquePrivateIps.sourceUnitLabel": "source", "xpack.securitySolution.kpiNetwork.uniquePrivateIps.title": "IP privés uniques", - "xpack.securitySolution.kpiUser.enableUserRiskText": "Activer le module de risque de l'utilisateur pour afficher davantage de données", - "xpack.securitySolution.kpiUser.learnMore": "Découvrez", - "xpack.securitySolution.kpiUser.userRiskData": "données de risque de l'utilisateur", "xpack.securitySolution.kpiUsers.totalUsers.errorSearchDescription": "Une erreur s'est produite sur la recherche du KPI du total des utilisateurs", "xpack.securitySolution.kpiUsers.totalUsers.title": "Utilisateurs", "xpack.securitySolution.kubernetes.columnContainer": "Conteneur", @@ -30626,8 +30600,6 @@ "xpack.synthetics.monitorRoute.title": "Moniteur | {baseTitle}", "xpack.synthetics.monitorStatusBar.locations.oneLocStatus": "{status} dans {loc} emplacement", "xpack.synthetics.monitorStatusBar.locations.upStatus": "{status} dans {loc} emplacements", - "xpack.synthetics.monitorSummary.lastRunLocation": "dans {loc}.", - "xpack.synthetics.monitorSummary.lastRunTime": "Dernière exécution à {time}", "xpack.synthetics.overview.alerts.enabled.success.description": "Un message sera envoyé à {actionConnectors} lorsque ce monitoring sera arrêté.", "xpack.synthetics.overview.durationMsFormatting": "{millis} ms", "xpack.synthetics.overview.durationSecondsFormatting": "{seconds} s", @@ -31367,16 +31339,7 @@ "xpack.synthetics.monitorStatusBar.timestampFromNowTextAriaLabel": "Temps depuis la dernière vérification", "xpack.synthetics.monitorStatusBar.type.ariaLabel": "Type de moniteur", "xpack.synthetics.monitorStatusBar.type.label": "Type", - "xpack.synthetics.monitorSummary.down": "Arrêté", - "xpack.synthetics.monitorSummary.errors": "Erreurs", - "xpack.synthetics.monitorSummary.failed": "Échoué", - "xpack.synthetics.monitorSummary.history": "Historique", - "xpack.synthetics.monitorSummary.pending": "En attente", "xpack.synthetics.monitorSummary.runTestManually": "Exécuter le test manuellement", - "xpack.synthetics.monitorSummary.succeeded": "Réussi", - "xpack.synthetics.monitorSummary.summary": "Résumé", - "xpack.synthetics.monitorSummary.up": "Opérationnel", - "xpack.synthetics.monitorSummary.waiting": "En attente du résultat du test.", "xpack.synthetics.navigateToAlertingButton.content": "Gérer les règles", "xpack.synthetics.navigateToAlertingUi": "Quitter Uptime et accéder à la page de gestion Alerting", "xpack.synthetics.noDataConfig.beatsCard.description": "Monitorez de façon proactive la disponibilité de vos sites et services. Recevez des alertes et corrigez les problèmes plus rapidement pour optimiser l'expérience de vos utilisateurs.", @@ -32330,7 +32293,6 @@ "xpack.triggersActionsUI.fieldBrowser.viewSelected": "sélectionné", "xpack.triggersActionsUI.home.appTitle": "Règles et connecteurs", "xpack.triggersActionsUI.home.breadcrumbTitle": "Règles et connecteurs", - "xpack.triggersActionsUI.home.connectorsTabTitle": "Connecteurs", "xpack.triggersActionsUI.home.docsLinkText": "Documentation", "xpack.triggersActionsUI.home.rulesTabTitle": "Règles", "xpack.triggersActionsUI.home.sectionDescription": "Détecter les conditions à l'aide des règles, et entreprendre des actions à l'aide des connecteurs.", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index e920046b1b016..f5ef512297e2e 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -7487,7 +7487,6 @@ "xpack.apm.serviceDetails.metrics.errorsList.title": "エラー", "xpack.apm.serviceDetails.metrics.memoryUsageChartTitle": "システムメモリー使用状況", "xpack.apm.serviceDetails.metricsTabLabel": "メトリック", - "xpack.apm.serviceDetails.nodesTabLabel": "JVM", "xpack.apm.serviceDetails.overviewTabLabel": "概要", "xpack.apm.serviceDetails.transactionsTabLabel": "トランザクション", "xpack.apm.serviceGroup.allServices.title": "すべてのサービス", @@ -9267,10 +9266,6 @@ "xpack.cases.connecors.get.missingCaseConnectorErrorMessage": "オブジェクトタイプ「{id}」は登録されていません。", "xpack.cases.connecors.register.duplicateCaseConnectorErrorMessage": "オブジェクトタイプ「{id}」はすでに登録されています。", "xpack.cases.connectors.card.createCommentWarningDesc": "コメントを外部で共有するには、{connectorName}コネクターの[コメントURLを作成]および[コメントオブジェクトを作成]フィールドを構成します。", - "xpack.cases.connectors.cases.externalIncidentAdded": "({date}に{user}が追加)", - "xpack.cases.connectors.cases.externalIncidentCreated": "({date}に{user}が作成)", - "xpack.cases.connectors.cases.externalIncidentDefault": "({date}に{user}が作成)", - "xpack.cases.connectors.cases.externalIncidentUpdated": "({date}に{user}が更新)", "xpack.cases.connectors.jira.unableToGetIssueMessage": "ID {id}の問題を取得できません", "xpack.cases.containers.pushToExternalService": "{ serviceName }への送信が正常に完了しました", "xpack.cases.containers.syncCase": "\"{caseTitle}\"のアラートが同期されました", @@ -9294,7 +9289,6 @@ "xpack.cases.casesStats.mttr": "クローズまでの平均時間", "xpack.cases.casesStats.mttrDescription": "現在のアセットの平均期間(作成から終了まで)", "xpack.cases.caseTable.bulkActions": "一斉アクション", - "xpack.cases.caseTable.bulkActions.deleteSelectedTitle": "選択した項目を削除", "xpack.cases.caseTable.changeStatus": "ステータスの変更", "xpack.cases.caseTable.closed": "終了", "xpack.cases.caseTable.closedCases": "終了したケース", @@ -9550,10 +9544,7 @@ "xpack.cases.severity.medium": "中", "xpack.cases.severity.title": "深刻度", "xpack.cases.status.all": "すべてのステータス", - "xpack.cases.status.closed": "終了", "xpack.cases.status.iconAria": "ステータスの変更", - "xpack.cases.status.inProgress": "進行中", - "xpack.cases.status.open": "開く", "xpack.cases.userActions.attachmentNotRegisteredErrorMsg": "アラートタイプが登録されていません", "xpack.cases.userActions.defaultEventAttachmentTitle": "タイプの添付ファイルが追加されました", "xpack.crossClusterReplication.app.deniedPermissionDescription": "クラスター横断レプリケーションを使用するには、{clusterPrivilegesCount, plural, other {次のクラスター特権}}が必要です:{clusterPrivileges}。", @@ -11351,11 +11342,6 @@ "xpack.enterpriseSearch.content.callout.dismissButton": "閉じる", "xpack.enterpriseSearch.content.callout.title": "エンタープライズ サーチでのElasticsearchインデックスの概要", "xpack.enterpriseSearch.content.description": "エンタープライズ サーチでは、さまざまな方法で簡単にデータを検索可能にできます。Webクローラー、Elasticsearchインデックス、API、直接アップロード、サードパーティコネクターから選択します。", - "xpack.enterpriseSearch.content.index.createAppSearchEngine.button": "App Searchエンジンの作成", - "xpack.enterpriseSearch.content.index.dismiss.button": "閉じる", - "xpack.enterpriseSearch.content.index.indexCreatedCallout.info": "App Searchエンジンを使用して、新しいElasticsearchインデックスの検索エクスペリエンスを構築できます。", - "xpack.enterpriseSearch.content.index.indexCreatedCallout.title": "Elasticsearchインデックスは正常に作成されました", - "xpack.enterpriseSearch.content.index.readDocumentation.link": "ドキュメントを読む", "xpack.enterpriseSearch.content.index.searchEngines.createEngine": "新しいApp Searchエンジンの作成", "xpack.enterpriseSearch.content.index.searchEngines.label": "検索エンジン", "xpack.enterpriseSearch.content.index.searchEngines.viewEngines": "App Searchエンジンを表示", @@ -13429,12 +13415,6 @@ "xpack.fleet.externallyManagedLabel": "これは外部で管理されている統合ポリシーです。", "xpack.fleet.featureCatalogueDescription": "Elasticエージェントとの統合を追加して管理します", "xpack.fleet.featureCatalogueTitle": "Elasticエージェント統合を追加", - "xpack.fleet.featuredObsDesc": "複雑なアプリケーションパフォーマンスの問題を監視、検出、診断します。", - "xpack.fleet.featuredObsTitle": "Elastic APM", - "xpack.fleet.featuredSearchDesc": "エンタープライズ サーチWebクローラーを使用して、検索をWebサイトに追加します。", - "xpack.fleet.featuredSearchTitle": "Webクローラー", - "xpack.fleet.featuredSecurityDesc": "脅威防御、検出、深いセキュリティデータの可視化を実現し、ホストおよびクラウドワークロードを保護します。", - "xpack.fleet.featuredSecurityTitle": "エンドポイントとクラウドセキュリティ", "xpack.fleet.fleetServerCloudRequiredCallout.cloudDeploymentLink": "クラウド展開", "xpack.fleet.fleetServerCloudRequiredCallout.editDeploymentButtonLabel": "デプロイを編集", "xpack.fleet.fleetServerCloudRequiredCallout.guideLink": "FleetおよびElasticエージェントガイド", @@ -28467,9 +28447,6 @@ "xpack.securitySolution.inspectPatternDifferent": "この要素には、データビュー設定とは別の固有のインデックスパターンがあります。", "xpack.securitySolution.investigationEnrichment.requestError": "脅威インテリジェンスの要求中にエラーが発生しました", "xpack.securitySolution.ja3.fingerprint.ja3.fingerprintLabel": "ja3", - "xpack.securitySolution.kpiHost.enableHostRiskText": "その他のデータを表示するには、ホストリスクモジュールを有効にしてください", - "xpack.securitySolution.kpiHost.hostRiskData": "ホストリスクデータ", - "xpack.securitySolution.kpiHost.learnMore": "詳細", "xpack.securitySolution.kpiHosts.hosts.title": "ホスト", "xpack.securitySolution.kpiHosts.riskyHosts.errorMessage": "高リスクホストAPIの取得エラー", "xpack.securitySolution.kpiHosts.riskyHosts.inspectTitle": "高リスクホスト", @@ -28493,9 +28470,6 @@ "xpack.securitySolution.kpiNetwork.uniquePrivateIps.sourceChartLabel": "Src.", "xpack.securitySolution.kpiNetwork.uniquePrivateIps.sourceUnitLabel": "ソース", "xpack.securitySolution.kpiNetwork.uniquePrivateIps.title": "固有のプライベート IP", - "xpack.securitySolution.kpiUser.enableUserRiskText": "その他のデータを表示するには、ユーザーリスクモジュールを有効にしてください", - "xpack.securitySolution.kpiUser.learnMore": "詳細", - "xpack.securitySolution.kpiUser.userRiskData": "ユーザーリスクデータ", "xpack.securitySolution.kpiUsers.totalUsers.errorSearchDescription": "統計ユーザーKPI検索でエラーが発生しました", "xpack.securitySolution.kpiUsers.totalUsers.title": "ユーザー", "xpack.securitySolution.kubernetes.columnContainer": "コンテナー", @@ -30602,8 +30576,6 @@ "xpack.synthetics.monitorRoute.title": "モニター | {baseTitle}", "xpack.synthetics.monitorStatusBar.locations.oneLocStatus": "{loc}場所での{status}", "xpack.synthetics.monitorStatusBar.locations.upStatus": "{loc}場所での{status}", - "xpack.synthetics.monitorSummary.lastRunLocation": "{loc}で。", - "xpack.synthetics.monitorSummary.lastRunTime": "前回実行日時:{time}", "xpack.synthetics.overview.alerts.enabled.success.description": "この監視が停止しているときには、メッセージが {actionConnectors} に送信されます。", "xpack.synthetics.overview.durationMsFormatting": "{millis}ミリ秒", "xpack.synthetics.overview.durationSecondsFormatting": "{seconds}秒", @@ -31343,16 +31315,7 @@ "xpack.synthetics.monitorStatusBar.timestampFromNowTextAriaLabel": "最終確認からの経過時間", "xpack.synthetics.monitorStatusBar.type.ariaLabel": "モニタータイプ", "xpack.synthetics.monitorStatusBar.type.label": "型", - "xpack.synthetics.monitorSummary.down": "ダウン", - "xpack.synthetics.monitorSummary.errors": "エラー", - "xpack.synthetics.monitorSummary.failed": "失敗", - "xpack.synthetics.monitorSummary.history": "履歴", - "xpack.synthetics.monitorSummary.pending": "保留中", "xpack.synthetics.monitorSummary.runTestManually": "手動でテストを実行", - "xpack.synthetics.monitorSummary.succeeded": "成功", - "xpack.synthetics.monitorSummary.summary": "まとめ", - "xpack.synthetics.monitorSummary.up": "アップ", - "xpack.synthetics.monitorSummary.waiting": "テスト実行結果を待機しています。", "xpack.synthetics.navigateToAlertingButton.content": "ルールの管理", "xpack.synthetics.navigateToAlertingUi": "Uptime を離れてアラート管理ページに移動します", "xpack.synthetics.noDataConfig.beatsCard.description": "サイトとサービスの可用性をアクティブに監視するアラートを受信し、問題をより迅速に解決して、ユーザーエクスペリエンスを最適化します。", @@ -32304,7 +32267,6 @@ "xpack.triggersActionsUI.fieldBrowser.viewSelected": "選択済み", "xpack.triggersActionsUI.home.appTitle": "ルールとコネクター", "xpack.triggersActionsUI.home.breadcrumbTitle": "ルールとコネクター", - "xpack.triggersActionsUI.home.connectorsTabTitle": "コネクター", "xpack.triggersActionsUI.home.docsLinkText": "ドキュメント", "xpack.triggersActionsUI.home.rulesTabTitle": "ルール", "xpack.triggersActionsUI.home.sectionDescription": "ルールを使用して条件を検出し、コネクターを使用してアクションを実行します。", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 76bca99b96d6a..e4f966a0a485f 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -7504,7 +7504,6 @@ "xpack.apm.serviceDetails.metrics.errorsList.title": "错误", "xpack.apm.serviceDetails.metrics.memoryUsageChartTitle": "系统内存使用", "xpack.apm.serviceDetails.metricsTabLabel": "指标", - "xpack.apm.serviceDetails.nodesTabLabel": "JVM", "xpack.apm.serviceDetails.overviewTabLabel": "概览", "xpack.apm.serviceDetails.transactionsTabLabel": "事务", "xpack.apm.serviceGroup.allServices.title": "所有服务", @@ -9285,10 +9284,6 @@ "xpack.cases.connecors.get.missingCaseConnectorErrorMessage": "对象类型“{id}”未注册。", "xpack.cases.connecors.register.duplicateCaseConnectorErrorMessage": "已注册对象类型“{id}”。", "xpack.cases.connectors.card.createCommentWarningDesc": "为 {connectorName} 连接器配置“创建注释 URL”和“创建注释对象”字段以在外部共享注释。", - "xpack.cases.connectors.cases.externalIncidentAdded": "(由 {user} 于 {date}添加)", - "xpack.cases.connectors.cases.externalIncidentCreated": "(由 {user} 于 {date}创建)", - "xpack.cases.connectors.cases.externalIncidentDefault": "(由 {user} 于 {date}创建)", - "xpack.cases.connectors.cases.externalIncidentUpdated": "(由 {user} 于 {date}更新)", "xpack.cases.connectors.jira.unableToGetIssueMessage": "无法获取 ID 为 {id} 的问题", "xpack.cases.containers.pushToExternalService": "已成功发送到 { serviceName }", "xpack.cases.containers.syncCase": "“{caseTitle}”中的告警已同步", @@ -9312,7 +9307,6 @@ "xpack.cases.casesStats.mttr": "平均关闭时间", "xpack.cases.casesStats.mttrDescription": "当前案例的平均持续时间(从创建到关闭)", "xpack.cases.caseTable.bulkActions": "批处理操作", - "xpack.cases.caseTable.bulkActions.deleteSelectedTitle": "删除所选", "xpack.cases.caseTable.changeStatus": "更改状态", "xpack.cases.caseTable.closed": "已关闭", "xpack.cases.caseTable.closedCases": "已关闭案例", @@ -9568,10 +9562,7 @@ "xpack.cases.severity.medium": "中", "xpack.cases.severity.title": "严重性", "xpack.cases.status.all": "所有状态", - "xpack.cases.status.closed": "已关闭", "xpack.cases.status.iconAria": "更改状态", - "xpack.cases.status.inProgress": "进行中", - "xpack.cases.status.open": "打开", "xpack.cases.userActions.attachmentNotRegisteredErrorMsg": "未注册附件类型", "xpack.cases.userActions.defaultEventAttachmentTitle": "已添加以下类型的附件", "xpack.crossClusterReplication.app.deniedPermissionDescription": "要使用跨集群复制,您必须具有{clusterPrivilegesCount, plural, other {以下集群权限}}:{clusterPrivileges}。", @@ -11370,11 +11361,6 @@ "xpack.enterpriseSearch.content.callout.dismissButton": "关闭", "xpack.enterpriseSearch.content.callout.title": "在 Enterprise Search 中引入 Elasticsearch 索引", "xpack.enterpriseSearch.content.description": "Enterprise Search 提供了各种方法以便您轻松搜索数据。从网络爬虫、Elasticsearch 索引、API、直接上传或第三方连接器中选择。", - "xpack.enterpriseSearch.content.index.createAppSearchEngine.button": "创建 App Search 引擎", - "xpack.enterpriseSearch.content.index.dismiss.button": "关闭", - "xpack.enterpriseSearch.content.index.indexCreatedCallout.info": "您可以使用 App Search 引擎为您的新 Elasticsearch 索引构建搜索体验。", - "xpack.enterpriseSearch.content.index.indexCreatedCallout.title": "已成功创建 Elasticsearch 索引", - "xpack.enterpriseSearch.content.index.readDocumentation.link": "阅读文档", "xpack.enterpriseSearch.content.index.searchEngines.createEngine": "创建新的 App Search 引擎", "xpack.enterpriseSearch.content.index.searchEngines.label": "搜索引擎", "xpack.enterpriseSearch.content.index.searchEngines.viewEngines": "查看 App Search 引擎", @@ -13449,12 +13435,6 @@ "xpack.fleet.externallyManagedLabel": "这是外部托管的集成策略。", "xpack.fleet.featureCatalogueDescription": "添加和管理 Elastic 代理集成", "xpack.fleet.featureCatalogueTitle": "添加 Elastic 代理集成", - "xpack.fleet.featuredObsDesc": "监测、检测并诊断复杂的应用程序性能问题。", - "xpack.fleet.featuredObsTitle": "Elastic APM", - "xpack.fleet.featuredSearchDesc": "通过 Enterprise Search 网络爬虫将搜索功能添加到您的网站。", - "xpack.fleet.featuredSearchTitle": "网络爬虫", - "xpack.fleet.featuredSecurityDesc": "使用威胁防御、检测和深度安全数据可见性功能保护您的主机和云工作负载。", - "xpack.fleet.featuredSecurityTitle": "终端和云安全", "xpack.fleet.fleetServerCloudRequiredCallout.cloudDeploymentLink": "云部署", "xpack.fleet.fleetServerCloudRequiredCallout.editDeploymentButtonLabel": "编辑部署", "xpack.fleet.fleetServerCloudRequiredCallout.guideLink": "Fleet 和 Elastic 代理指南", @@ -28501,9 +28481,6 @@ "xpack.securitySolution.inspectPatternDifferent": "此元素具有与数据视图设置不同的唯一索引模式。", "xpack.securitySolution.investigationEnrichment.requestError": "请求威胁情报时发生错误", "xpack.securitySolution.ja3.fingerprint.ja3.fingerprintLabel": "ja3", - "xpack.securitySolution.kpiHost.enableHostRiskText": "启用主机风险模块以查看更多数据", - "xpack.securitySolution.kpiHost.hostRiskData": "主机风险数据", - "xpack.securitySolution.kpiHost.learnMore": "详细了解", "xpack.securitySolution.kpiHosts.hosts.title": "主机", "xpack.securitySolution.kpiHosts.riskyHosts.errorMessage": "提取有风险主机 API 时出错", "xpack.securitySolution.kpiHosts.riskyHosts.inspectTitle": "有风险主机", @@ -28527,9 +28504,6 @@ "xpack.securitySolution.kpiNetwork.uniquePrivateIps.sourceChartLabel": "源", "xpack.securitySolution.kpiNetwork.uniquePrivateIps.sourceUnitLabel": "源", "xpack.securitySolution.kpiNetwork.uniquePrivateIps.title": "唯一专用 IP", - "xpack.securitySolution.kpiUser.enableUserRiskText": "启用用户风险模块以查看更多数据", - "xpack.securitySolution.kpiUser.learnMore": "详细了解", - "xpack.securitySolution.kpiUser.userRiskData": "用户风险数据", "xpack.securitySolution.kpiUsers.totalUsers.errorSearchDescription": "搜索总体用户 KPI 时发生错误", "xpack.securitySolution.kpiUsers.totalUsers.title": "用户", "xpack.securitySolution.kubernetes.columnContainer": "容器", @@ -30637,8 +30611,6 @@ "xpack.synthetics.monitorRoute.title": "监测 | {baseTitle}", "xpack.synthetics.monitorStatusBar.locations.oneLocStatus": "在 {loc} 位置处于 {status}", "xpack.synthetics.monitorStatusBar.locations.upStatus": "在 {loc} 位置处于 {status}", - "xpack.synthetics.monitorSummary.lastRunLocation": "在 {loc} 中。", - "xpack.synthetics.monitorSummary.lastRunTime": "上次运行时间:{time}", "xpack.synthetics.overview.alerts.enabled.success.description": "此监测关闭时,将有消息发送到 {actionConnectors}。", "xpack.synthetics.overview.durationMsFormatting": "{millis} 毫秒", "xpack.synthetics.overview.durationSecondsFormatting": "{seconds} 秒", @@ -31378,16 +31350,7 @@ "xpack.synthetics.monitorStatusBar.timestampFromNowTextAriaLabel": "自上次检查以来经过的时间", "xpack.synthetics.monitorStatusBar.type.ariaLabel": "监测类型", "xpack.synthetics.monitorStatusBar.type.label": "类型", - "xpack.synthetics.monitorSummary.down": "关闭", - "xpack.synthetics.monitorSummary.errors": "错误", - "xpack.synthetics.monitorSummary.failed": "失败", - "xpack.synthetics.monitorSummary.history": "历史记录", - "xpack.synthetics.monitorSummary.pending": "待处理", "xpack.synthetics.monitorSummary.runTestManually": "手动运行测试", - "xpack.synthetics.monitorSummary.succeeded": "成功", - "xpack.synthetics.monitorSummary.summary": "摘要", - "xpack.synthetics.monitorSummary.up": "运行", - "xpack.synthetics.monitorSummary.waiting": "等待测试运行结果。", "xpack.synthetics.navigateToAlertingButton.content": "管理规则", "xpack.synthetics.navigateToAlertingUi": "离开 Uptime 并前往“Alerting 管理”页面", "xpack.synthetics.noDataConfig.beatsCard.description": "主动监测站点和服务的可用性。接收告警并更快地解决问题,从而优化用户体验。", @@ -32341,7 +32304,6 @@ "xpack.triggersActionsUI.fieldBrowser.viewSelected": "已选定", "xpack.triggersActionsUI.home.appTitle": "规则和连接器", "xpack.triggersActionsUI.home.breadcrumbTitle": "规则和连接器", - "xpack.triggersActionsUI.home.connectorsTabTitle": "连接器", "xpack.triggersActionsUI.home.docsLinkText": "文档", "xpack.triggersActionsUI.home.rulesTabTitle": "规则", "xpack.triggersActionsUI.home.sectionDescription": "使规则检测条件,并使用连接器采取操作。", diff --git a/x-pack/plugins/triggers_actions_ui/public/application/app.tsx b/x-pack/plugins/triggers_actions_ui/public/application/app.tsx index 5f2dcfcb5ff62..d0c61c884e528 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/app.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/app.tsx @@ -31,11 +31,17 @@ import { AlertsTableConfigurationRegistryContract, RuleTypeRegistryContract, } from '../types'; -import { Section, routeToRuleDetails, legacyRouteToRuleDetails } from './constants'; +import { + Section, + routeToRuleDetails, + legacyRouteToRuleDetails, + routeToConnectors, +} from './constants'; import { setDataViewsService } from '../common/lib/data_apis'; import { KibanaContextProvider, useKibana } from '../common/lib/kibana'; import { ConnectorProvider } from './context/connector_context'; +import { CONNECTORS_PLUGIN_ID } from '../common/constants'; const TriggersActionsUIHome = lazy(() => import('./home')); const RuleDetailsRoute = lazy( @@ -73,7 +79,7 @@ export const renderApp = (deps: TriggersAndActionsUiServices) => { export const App = ({ deps }: { deps: TriggersAndActionsUiServices }) => { const { dataViews, uiSettings, theme$ } = deps; - const sections: Section[] = ['rules', 'connectors', 'logs', 'alerts']; + const sections: Section[] = ['rules', 'logs', 'alerts']; const isDarkMode = useObservable(uiSettings.get$('theme:darkMode')); const sectionsRegex = sections.join('|'); @@ -96,6 +102,7 @@ export const App = ({ deps }: { deps: TriggersAndActionsUiServices }) => { export const AppWithoutRouter = ({ sectionsRegex }: { sectionsRegex: string }) => { const { actions: { validateEmailAddresses }, + application: { navigateToApp }, } = useKibana().services; return ( @@ -114,6 +121,15 @@ export const AppWithoutRouter = ({ sectionsRegex }: { sectionsRegex: string }) = path={legacyRouteToRuleDetails} render={({ match }) => } /> + { + navigateToApp(`management/insightsAndAlerting/${CONNECTORS_PLUGIN_ID}`); + return null; + }} + /> + diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/prompts/empty_connectors_prompt.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/prompts/empty_connectors_prompt.tsx index 4637b6aa1d801..f6b149328db97 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/prompts/empty_connectors_prompt.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/prompts/empty_connectors_prompt.tsx @@ -7,11 +7,25 @@ import { FormattedMessage } from '@kbn/i18n-react'; import React from 'react'; -import { EuiButton, EuiEmptyPrompt, EuiIcon, EuiSpacer, EuiTitle } from '@elastic/eui'; +import { + EuiButton, + EuiButtonEmpty, + EuiPageTemplate, + EuiIcon, + EuiSpacer, + EuiTitle, +} from '@elastic/eui'; +import { DocLinksStart } from '@kbn/core-doc-links-browser'; import './empty_connectors_prompt.scss'; -export const EmptyConnectorsPrompt = ({ onCTAClicked }: { onCTAClicked: () => void }) => ( - void; + docLinks: DocLinksStart; +}) => ( + @@ -33,24 +47,39 @@ export const EmptyConnectorsPrompt = ({ onCTAClicked }: { onCTAClicked: () => vo

} actions={ - - - + <> + + + +
+ + + + } /> ); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/connectors_app.tsx b/x-pack/plugins/triggers_actions_ui/public/application/connectors_app.tsx new file mode 100644 index 0000000000000..78b2559cc3dec --- /dev/null +++ b/x-pack/plugins/triggers_actions_ui/public/application/connectors_app.tsx @@ -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 React, { lazy } from 'react'; +import { Switch, Route, Router } from 'react-router-dom'; +import { ChromeBreadcrumb, CoreStart, CoreTheme, ScopedHistory } from '@kbn/core/public'; +import { render, unmountComponentAtNode } from 'react-dom'; +import { I18nProvider } from '@kbn/i18n-react'; +import useObservable from 'react-use/lib/useObservable'; +import { Observable } from 'rxjs'; +import { KibanaFeature } from '@kbn/features-plugin/common'; +import { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public'; +import { ChartsPluginStart } from '@kbn/charts-plugin/public'; +import { DataPublicPluginStart } from '@kbn/data-plugin/public'; +import { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public'; +import type { DataViewEditorStart } from '@kbn/data-view-editor-plugin/public'; +import { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/public'; +import { PluginStartContract as AlertingStart } from '@kbn/alerting-plugin/public'; +import type { SpacesPluginStart } from '@kbn/spaces-plugin/public'; + +import { Storage } from '@kbn/kibana-utils-plugin/public'; +import { EuiThemeProvider } from '@kbn/kibana-react-plugin/common'; +import { ActionsPublicPluginSetup } from '@kbn/actions-plugin/public'; +import { suspendedComponentWithProps } from './lib/suspended_component_with_props'; +import { + ActionTypeRegistryContract, + AlertsTableConfigurationRegistryContract, + RuleTypeRegistryContract, +} from '../types'; + +import { setDataViewsService } from '../common/lib/data_apis'; +import { KibanaContextProvider, useKibana } from '../common/lib/kibana'; +import { ConnectorProvider } from './context/connector_context'; + +const ActionsConnectorsList = lazy( + () => import('./sections/actions_connectors_list/components/actions_connectors_list') +); + +export interface TriggersAndActionsUiServices extends CoreStart { + actions: ActionsPublicPluginSetup; + data: DataPublicPluginStart; + dataViews: DataViewsPublicPluginStart; + dataViewEditor: DataViewEditorStart; + charts: ChartsPluginStart; + alerting?: AlertingStart; + spaces?: SpacesPluginStart; + storage?: Storage; + isCloud: boolean; + setBreadcrumbs: (crumbs: ChromeBreadcrumb[]) => void; + actionTypeRegistry: ActionTypeRegistryContract; + ruleTypeRegistry: RuleTypeRegistryContract; + alertsTableConfigurationRegistry: AlertsTableConfigurationRegistryContract; + history: ScopedHistory; + kibanaFeatures: KibanaFeature[]; + element: HTMLElement; + theme$: Observable; + unifiedSearch: UnifiedSearchPublicPluginStart; +} + +export const renderApp = (deps: TriggersAndActionsUiServices) => { + const { element } = deps; + render(, element); + return () => { + unmountComponentAtNode(element); + }; +}; + +export const App = ({ deps }: { deps: TriggersAndActionsUiServices }) => { + const { dataViews, uiSettings, theme$ } = deps; + const isDarkMode = useObservable(uiSettings.get$('theme:darkMode')); + + setDataViewsService(dataViews); + return ( + + + + + + + + + + + + ); +}; + +export const AppWithoutRouter = () => { + const { + actions: { validateEmailAddresses }, + } = useKibana().services; + + return ( + + + + + + ); +}; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/constants/plugin.ts b/x-pack/plugins/triggers_actions_ui/public/application/constants/plugin.ts index bf5cf6d58c69c..93ba3dd88b709 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/constants/plugin.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/constants/plugin.ts @@ -9,7 +9,7 @@ export const PLUGIN = { ID: 'triggersActionsUi', getI18nName: (i18n: any): string => { return i18n.translate('xpack.triggersActionsUI.appName', { - defaultMessage: 'Rules and Connectors', + defaultMessage: 'Rules', }); }, }; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/home.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/home.test.tsx index 0024fef8ac125..83c856663f8f8 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/home.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/home.test.tsx @@ -69,8 +69,8 @@ describe('home', () => { let home = mountWithIntl(); - // Just rules/connectors - expect(home.find('.euiTab__content').length).toBe(3); + // Just rules/logs + expect(home.find('.euiTab__content').length).toBe(2); (getIsExperimentalFeatureEnabled as jest.Mock).mockImplementation((feature: string) => { if (feature === 'internalAlertsTable') { @@ -81,6 +81,6 @@ describe('home', () => { home = mountWithIntl(); // alerts now too! - expect(home.find('.euiTab__content').length).toBe(4); + expect(home.find('.euiTab__content').length).toBe(3); }); }); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/home.tsx b/x-pack/plugins/triggers_actions_ui/public/application/home.tsx index 8963e63eb44fc..894db7ce5a59e 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/home.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/home.tsx @@ -11,25 +11,15 @@ import { FormattedMessage } from '@kbn/i18n-react'; import { EuiSpacer, EuiButtonEmpty, EuiPageHeader } from '@elastic/eui'; import { getIsExperimentalFeatureEnabled } from '../common/get_experimental_features'; -import { - Section, - routeToConnectors, - routeToRules, - routeToInternalAlerts, - routeToLogs, -} from './constants'; +import { Section, routeToRules, routeToInternalAlerts, routeToLogs } from './constants'; import { getAlertingSectionBreadcrumb } from './lib/breadcrumb'; import { getCurrentDocTitle } from './lib/doc_title'; -import { hasShowActionsCapability } from './lib/capabilities'; import { HealthCheck } from './components/health_check'; import { HealthContextProvider } from './context/health_context'; import { useKibana } from '../common/lib/kibana'; import { suspendedComponentWithProps } from './lib/suspended_component_with_props'; -const ActionsConnectorsList = lazy( - () => import('./sections/actions_connectors_list/components/actions_connectors_list') -); const RulesList = lazy(() => import('./sections/rules_list/components/rules_list')); const LogsList = lazy(() => import('./sections/logs_list/components/logs_list')); const AlertsPage = lazy(() => import('./sections/alerts_table/alerts_page')); @@ -44,16 +34,9 @@ export const TriggersActionsUIHome: React.FunctionComponent { - const { - chrome, - application: { capabilities }, - - setBreadcrumbs, - docLinks, - } = useKibana().services; + const { chrome, setBreadcrumbs, docLinks } = useKibana().services; const isInternalAlertsTableEnabled = getIsExperimentalFeatureEnabled('internalAlertsTable'); - const canShowActions = hasShowActionsCapability(capabilities); const tabs: Array<{ id: Section; name: React.ReactNode; @@ -66,18 +49,6 @@ export const TriggersActionsUIHome: React.FunctionComponent - ), - }); - } - tabs.push({ id: 'logs', name: , @@ -111,10 +82,7 @@ export const TriggersActionsUIHome: React.FunctionComponent - + } rightSideItems={[ @@ -133,7 +101,7 @@ export const TriggersActionsUIHome: React.FunctionComponent } tabs={tabs.map((tab) => ({ @@ -155,13 +123,6 @@ export const TriggersActionsUIHome: React.FunctionComponent - {canShowActions && ( - - )} { }); expect(getAlertingSectionBreadcrumb('home', true)).toMatchObject({ text: i18n.translate('xpack.triggersActionsUI.home.breadcrumbTitle', { - defaultMessage: 'Rules and Connectors', + defaultMessage: 'Rules', }), href: `${routeToHome}`, }); @@ -44,7 +44,7 @@ describe('getAlertingSectionBreadcrumb', () => { }); expect(getAlertingSectionBreadcrumb('home', false)).toMatchObject({ text: i18n.translate('xpack.triggersActionsUI.home.breadcrumbTitle', { - defaultMessage: 'Rules and Connectors', + defaultMessage: 'Rules', }), }); }); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/breadcrumb.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/breadcrumb.ts index 46a15b12bb733..c0b9551968870 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/breadcrumb.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/breadcrumb.ts @@ -6,7 +6,7 @@ */ import { i18n } from '@kbn/i18n'; -import { routeToHome, routeToConnectors, routeToRules } from '../constants'; +import { routeToHome, routeToConnectors, routeToRules, routeToLogs } from '../constants'; export const getAlertingSectionBreadcrumb = ( type: string, @@ -14,6 +14,17 @@ export const getAlertingSectionBreadcrumb = ( ): { text: string; href?: string } => { // Home and sections switch (type) { + case 'logs': + return { + text: i18n.translate('xpack.triggersActionsUI.logs.breadcrumbTitle', { + defaultMessage: 'Logs', + }), + ...(returnHref + ? { + href: `${routeToLogs}`, + } + : {}), + }; case 'connectors': return { text: i18n.translate('xpack.triggersActionsUI.connectors.breadcrumbTitle', { @@ -39,7 +50,7 @@ export const getAlertingSectionBreadcrumb = ( default: return { text: i18n.translate('xpack.triggersActionsUI.home.breadcrumbTitle', { - defaultMessage: 'Rules and Connectors', + defaultMessage: 'Rules', }), ...(returnHref ? { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/doc_title.test.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/doc_title.test.ts index af352de0cc6e7..8d4996ceb8259 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/doc_title.test.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/doc_title.test.ts @@ -9,7 +9,7 @@ import { getCurrentDocTitle } from './doc_title'; describe('getCurrentDocTitle', () => { test('if change calls return the proper doc title ', async () => { - expect(getCurrentDocTitle('home') === 'Rules and Connectors').toBeTruthy(); + expect(getCurrentDocTitle('home') === 'Rules').toBeTruthy(); expect(getCurrentDocTitle('connectors') === 'Connectors').toBeTruthy(); expect(getCurrentDocTitle('rules') === 'Rules').toBeTruthy(); }); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/doc_title.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/doc_title.ts index fab9e19c8acee..16699e750d223 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/doc_title.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/doc_title.ts @@ -11,6 +11,11 @@ export const getCurrentDocTitle = (page: string): string => { let updatedTitle: string; switch (page) { + case 'logs': + updatedTitle = i18n.translate('xpack.triggersActionsUI.logs.breadcrumbTitle', { + defaultMessage: 'Logs', + }); + break; case 'connectors': updatedTitle = i18n.translate('xpack.triggersActionsUI.connectors.breadcrumbTitle', { defaultMessage: 'Connectors', @@ -23,7 +28,7 @@ export const getCurrentDocTitle = (page: string): string => { break; default: updatedTitle = i18n.translate('xpack.triggersActionsUI.home.breadcrumbTitle', { - defaultMessage: 'Rules and Connectors', + defaultMessage: 'Rules', }); } return updatedTitle; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/get_filter.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/get_filter.ts index 65ace4fa72c7b..19551982ca000 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/get_filter.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/get_filter.ts @@ -23,7 +23,7 @@ export const getFilter = ({ } if (outcomeFilter && outcomeFilter.length) { - filter.push(`event.outcome: ${outcomeFilter.join(' or ')}`); + filter.push(getOutcomeFilter(outcomeFilter)); } if (runId) { @@ -32,3 +32,13 @@ export const getFilter = ({ return filter; }; + +function getOutcomeFilter(outcomeFilter: string[]) { + const filterMapping: Record = { + failure: 'event.outcome: failure', + warning: 'kibana.alerting.outcome: warning', + success: + 'kibana.alerting.outcome:success OR (event.outcome: success AND NOT kibana.alerting.outcome:*)', + }; + return `${outcomeFilter.map((f) => filterMapping[f]).join(' OR ')}`; +} diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/load_execution_log_aggregations.test.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/load_execution_log_aggregations.test.ts index 7eccd9be2955b..c40f0a0b2735d 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/load_execution_log_aggregations.test.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/load_execution_log_aggregations.test.ts @@ -47,7 +47,7 @@ describe('loadExecutionLogAggregations', () => { id: 'test-id', dateStart: '2022-03-23T16:17:53.482Z', dateEnd: '2022-03-23T16:17:53.482Z', - outcomeFilter: ['success', 'unknown'], + outcomeFilter: ['success'], perPage: 10, page: 0, sort: [sortTimestamp], @@ -84,7 +84,7 @@ describe('loadExecutionLogAggregations', () => { "query": Object { "date_end": "2022-03-23T16:17:53.482Z", "date_start": "2022-03-23T16:17:53.482Z", - "filter": "event.outcome: success or unknown", + "filter": "kibana.alerting.outcome:success OR (event.outcome: success AND NOT kibana.alerting.outcome:*)", "page": 1, "per_page": 10, "sort": "[{\\"timestamp\\":{\\"order\\":\\"asc\\"}}]", diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/actions_connectors_list/components/actions_connectors_list.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/actions_connectors_list/components/actions_connectors_list.tsx index e973fce282dcb..55885aa3c14c3 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/actions_connectors_list/components/actions_connectors_list.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/actions_connectors_list/components/actions_connectors_list.tsx @@ -22,6 +22,7 @@ import { Criteria, EuiButtonEmpty, EuiBadge, + EuiPageTemplate, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { omit } from 'lodash'; @@ -52,6 +53,8 @@ import { } from '../../../../common/connectors_selection'; import { CreateConnectorFlyout } from '../../action_connector_form/create_connector_flyout'; import { EditConnectorFlyout } from '../../action_connector_form/edit_connector_flyout'; +import { getAlertingSectionBreadcrumb } from '../../../lib/breadcrumb'; +import { getCurrentDocTitle } from '../../../lib/doc_title'; const ConnectorIconTipWithSpacing = withTheme(({ theme }: { theme: EuiTheme }) => { return ( @@ -83,6 +86,9 @@ const ActionsConnectorsList: React.FunctionComponent = () => { notifications: { toasts }, application: { capabilities }, actionTypeRegistry, + setBreadcrumbs, + chrome, + docLinks, } = useKibana().services; const canDelete = hasDeleteActionsCapability(capabilities); const canExecute = hasExecuteActionsCapability(capabilities); @@ -107,6 +113,12 @@ const ActionsConnectorsList: React.FunctionComponent = () => { }, []); const [showWarningText, setShowWarningText] = useState(false); + // Set breadcrumb and page title + useEffect(() => { + setBreadcrumbs([getAlertingSectionBreadcrumb('connectors')]); + chrome.docTitle.change(getCurrentDocTitle('connectors')); + }, [chrome, setBreadcrumbs]); + useEffect(() => { (async () => { try { @@ -428,110 +440,144 @@ const ActionsConnectorsList: React.FunctionComponent = () => { />
, ], - toolsRight: canSave - ? [ - setAddFlyoutVisibility(true)} - > - - , - ] - : [], }} /> ); return ( -
- { - if (selectedItems.length === 0 || selectedItems.length === deleted.length) { - const updatedActions = actions.filter( - (action) => action.id && !connectorsToDelete.includes(action.id) - ); - setActions(updatedActions); - setSelectedItems([]); - } - setConnectorsToDelete([]); - }} - onErrors={async () => { - // Refresh the actions from the server, some actions may have beend deleted - await loadActions(); - setConnectorsToDelete([]); - }} - onCancel={async () => { - setConnectorsToDelete([]); - }} - apiDeleteCall={deleteActions} - idsToDelete={connectorsToDelete} - singleTitle={i18n.translate( - 'xpack.triggersActionsUI.sections.actionsConnectorsList.singleTitle', - { defaultMessage: 'connector' } - )} - multipleTitle={i18n.translate( - 'xpack.triggersActionsUI.sections.actionsConnectorsList.multipleTitle', - { defaultMessage: 'connectors' } - )} - showWarningText={showWarningText} - warningText={i18n.translate( - 'xpack.triggersActionsUI.sections.actionsConnectorsList.warningText', - { - defaultMessage: - '{connectors, plural, one {This connector is} other {Some connectors are}} currently in use.', - values: { - connectors: connectorsToDelete.length, - }, - } - )} - setIsLoadingState={(isLoading: boolean) => setIsLoadingActionTypes(isLoading)} - /> - - - {/* Render the view based on if there's data or if they can save */} - {(isLoadingActions || isLoadingActionTypes) && } - {actionConnectorTableItems.length !== 0 && table} - {actionConnectorTableItems.length === 0 && - canSave && - !isLoadingActions && - !isLoadingActionTypes && ( - setAddFlyoutVisibility(true)} /> - )} - {actionConnectorTableItems.length === 0 && !canSave && } - {addFlyoutVisible ? ( - { - setAddFlyoutVisibility(false); - }} - onTestConnector={(connector) => editItem(connector, EditConnectorTabs.Test)} - onConnectorCreated={loadActions} - actionTypeRegistry={actionTypeRegistry} + <> + {actionConnectorTableItems.length !== 0 && ( + setAddFlyoutVisibility(true)} + iconType="plusInCircle" + > + + , + ] + : [] + ).concat([ + + + , + ])} /> - ) : null} - {editConnectorProps.initialConnector ? ( - { - setEditConnectorProps(omit(editConnectorProps, 'initialConnector')); + )} + + { + if (selectedItems.length === 0 || selectedItems.length === deleted.length) { + const updatedActions = actions.filter( + (action) => action.id && !connectorsToDelete.includes(action.id) + ); + setActions(updatedActions); + setSelectedItems([]); + } + setConnectorsToDelete([]); }} - onConnectorUpdated={(connector) => { - setEditConnectorProps({ ...editConnectorProps, initialConnector: connector }); - loadActions(); + onErrors={async () => { + // Refresh the actions from the server, some actions may have beend deleted + await loadActions(); + setConnectorsToDelete([]); }} - actionTypeRegistry={actionTypeRegistry} + onCancel={async () => { + setConnectorsToDelete([]); + }} + apiDeleteCall={deleteActions} + idsToDelete={connectorsToDelete} + singleTitle={i18n.translate( + 'xpack.triggersActionsUI.sections.actionsConnectorsList.singleTitle', + { defaultMessage: 'connector' } + )} + multipleTitle={i18n.translate( + 'xpack.triggersActionsUI.sections.actionsConnectorsList.multipleTitle', + { defaultMessage: 'connectors' } + )} + showWarningText={showWarningText} + warningText={i18n.translate( + 'xpack.triggersActionsUI.sections.actionsConnectorsList.warningText', + { + defaultMessage: + '{connectors, plural, one {This connector is} other {Some connectors are}} currently in use.', + values: { + connectors: connectorsToDelete.length, + }, + } + )} + setIsLoadingState={(isLoading: boolean) => setIsLoadingActionTypes(isLoading)} /> - ) : null} -
+ + + {/* Render the view based on if there's data or if they can save */} + {(isLoadingActions || isLoadingActionTypes) && } + {actionConnectorTableItems.length !== 0 && table} + {actionConnectorTableItems.length === 0 && + canSave && + !isLoadingActions && + !isLoadingActionTypes && ( + setAddFlyoutVisibility(true)} + docLinks={docLinks} + /> + )} + {actionConnectorTableItems.length === 0 && !canSave && } + {addFlyoutVisible ? ( + { + setAddFlyoutVisibility(false); + }} + onTestConnector={(connector) => editItem(connector, EditConnectorTabs.Test)} + onConnectorCreated={loadActions} + actionTypeRegistry={actionTypeRegistry} + /> + ) : null} + {editConnectorProps.initialConnector ? ( + { + setEditConnectorProps(omit(editConnectorProps, 'initialConnector')); + }} + onConnectorUpdated={(connector) => { + setEditConnectorProps({ ...editConnectorProps, initialConnector: connector }); + loadActions(); + }} + actionTypeRegistry={actionTypeRegistry} + /> + ) : null} + + ); }; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule.tsx index db82f36cbc90c..02c740d2b6cc8 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule.tsx @@ -103,7 +103,12 @@ export function RuleComponent({ defaultMessage: 'Alerts', }), 'data-test-subj': 'ruleAlertListTab', - content: renderRuleAlertList(), + content: ( + <> + + {renderRuleAlertList()} + + ), }, { id: EVENT_LOG_LIST_TAB, diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_event_log_list.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_event_log_list.tsx index 90a721423e848..aec6566d58668 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_event_log_list.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_event_log_list.tsx @@ -77,6 +77,7 @@ export const RuleEventLogList = ( requestRefresh={requestRefresh} fetchRuleSummary={fetchRuleSummary} /> + ; + return ; } if (columnId === 'timestamp') { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_event_log_list_kpi.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_event_log_list_kpi.test.tsx index f77494e4f3c12..c51109bd11514 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_event_log_list_kpi.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_event_log_list_kpi.test.tsx @@ -30,8 +30,9 @@ jest.mock('../../../lib/rule_api/load_global_execution_kpi_aggregations', () => const mockKpiResponse = { success: 4, - unknown: 10, + unknown: 0, failure: 60, + warning: 10, activeAlerts: 100, newAlerts: 40, recoveredAlerts: 30, @@ -62,7 +63,48 @@ describe('rule_event_log_list_kpi', () => { /> ); - expect(wrapper.find('[data-test-subj="centerJustifiedSpinner"]').exists()).toBeTruthy(); + expect( + wrapper + .find('[data-test-subj="ruleEventLogKpi-successOutcome"] .euiStat__title') + .first() + .text() + ).toEqual('--'); + expect( + wrapper + .find('[data-test-subj="ruleEventLogKpi-warningOutcome"] .euiStat__title') + .first() + .text() + ).toEqual('--'); + expect( + wrapper + .find('[data-test-subj="ruleEventLogKpi-failureOutcome"] .euiStat__title') + .first() + .text() + ).toEqual('--'); + expect( + wrapper.find('[data-test-subj="ruleEventLogKpi-activeAlerts"] .euiStat__title').first().text() + ).toEqual('--'); + expect( + wrapper.find('[data-test-subj="ruleEventLogKpi-newAlerts"] .euiStat__title').first().text() + ).toEqual('--'); + expect( + wrapper + .find('[data-test-subj="ruleEventLogKpi-recoveredAlerts"] .euiStat__title') + .first() + .text() + ).toEqual('--'); + expect( + wrapper + .find('[data-test-subj="ruleEventLogKpi-erroredActions"] .euiStat__title') + .first() + .text() + ).toEqual('--'); + expect( + wrapper + .find('[data-test-subj="ruleEventLogKpi-triggeredActions"] .euiStat__title') + .first() + .text() + ).toEqual('--'); // Let the load resolve await act(async () => { @@ -70,8 +112,6 @@ describe('rule_event_log_list_kpi', () => { wrapper.update(); }); - expect(wrapper.find('[data-test-subj="centerJustifiedSpinner"]').exists()).toBeFalsy(); - expect(loadExecutionKPIAggregationsMock).toHaveBeenCalledWith( expect.objectContaining({ id: '123', @@ -90,10 +130,10 @@ describe('rule_event_log_list_kpi', () => { ).toEqual(`${mockKpiResponse.success}`); expect( wrapper - .find('[data-test-subj="ruleEventLogKpi-unknownOutcome"] .euiStat__title') + .find('[data-test-subj="ruleEventLogKpi-warningOutcome"] .euiStat__title') .first() .text() - ).toEqual(`${mockKpiResponse.unknown}`); + ).toEqual(`${mockKpiResponse.warning}`); expect( wrapper .find('[data-test-subj="ruleEventLogKpi-failureOutcome"] .euiStat__title') diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_event_log_list_kpi.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_event_log_list_kpi.tsx index 7fe7dd8fdb029..970390359f0d7 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_event_log_list_kpi.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_event_log_list_kpi.tsx @@ -15,7 +15,6 @@ import { withBulkRuleOperations, } from '../../common/components/with_bulk_rule_api_operations'; import { useKibana } from '../../../../common/lib/kibana'; -import { CenterJustifiedSpinner } from '../../../components/center_justified_spinner'; import { RuleEventLogListStatus } from './rule_event_log_list_status'; const getParsedDate = (date: string) => { @@ -35,21 +34,21 @@ const API_FAILED_MESSAGE = i18n.translate( const RESPONSE_TOOLTIP = i18n.translate( 'xpack.triggersActionsUI.sections.ruleDetails.ruleEventLogListKpi.responseTooltip', { - defaultMessage: 'The responses for the latest rule runs.', + defaultMessage: 'The responses for up to 10,000 most recent rule runs.', } ); const ALERTS_TOOLTIP = i18n.translate( 'xpack.triggersActionsUI.sections.ruleDetails.ruleEventLogListKpi.alertsTooltip', { - defaultMessage: 'The alert statuses for the latest rule runs.', + defaultMessage: 'The alert statuses for up to 10,000 most recent rule runs.', } ); const ACTIONS_TOOLTIP = i18n.translate( 'xpack.triggersActionsUI.sections.ruleDetails.ruleEventLogListKpi.actionsTooltip', { - defaultMessage: 'The action statuses for the latest rule runs.', + defaultMessage: 'The action statuses for up to 10,000 most recent rule runs.', } ); @@ -147,9 +146,7 @@ export const RuleEventLogListKPI = (props: RuleEventLogListKPIProps) => { // eslint-disable-next-line react-hooks/exhaustive-deps }, [refreshToken]); - if (isLoading || !kpi) { - return ; - } + const isLoadingData = useMemo(() => isLoading || !kpi, [isLoading, kpi]); const getStatDescription = (element: React.ReactNode) => { return ( @@ -170,15 +167,17 @@ export const RuleEventLogListKPI = (props: RuleEventLogListKPIProps) => { data-test-subj="ruleEventLogKpi-successOutcome" description={getStatDescription()} titleSize="s" - title={kpi.success} + title={kpi?.success ?? 0} + isLoading={isLoadingData} /> )} + data-test-subj="ruleEventLogKpi-warningOutcome" + description={getStatDescription()} titleSize="s" - title={kpi.unknown} + title={kpi?.warning ?? 0} + isLoading={isLoadingData} /> @@ -186,7 +185,8 @@ export const RuleEventLogListKPI = (props: RuleEventLogListKPIProps) => { data-test-subj="ruleEventLogKpi-failureOutcome" description={getStatDescription()} titleSize="s" - title={kpi.failure} + title={kpi?.failure ?? 0} + isLoading={isLoadingData} /> @@ -200,7 +200,8 @@ export const RuleEventLogListKPI = (props: RuleEventLogListKPIProps) => { data-test-subj="ruleEventLogKpi-activeAlerts" description={getStatDescription('Active')} titleSize="s" - title={kpi.activeAlerts} + title={kpi?.activeAlerts ?? 0} + isLoading={isLoadingData} /> @@ -208,7 +209,8 @@ export const RuleEventLogListKPI = (props: RuleEventLogListKPIProps) => { data-test-subj="ruleEventLogKpi-newAlerts" description={getStatDescription('New')} titleSize="s" - title={kpi.newAlerts} + title={kpi?.newAlerts ?? 0} + isLoading={isLoadingData} /> @@ -216,7 +218,8 @@ export const RuleEventLogListKPI = (props: RuleEventLogListKPIProps) => { data-test-subj="ruleEventLogKpi-recoveredAlerts" description={getStatDescription('Recovered')} titleSize="s" - title={kpi.recoveredAlerts} + title={kpi?.recoveredAlerts ?? 0} + isLoading={isLoadingData} /> @@ -230,7 +233,8 @@ export const RuleEventLogListKPI = (props: RuleEventLogListKPIProps) => { data-test-subj="ruleEventLogKpi-erroredActions" description={getStatDescription('Errored')} titleSize="s" - title={kpi.erroredActions} + title={kpi?.erroredActions ?? 0} + isLoading={isLoadingData} /> @@ -238,7 +242,8 @@ export const RuleEventLogListKPI = (props: RuleEventLogListKPIProps) => { data-test-subj="ruleEventLogKpi-triggeredActions" description={getStatDescription('Triggered')} titleSize="s" - title={kpi.triggeredActions} + title={kpi?.triggeredActions ?? 0} + isLoading={isLoadingData} /> diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_event_log_list_status.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_event_log_list_status.tsx index 02d5bcf082f28..d82915f2fd59d 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_event_log_list_status.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_event_log_list_status.tsx @@ -7,10 +7,10 @@ import React from 'react'; import { EuiIcon } from '@elastic/eui'; -import type { EcsEventOutcome } from '@kbn/core/server'; +import { RuleAlertingOutcome } from '@kbn/alerting-plugin/common'; interface RuleEventLogListStatusProps { - status: EcsEventOutcome; + status: RuleAlertingOutcome; } const statusContainerStyles = { @@ -23,10 +23,11 @@ const iconStyles = { marginRight: '8px', }; -const STATUS_TO_COLOR: Record = { +const STATUS_TO_COLOR: Record = { success: 'success', failure: 'danger', unknown: 'gray', + warning: 'warning', }; export const RuleEventLogListStatus = (props: RuleEventLogListStatusProps) => { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_event_log_list_status_filter.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_event_log_list_status_filter.test.tsx index bb7f87b59aa5b..14591c7a15ccd 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_event_log_list_status_filter.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_event_log_list_status_filter.test.tsx @@ -36,7 +36,7 @@ describe('rule_event_log_list_status_filter', () => { wrapper.find(EuiFilterButton).simulate('click'); const statusItems = wrapper.find(EuiFilterSelectItem); - expect(statusItems.length).toEqual(3); + expect(statusItems.length).toEqual(4); statusItems.at(0).simulate('click'); expect(onChangeMock).toHaveBeenCalledWith(['success']); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_event_log_list_status_filter.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_event_log_list_status_filter.tsx index f70c2ab51400d..6d1b38a7ae94d 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_event_log_list_status_filter.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_event_log_list_status_filter.tsx @@ -7,11 +7,11 @@ import React, { useState, useCallback } from 'react'; import { FormattedMessage } from '@kbn/i18n-react'; +import { RuleAlertingOutcome } from '@kbn/alerting-plugin/common'; import { EuiFilterButton, EuiPopover, EuiFilterGroup, EuiFilterSelectItem } from '@elastic/eui'; -import type { EcsEventOutcome } from '@kbn/core/server'; import { RuleEventLogListStatus } from './rule_event_log_list_status'; -const statusFilters: EcsEventOutcome[] = ['success', 'failure', 'unknown']; +const statusFilters: RuleAlertingOutcome[] = ['success', 'failure', 'warning', 'unknown']; interface RuleEventLogListStatusFilterProps { selectedOptions: string[]; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_event_log_list_table.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_event_log_list_table.tsx index 2c1d6df71fc3d..58cd6447ca737 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_event_log_list_table.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_event_log_list_table.tsx @@ -348,54 +348,60 @@ export const RuleEventLogListTable = ( }, [refreshToken]); return ( - <> - - - - - - - - - - - - - - - {renderList()} - {isOnLastPage && ( - + + + + + + + + + + + + + + + + - )} + + + + {renderList()} + {isOnLastPage && ( + + )} + {isFlyoutOpen && selectedRunLog && ( ( onClose={onFlyoutClose} /> )} - + ); }; diff --git a/x-pack/plugins/triggers_actions_ui/public/common/constants/index.ts b/x-pack/plugins/triggers_actions_ui/public/common/constants/index.ts index 794a7e90bf53f..1db1551ecfd38 100644 --- a/x-pack/plugins/triggers_actions_ui/public/common/constants/index.ts +++ b/x-pack/plugins/triggers_actions_ui/public/common/constants/index.ts @@ -12,3 +12,4 @@ export { builtInGroupByTypes } from './group_by_types'; export const VIEW_LICENSE_OPTIONS_LINK = 'https://www.elastic.co/subscriptions'; export const PLUGIN_ID = 'triggersActions'; +export const CONNECTORS_PLUGIN_ID = 'triggersActionsConnectors'; diff --git a/x-pack/plugins/triggers_actions_ui/public/plugin.ts b/x-pack/plugins/triggers_actions_ui/public/plugin.ts index 1374f10355e16..9e4645b164f21 100644 --- a/x-pack/plugins/triggers_actions_ui/public/plugin.ts +++ b/x-pack/plugins/triggers_actions_ui/public/plugin.ts @@ -69,7 +69,7 @@ import type { } from './types'; import { TriggersActionsUiConfigType } from '../common/types'; import { registerAlertsTableConfiguration } from './application/sections/alerts_table/alerts_page/register_alerts_table_configuration'; -import { PLUGIN_ID } from './common/constants'; +import { PLUGIN_ID, CONNECTORS_PLUGIN_ID } from './common/constants'; import type { AlertsTableStateProps } from './application/sections/alerts_table/alerts_table_state'; import { getAlertsTableStateLazy } from './common/get_alerts_table_state'; import { ActionAccordionFormProps } from './application/sections/action_connector_form/action_form'; @@ -182,12 +182,24 @@ export class Plugin ExperimentalFeaturesService.init({ experimentalFeatures: this.experimentalFeatures }); const featureTitle = i18n.translate('xpack.triggersActionsUI.managementSection.displayName', { - defaultMessage: 'Rules and Connectors', + defaultMessage: 'Rules', }); const featureDescription = i18n.translate( 'xpack.triggersActionsUI.managementSection.displayDescription', { - defaultMessage: 'Detect conditions using rules, and take actions using connectors.', + defaultMessage: 'Detect conditions using rules.', + } + ); + const connectorsFeatureTitle = i18n.translate( + 'xpack.triggersActionsUI.managementSection.connectors.displayName', + { + defaultMessage: 'Connectors', + } + ); + const connectorsFeatureDescription = i18n.translate( + 'xpack.triggersActionsUI.managementSection.connectors.displayDescription', + { + defaultMessage: 'Connect third-party software with your alerting data.', } ); @@ -201,6 +213,15 @@ export class Plugin showOnHomePage: false, category: 'admin', }); + plugins.home.featureCatalogue.register({ + id: CONNECTORS_PLUGIN_ID, + title: connectorsFeatureTitle, + description: connectorsFeatureDescription, + icon: 'watchesApp', + path: '/app/management/insightsAndAlerting/triggersActions', + showOnHomePage: false, + category: 'admin', + }); } plugins.management.sections.section.insightsAndAlerting.registerApp({ @@ -250,6 +271,53 @@ export class Plugin }, }); + plugins.management.sections.section.insightsAndAlerting.registerApp({ + id: CONNECTORS_PLUGIN_ID, + title: connectorsFeatureTitle, + order: 2, + async mount(params: ManagementAppMountParams) { + const [coreStart, pluginsStart] = (await core.getStartServices()) as [ + CoreStart, + PluginsStart, + unknown + ]; + + const { renderApp } = await import('./application/connectors_app'); + + // The `/api/features` endpoint requires the "Global All" Kibana privilege. Users with a + // subset of this privilege are not authorized to access this endpoint and will receive a 404 + // error that causes the Alerting view to fail to load. + let kibanaFeatures: KibanaFeature[]; + try { + kibanaFeatures = await pluginsStart.features.getFeatures(); + } catch (err) { + kibanaFeatures = []; + } + + return renderApp({ + ...coreStart, + actions: plugins.actions, + data: pluginsStart.data, + dataViews: pluginsStart.dataViews, + dataViewEditor: pluginsStart.dataViewEditor, + charts: pluginsStart.charts, + alerting: pluginsStart.alerting, + spaces: pluginsStart.spaces, + unifiedSearch: pluginsStart.unifiedSearch, + isCloud: Boolean(plugins.cloud?.isCloudEnabled), + element: params.element, + theme$: params.theme$, + storage: new Storage(window.localStorage), + setBreadcrumbs: params.setBreadcrumbs, + history: params.history, + actionTypeRegistry, + ruleTypeRegistry, + alertsTableConfigurationRegistry, + kibanaFeatures, + }); + }, + }); + if (this.experimentalFeatures.internalAlertsTable) { registerAlertsTableConfiguration({ alertsTableConfigurationRegistry: this.alertsTableConfigurationRegistry, diff --git a/x-pack/plugins/triggers_actions_ui/server/data/lib/core_query_types.test.ts b/x-pack/plugins/triggers_actions_ui/server/data/lib/core_query_types.test.ts index 9909297da1063..6ffed5accf9cd 100644 --- a/x-pack/plugins/triggers_actions_ui/server/data/lib/core_query_types.test.ts +++ b/x-pack/plugins/triggers_actions_ui/server/data/lib/core_query_types.test.ts @@ -19,6 +19,7 @@ const DefaultParams: Writable> = { groupBy: 'all', timeWindowSize: 5, timeWindowUnit: 'm', + filterKuery: 'event.provider: alerting', }; export function runTests(schema: ObjectType, defaultTypeParams: Record): void { @@ -183,6 +184,13 @@ export function runTests(schema: ObjectType, defaultTypeParams: Record { + params.filterKuery = 'event:'; + expect(onValidate()).toThrowErrorMatchingInlineSnapshot( + '"[filterKuery]: Filter query is invalid."' + ); + }); }); function onValidate(): () => void { diff --git a/x-pack/plugins/triggers_actions_ui/server/data/lib/core_query_types.ts b/x-pack/plugins/triggers_actions_ui/server/data/lib/core_query_types.ts index 605a06ab7ab5e..06e7c75d9795b 100644 --- a/x-pack/plugins/triggers_actions_ui/server/data/lib/core_query_types.ts +++ b/x-pack/plugins/triggers_actions_ui/server/data/lib/core_query_types.ts @@ -10,6 +10,7 @@ import { i18n } from '@kbn/i18n'; import { schema, TypeOf } from '@kbn/config-schema'; +import { toElasticsearchQuery, fromKueryExpression } from '@kbn/es-query'; import { MAX_GROUPS } from '..'; export const CoreQueryParamsSchemaProperties = { @@ -28,6 +29,8 @@ export const CoreQueryParamsSchemaProperties = { groupBy: schema.string({ validate: validateGroupBy }), // field to group on (for groupBy: top) termField: schema.maybe(schema.string({ minLength: 1 })), + // filter field + filterKuery: schema.maybe(schema.string({ validate: validateKuery })), // limit on number of groups returned termSize: schema.maybe(schema.number({ min: 1 })), // size of time window for date range aggregations @@ -135,3 +138,16 @@ export function validateTimeWindowUnits(timeWindowUnit: string): string | undefi } ); } + +export function validateKuery(query: string): string | undefined { + try { + toElasticsearchQuery(fromKueryExpression(query)); + } catch (e) { + return i18n.translate( + 'xpack.triggersActionsUI.data.coreQueryParams.invalidKQLQueryErrorMessage', + { + defaultMessage: 'Filter query is invalid.', + } + ); + } +} diff --git a/x-pack/plugins/triggers_actions_ui/server/data/lib/time_series_query.test.ts b/x-pack/plugins/triggers_actions_ui/server/data/lib/time_series_query.test.ts index 5e2550e15f35d..514601612db21 100644 --- a/x-pack/plugins/triggers_actions_ui/server/data/lib/time_series_query.test.ts +++ b/x-pack/plugins/triggers_actions_ui/server/data/lib/time_series_query.test.ts @@ -54,6 +54,26 @@ describe('timeSeriesQuery', () => { ).rejects.toThrowErrorMatchingInlineSnapshot(`"invalid date format for dateStart: \\"x\\""`); }); + it('filters the results when filter param is passed', async () => { + await timeSeriesQuery({ + ...params, + query: { ...params.query, filterKuery: 'event.provider: alerting' }, + }); + // @ts-ignore + expect(esClient.search.mock.calls[0]![0].body.query.bool.filter[1]).toEqual({ + bool: { + minimum_should_match: 1, + should: [ + { + match: { + 'event.provider': 'alerting', + }, + }, + ], + }, + }); + }); + it('should create correct query when aggType=count and termField is undefined (count over all) and selector params are undefined', async () => { await timeSeriesQuery(params); expect(esClient.search).toHaveBeenCalledWith( @@ -80,15 +100,17 @@ describe('timeSeriesQuery', () => { }, query: { bool: { - filter: { - range: { - 'time-field': { - format: 'strict_date_time', - gte: '2021-04-22T15:14:31.000Z', - lt: '2021-04-22T15:20:31.000Z', + filter: [ + { + range: { + 'time-field': { + format: 'strict_date_time', + gte: '2021-04-22T15:14:31.000Z', + lt: '2021-04-22T15:20:31.000Z', + }, }, }, - }, + ], }, }, size: 0, @@ -132,15 +154,17 @@ describe('timeSeriesQuery', () => { }, query: { bool: { - filter: { - range: { - 'time-field': { - format: 'strict_date_time', - gte: '2021-04-22T15:14:31.000Z', - lt: '2021-04-22T15:20:31.000Z', + filter: [ + { + range: { + 'time-field': { + format: 'strict_date_time', + gte: '2021-04-22T15:14:31.000Z', + lt: '2021-04-22T15:20:31.000Z', + }, }, }, - }, + ], }, }, size: 0, @@ -193,15 +217,17 @@ describe('timeSeriesQuery', () => { }, query: { bool: { - filter: { - range: { - 'time-field': { - format: 'strict_date_time', - gte: '2021-04-22T15:14:31.000Z', - lt: '2021-04-22T15:20:31.000Z', + filter: [ + { + range: { + 'time-field': { + format: 'strict_date_time', + gte: '2021-04-22T15:14:31.000Z', + lt: '2021-04-22T15:20:31.000Z', + }, }, }, - }, + ], }, }, size: 0, @@ -271,15 +297,17 @@ describe('timeSeriesQuery', () => { }, query: { bool: { - filter: { - range: { - 'time-field': { - format: 'strict_date_time', - gte: '2021-04-22T15:14:31.000Z', - lt: '2021-04-22T15:20:31.000Z', + filter: [ + { + range: { + 'time-field': { + format: 'strict_date_time', + gte: '2021-04-22T15:14:31.000Z', + lt: '2021-04-22T15:20:31.000Z', + }, }, }, - }, + ], }, }, size: 0, @@ -336,15 +364,17 @@ describe('timeSeriesQuery', () => { }, query: { bool: { - filter: { - range: { - 'time-field': { - format: 'strict_date_time', - gte: '2021-04-22T15:14:31.000Z', - lt: '2021-04-22T15:20:31.000Z', + filter: [ + { + range: { + 'time-field': { + format: 'strict_date_time', + gte: '2021-04-22T15:14:31.000Z', + lt: '2021-04-22T15:20:31.000Z', + }, }, }, - }, + ], }, }, size: 0, @@ -405,15 +435,17 @@ describe('timeSeriesQuery', () => { }, query: { bool: { - filter: { - range: { - 'time-field': { - format: 'strict_date_time', - gte: '2021-04-22T15:14:31.000Z', - lt: '2021-04-22T15:20:31.000Z', + filter: [ + { + range: { + 'time-field': { + format: 'strict_date_time', + gte: '2021-04-22T15:14:31.000Z', + lt: '2021-04-22T15:20:31.000Z', + }, }, }, - }, + ], }, }, size: 0, @@ -483,15 +515,17 @@ describe('timeSeriesQuery', () => { }, query: { bool: { - filter: { - range: { - 'time-field': { - format: 'strict_date_time', - gte: '2021-04-22T15:14:31.000Z', - lt: '2021-04-22T15:20:31.000Z', + filter: [ + { + range: { + 'time-field': { + format: 'strict_date_time', + gte: '2021-04-22T15:14:31.000Z', + lt: '2021-04-22T15:20:31.000Z', + }, }, }, - }, + ], }, }, size: 0, @@ -578,15 +612,17 @@ describe('timeSeriesQuery', () => { }, query: { bool: { - filter: { - range: { - 'time-field': { - format: 'strict_date_time', - gte: '2021-04-22T15:14:31.000Z', - lt: '2021-04-22T15:20:31.000Z', + filter: [ + { + range: { + 'time-field': { + format: 'strict_date_time', + gte: '2021-04-22T15:14:31.000Z', + lt: '2021-04-22T15:20:31.000Z', + }, }, }, - }, + ], }, }, size: 0, @@ -656,15 +692,17 @@ describe('timeSeriesQuery', () => { }, query: { bool: { - filter: { - range: { - 'time-field': { - format: 'strict_date_time', - gte: '2021-04-22T15:14:31.000Z', - lt: '2021-04-22T15:20:31.000Z', + filter: [ + { + range: { + 'time-field': { + format: 'strict_date_time', + gte: '2021-04-22T15:14:31.000Z', + lt: '2021-04-22T15:20:31.000Z', + }, }, }, - }, + ], }, }, size: 0, diff --git a/x-pack/plugins/triggers_actions_ui/server/data/lib/time_series_query.ts b/x-pack/plugins/triggers_actions_ui/server/data/lib/time_series_query.ts index 885be0bf59f5b..ccf4ae631bf8e 100644 --- a/x-pack/plugins/triggers_actions_ui/server/data/lib/time_series_query.ts +++ b/x-pack/plugins/triggers_actions_ui/server/data/lib/time_series_query.ts @@ -9,6 +9,7 @@ import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { Logger } from '@kbn/core/server'; import type { ElasticsearchClient } from '@kbn/core/server'; import { getEsErrorMessage } from '@kbn/alerting-plugin/server'; +import { toElasticsearchQuery, fromKueryExpression } from '@kbn/es-query'; import { DEFAULT_GROUPS } from '..'; import { getDateRangeInfo } from './date_range_info'; @@ -34,8 +35,16 @@ export async function timeSeriesQuery( params: TimeSeriesQueryParameters ): Promise { const { logger, esClient, query: queryParams, condition: conditionParams } = params; - const { index, timeWindowSize, timeWindowUnit, interval, timeField, dateStart, dateEnd } = - queryParams; + const { + index, + timeWindowSize, + timeWindowUnit, + interval, + timeField, + dateStart, + dateEnd, + filterKuery, + } = queryParams; const window = `${timeWindowSize}${timeWindowUnit}`; const dateRangeInfo = getDateRangeInfo({ dateStart, dateEnd, window, interval }); @@ -49,15 +58,18 @@ export async function timeSeriesQuery( size: 0, query: { bool: { - filter: { - range: { - [timeField]: { - gte: dateRangeInfo.dateStart, - lt: dateRangeInfo.dateEnd, - format: 'strict_date_time', + filter: [ + { + range: { + [timeField]: { + gte: dateRangeInfo.dateStart, + lt: dateRangeInfo.dateEnd, + format: 'strict_date_time', + }, }, }, - }, + ...(!!filterKuery ? [toElasticsearchQuery(fromKueryExpression(filterKuery))] : []), + ], }, }, // aggs: {...}, filled in below diff --git a/x-pack/plugins/ux/public/components/app/rum_dashboard/charts/__snapshots__/visitor_breakdown_chart.test.tsx.snap b/x-pack/plugins/ux/public/components/app/rum_dashboard/charts/__snapshots__/visitor_breakdown_chart.test.tsx.snap index c3bc67a02749c..1e7d3ca13e43c 100644 --- a/x-pack/plugins/ux/public/components/app/rum_dashboard/charts/__snapshots__/visitor_breakdown_chart.test.tsx.snap +++ b/x-pack/plugins/ux/public/components/app/rum_dashboard/charts/__snapshots__/visitor_breakdown_chart.test.tsx.snap @@ -2,21 +2,15 @@ exports[`VisitorBreakdownChart getVisitorBreakdownLensAttributes generates expected lens attributes 1`] = ` Object { - "references": Array [ - Object { - "id": "Required", - "name": "indexpattern-datasource-current-indexpattern", - "type": "index-pattern", - }, - Object { - "id": "Required", - "name": "indexpattern-datasource-layer-layer1", - "type": "index-pattern", - }, - ], + "references": Array [], "state": Object { + "adHocDataViews": Object { + "xxxx-xxxxxxxxxxx-xxxx": Object { + "id": "xxxx-xxxxxxxxxxx-xxxx", + }, + }, "datasourceStates": Object { - "indexpattern": Object { + "formBased": Object { "layers": Object { "layer1": Object { "columnOrder": Array [ @@ -95,6 +89,18 @@ Object { }, }, ], + "internalReferences": Array [ + Object { + "id": "xxxx-xxxxxxxxxxx-xxxx", + "name": "indexpattern-datasource-current-indexpattern", + "type": "index-pattern", + }, + Object { + "id": "xxxx-xxxxxxxxxxx-xxxx", + "name": "indexpattern-datasource-layer-layer1", + "type": "index-pattern", + }, + ], "query": Object { "language": "kuery", "query": "", diff --git a/x-pack/plugins/ux/public/components/app/rum_dashboard/charts/visitor_breakdown_chart.test.tsx b/x-pack/plugins/ux/public/components/app/rum_dashboard/charts/visitor_breakdown_chart.test.tsx index 536a5158cac9c..65f76b705ef54 100644 --- a/x-pack/plugins/ux/public/components/app/rum_dashboard/charts/visitor_breakdown_chart.test.tsx +++ b/x-pack/plugins/ux/public/components/app/rum_dashboard/charts/visitor_breakdown_chart.test.tsx @@ -13,8 +13,19 @@ import { VisitorBreakdownMetric, } from './visitor_breakdown_chart'; import { useKibanaServices } from '../../../../hooks/use_kibana_services'; +import type { DataView } from '@kbn/data-views-plugin/public'; jest.mock('../../../../hooks/use_kibana_services'); +jest.mock('uuid'); + +const mockDataView = { + id: 'mock-id', + title: 'mock-title', + timeFieldName: 'mock-time-field-name', + isPersisted: () => false, + getName: () => 'mock-data-view', + toSpec: () => ({}), +} as DataView; describe('VisitorBreakdownChart', () => { describe('getVisitorBreakdownLensAttributes', () => { @@ -25,7 +36,8 @@ describe('VisitorBreakdownChart', () => { environment: 'ENVIRONMENT_ALL', }, urlQuery: 'elastic.co', - dataView: 'Required', + dataView: mockDataView, + localDataViewId: 'xxxx-xxxxxxxxxxx-xxxx', }; expect(getVisitorBreakdownLensAttributes(props)).toMatchSnapshot(); @@ -33,6 +45,8 @@ describe('VisitorBreakdownChart', () => { }); describe('component', () => { + const mockUuid = jest.requireMock('uuid'); + mockUuid.v4 = jest.fn().mockReturnValue('xxxx-xxxxxxxxxxx-xxxx'); const mockEmbeddableComponent = jest.fn((_) => <>); beforeEach(() => { @@ -53,7 +67,8 @@ describe('VisitorBreakdownChart', () => { environment: 'ENVIRONMENT_ALL', }, urlQuery: 'elastic.co', - dataView: 'Required', + dataView: mockDataView, + localDataViewId: 'xxxx-xxxxxxxxxxx-xxxx', onFilter: (_m: VisitorBreakdownMetric, _e: any) => {}, }; diff --git a/x-pack/plugins/ux/public/components/app/rum_dashboard/charts/visitor_breakdown_chart.tsx b/x-pack/plugins/ux/public/components/app/rum_dashboard/charts/visitor_breakdown_chart.tsx index 89176ea2e21c0..e20e9b1f89f7e 100644 --- a/x-pack/plugins/ux/public/components/app/rum_dashboard/charts/visitor_breakdown_chart.tsx +++ b/x-pack/plugins/ux/public/components/app/rum_dashboard/charts/visitor_breakdown_chart.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React, { useCallback, useMemo } from 'react'; +import React, { useCallback, useMemo, useState } from 'react'; import { ViewMode } from '@kbn/embeddable-plugin/public'; import { CountIndexPatternColumn, @@ -16,6 +16,8 @@ import { } from '@kbn/lens-plugin/public'; import { EuiText } from '@elastic/eui'; import { ProcessorEvent } from '@kbn/observability-plugin/common'; +import { DataView } from '@kbn/data-views-plugin/public'; +import uuid from 'uuid'; import { TRANSACTION_PAGE_LOAD } from '../../../../../common/transaction_types'; import { PROCESSOR_EVENT, @@ -36,7 +38,7 @@ interface LensAttributes { metric: VisitorBreakdownMetric; uiFilters: UxUIFilters; urlQuery?: string; - dataView: string; + dataView: DataView; } type Props = { @@ -56,6 +58,7 @@ export function VisitorBreakdownChart({ }: Props) { const kibana = useKibanaServices(); const LensEmbeddableComponent = kibana.lens.EmbeddableComponent; + const [localDataViewId] = useState(uuid.v4()); const lensAttributes = useMemo( () => @@ -64,8 +67,9 @@ export function VisitorBreakdownChart({ urlQuery, metric, dataView, + localDataViewId, }), - [uiFilters, urlQuery, metric, dataView] + [uiFilters, urlQuery, metric, dataView, localDataViewId] ); const filterHandler = useCallback( @@ -118,7 +122,13 @@ export function getVisitorBreakdownLensAttributes({ urlQuery, metric, dataView, -}: LensAttributes): TypedLensByValueInput['attributes'] { + localDataViewId, +}: LensAttributes & { + localDataViewId: string; +}): TypedLensByValueInput['attributes'] { + const localDataView = dataView.toSpec(false); + localDataView.id = localDataViewId; + const dataLayer: PersistedIndexPatternLayer = { incompleteColumns: {}, columnOrder: ['col1', 'col2'], @@ -160,21 +170,25 @@ export function getVisitorBreakdownLensAttributes({ return { visualizationType: 'lnsPie', title: `ux-visitor-breakdown-${metric}`, - references: [ - { - id: dataView, - name: 'indexpattern-datasource-current-indexpattern', - type: 'index-pattern', - }, - { - id: dataView, - name: 'indexpattern-datasource-layer-layer1', - type: 'index-pattern', - }, - ], + references: [], state: { + internalReferences: [ + { + id: localDataView.id, + name: 'indexpattern-datasource-current-indexpattern', + type: 'index-pattern', + }, + { + id: localDataView.id, + name: 'indexpattern-datasource-layer-layer1', + type: 'index-pattern', + }, + ], + adHocDataViews: { + [localDataView.id]: localDataView, + }, datasourceStates: { - indexpattern: { + formBased: { layers: { layer1: dataLayer, }, diff --git a/x-pack/plugins/ux/public/components/app/rum_dashboard/csm_shared_context/index.tsx b/x-pack/plugins/ux/public/components/app/rum_dashboard/csm_shared_context/index.tsx index e3a888effd319..9c63c77735341 100644 --- a/x-pack/plugins/ux/public/components/app/rum_dashboard/csm_shared_context/index.tsx +++ b/x-pack/plugins/ux/public/components/app/rum_dashboard/csm_shared_context/index.tsx @@ -57,6 +57,7 @@ export function CsmSharedContextProvider({ if (dataViewTitle) { return dataViews.create({ title: dataViewTitle, + timeFieldName: '@timestamp', }); } }, [dataViewTitle, dataViews]); diff --git a/x-pack/plugins/ux/public/components/app/rum_dashboard/hooks/use_local_uifilters.ts b/x-pack/plugins/ux/public/components/app/rum_dashboard/hooks/use_local_uifilters.ts index e208e8536b718..6ae8b593296ee 100644 --- a/x-pack/plugins/ux/public/components/app/rum_dashboard/hooks/use_local_uifilters.ts +++ b/x-pack/plugins/ux/public/components/app/rum_dashboard/hooks/use_local_uifilters.ts @@ -8,6 +8,7 @@ import { omit } from 'lodash'; import { useHistory } from 'react-router-dom'; import { fromQuery, toQuery } from '@kbn/observability-plugin/public'; +import { useCallback, useMemo } from 'react'; import { useLegacyUrlParams } from '../../../../context/url_params_context/use_url_params'; import { getExcludedName } from '../local_uifilters'; @@ -28,55 +29,57 @@ export function useLocalUIFilters({ const history = useHistory(); const { uxUiFilters } = useLegacyUrlParams(); - const setFilterValue = (name: UxLocalUIFilterName, value: string[]) => { - const search = omit(toQuery(history.location.search), name); + const setFilterValue = useCallback( + (name: UxLocalUIFilterName, value: string[]) => { + const search = omit(toQuery(history.location.search), name); - history.push({ - ...history.location, - search: fromQuery( - removeUndefinedProps({ - ...search, - [name]: value.length ? value.join(',') : undefined, - }) - ), - }); - }; + history.push({ + ...history.location, + search: fromQuery( + removeUndefinedProps({ + ...search, + [name]: value.length ? value.join(',') : undefined, + }) + ), + }); + }, + [history] + ); - const invertFilter = ( - name: UxLocalUIFilterName, - value: string, - negate: boolean - ) => { - if (!negate) { - setFilterValue( - name, - (uxUiFilters?.[name] as string[]).filter((valT) => valT !== value) - ); + const invertFilter = useCallback( + (name: UxLocalUIFilterName, value: string, negate: boolean) => { + if (!negate) { + setFilterValue( + name, + (uxUiFilters?.[name] as string[]).filter((valT) => valT !== value) + ); - const excludedName = getExcludedName(name); - setFilterValue(excludedName, [ - ...(uxUiFilters?.[excludedName] ?? []), - value, - ]); - } else { - const includeName = name.split('Excluded')[0] as UxLocalUIFilterName; - const excludedName = name; + const excludedName = getExcludedName(name); + setFilterValue(excludedName, [ + ...(uxUiFilters?.[excludedName] ?? []), + value, + ]); + } else { + const includeName = name.split('Excluded')[0] as UxLocalUIFilterName; + const excludedName = name; - setFilterValue( - excludedName, - (uxUiFilters?.[excludedName] as string[]).filter( - (valT) => valT !== value - ) - ); + setFilterValue( + excludedName, + (uxUiFilters?.[excludedName] as string[]).filter( + (valT) => valT !== value + ) + ); - setFilterValue(includeName, [ - ...(uxUiFilters?.[includeName] ?? []), - value, - ]); - } - }; + setFilterValue(includeName, [ + ...(uxUiFilters?.[includeName] ?? []), + value, + ]); + } + }, + [setFilterValue, uxUiFilters] + ); - const clearValues = () => { + const clearValues = useCallback(() => { const search = omit(toQuery(history.location.search), [ ...filterNames, 'searchTerm', @@ -87,13 +90,17 @@ export function useLocalUIFilters({ ...history.location, search: fromQuery(search), }); - }; + }, [filterNames, history]); - const filters: UxLocalUIFilter[] = filterNames.map((name) => ({ - value: (uxUiFilters[name] as string[]) ?? [], - ...uxFiltersByName[name], - name, - })); + const filters: UxLocalUIFilter[] = useMemo( + () => + filterNames.map((name) => ({ + value: (uxUiFilters[name] as string[]) ?? [], + ...uxFiltersByName[name], + name, + })), + [filterNames, uxUiFilters] + ); return { filters, diff --git a/x-pack/plugins/ux/public/components/app/rum_dashboard/visitor_breakdown/index.tsx b/x-pack/plugins/ux/public/components/app/rum_dashboard/visitor_breakdown/index.tsx index 699c4aad80724..9d631524308a2 100644 --- a/x-pack/plugins/ux/public/components/app/rum_dashboard/visitor_breakdown/index.tsx +++ b/x-pack/plugins/ux/public/components/app/rum_dashboard/visitor_breakdown/index.tsx @@ -19,9 +19,9 @@ import { } from '../charts/visitor_breakdown_chart'; import { I18LABELS, VisitorBreakdownLabel } from '../translations'; import { useLegacyUrlParams } from '../../../../context/url_params_context/use_url_params'; -import { useStaticDataView } from '../../../../hooks/use_static_data_view'; import { useLocalUIFilters } from '../hooks/use_local_uifilters'; import { getExcludedName } from '../local_uifilters'; +import { useDataView } from '../local_uifilters/use_data_view'; type VisitorBreakdownFieldMap = Record< VisitorBreakdownMetric, @@ -40,20 +40,21 @@ const EuiLoadingEmbeddable = styled(EuiFlexGroup)` } `; +const vistorBreakdownFilter = { + filterNames: uxLocalUIFilterNames.filter((name) => + ['browser', 'browserExcluded', 'os', 'osExcluded'].includes(name) + ), +}; + const getInvertedFilterName = (filter: UxLocalUIFilterName, negate: boolean) => negate ? filter : getExcludedName(filter); export function VisitorBreakdown() { const { urlParams, uxUiFilters } = useLegacyUrlParams(); const { start, end, searchTerm } = urlParams; - // static dataView is required for lens - const { dataView, loading } = useStaticDataView(); + const { dataView } = useDataView(); - const { filters, setFilterValue } = useLocalUIFilters({ - filterNames: uxLocalUIFilterNames.filter((name) => - ['browser', 'browserExcluded', 'os', 'osExcluded'].includes(name) - ), - }); + const { filters, setFilterValue } = useLocalUIFilters(vistorBreakdownFilter); const onFilter = useCallback( (metric: VisitorBreakdownMetric, event: any) => { @@ -96,7 +97,7 @@ export function VisitorBreakdown() {

{I18LABELS.browser}

- {!!loading ? ( + {!dataView?.id ? ( ) : ( {I18LABELS.operatingSystem} - {!!loading ? ( + {!dataView?.id ? ( ) : ( { const watcherESApp = esSection.registerApp({ id: 'watcher', title: pluginName, - order: 3, + order: 5, mount: async ({ element, setBreadcrumbs, history, theme$ }) => { const [coreStart] = await getStartServices(); const { diff --git a/x-pack/test/alerting_api_integration/common/config.ts b/x-pack/test/alerting_api_integration/common/config.ts index 80b879534323b..090e48f7a8a2d 100644 --- a/x-pack/test/alerting_api_integration/common/config.ts +++ b/x-pack/test/alerting_api_integration/common/config.ts @@ -34,6 +34,7 @@ const enabledActionTypes = [ '.cases-webhook', '.email', '.index', + '.opsgenie', '.pagerduty', '.swimlane', '.server-log', diff --git a/x-pack/test/alerting_api_integration/common/fixtures/plugins/actions_simulators/server/data_handler.ts b/x-pack/test/alerting_api_integration/common/fixtures/plugins/actions_simulators/server/data_handler.ts new file mode 100644 index 0000000000000..126a485b1d5ea --- /dev/null +++ b/x-pack/test/alerting_api_integration/common/fixtures/plugins/actions_simulators/server/data_handler.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 http from 'http'; + +export const getDataFromRequest = async (request: http.IncomingMessage) => { + if (request.method !== 'POST' && request.method !== 'PATCH') { + return {}; + } + + const buffers = []; + + for await (const chunk of request) { + buffers.push(chunk); + } + + return JSON.parse(Buffer.concat(buffers).toString()); +}; diff --git a/x-pack/test/alerting_api_integration/common/fixtures/plugins/actions_simulators/server/opsgenie_simulation.ts b/x-pack/test/alerting_api_integration/common/fixtures/plugins/actions_simulators/server/opsgenie_simulation.ts new file mode 100644 index 0000000000000..abc73b48a7e72 --- /dev/null +++ b/x-pack/test/alerting_api_integration/common/fixtures/plugins/actions_simulators/server/opsgenie_simulation.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import http from 'http'; + +import { ProxyArgs, Simulator } from './simulator'; + +export class OpsgenieSimulator extends Simulator { + private readonly returnError: boolean; + + constructor({ returnError = false, proxy }: { returnError?: boolean; proxy?: ProxyArgs }) { + super(proxy); + + this.returnError = returnError; + } + + public async handler( + request: http.IncomingMessage, + response: http.ServerResponse, + data: Record + ) { + if (this.returnError) { + return OpsgenieSimulator.sendErrorResponse(response); + } + + return OpsgenieSimulator.sendResponse(response); + } + + private static sendResponse(response: http.ServerResponse) { + response.statusCode = 202; + response.setHeader('Content-Type', 'application/json'); + response.end(JSON.stringify(opsgenieSuccessResponse, null, 4)); + } + + private static sendErrorResponse(response: http.ServerResponse) { + response.statusCode = 422; + response.setHeader('Content-Type', 'application/json;charset=UTF-8'); + response.end(JSON.stringify(opsgenieFailedResponse, null, 4)); + } +} + +export const opsgenieSuccessResponse = { + result: 'Request will be processed', + took: 0.107, + requestId: '43a29c5c-3dbf-4fa4-9c26-f4f71023e120', +}; + +export const opsgenieFailedResponse = { + result: 'error', + errors: { + message: 'failed', + }, + took: 0.107, + requestId: '43a29c5c-3dbf-4fa4-9c26-f4f71023e120', +}; diff --git a/x-pack/test/alerting_api_integration/common/fixtures/plugins/actions_simulators/server/plugin.ts b/x-pack/test/alerting_api_integration/common/fixtures/plugins/actions_simulators/server/plugin.ts index 52f4b035341b0..ae874d942e75b 100644 --- a/x-pack/test/alerting_api_integration/common/fixtures/plugins/actions_simulators/server/plugin.ts +++ b/x-pack/test/alerting_api_integration/common/fixtures/plugins/actions_simulators/server/plugin.ts @@ -26,6 +26,7 @@ import { initPlugin as initXmatters } from './xmatters_simulation'; export const NAME = 'actions-FTS-external-service-simulators'; export enum ExternalServiceSimulator { + OPSGENIE = 'opsgenie', PAGERDUTY = 'pagerduty', SWIMLANE = 'swimlane', SERVICENOW = 'servicenow', diff --git a/x-pack/test/alerting_api_integration/common/fixtures/plugins/actions_simulators/server/servicenow_simulation.ts b/x-pack/test/alerting_api_integration/common/fixtures/plugins/actions_simulators/server/servicenow_simulation.ts index 007c03193d5a0..5e5d05da833f1 100644 --- a/x-pack/test/alerting_api_integration/common/fixtures/plugins/actions_simulators/server/servicenow_simulation.ts +++ b/x-pack/test/alerting_api_integration/common/fixtures/plugins/actions_simulators/server/servicenow_simulation.ts @@ -6,6 +6,8 @@ */ import http from 'http'; +import { isEmpty } from 'lodash'; +import { getDataFromRequest } from './data_handler'; /** * This server records the data from a create incident request. It only saves the most recent request. When building tests, @@ -14,6 +16,7 @@ import http from 'http'; export class RecordingServiceNowSimulator { private _incident: Record | undefined; private _server: http.Server | undefined; + private _allRequestData: Array> = []; private constructor() {} @@ -28,13 +31,17 @@ export class RecordingServiceNowSimulator { } private handler = async (request: http.IncomingMessage, response: http.ServerResponse) => { - const data = await getData(request); + const data = await getDataFromRequest(request); const pathName = request.url!; if (isCreateRequest(pathName)) { this._incident = data; } + if (!isEmpty(data)) { + this._allRequestData.push(data); + } + return handleSendingResponse(request, response, data); }; @@ -45,6 +52,10 @@ export class RecordingServiceNowSimulator { public get server() { return this._server!; } + + public get allRequestData() { + return this._allRequestData!; + } } const isCreateRequest = (pathName: string) => { @@ -62,7 +73,7 @@ const sendResponse = (response: http.ServerResponse, data: any) => { }; const requestHandler = async (request: http.IncomingMessage, response: http.ServerResponse) => { - const data: Record = await getData(request); + const data: Record = await getDataFromRequest(request); return handleSendingResponse(request, response, data); }; @@ -230,19 +241,3 @@ const handleSendingResponse = async ( response.setHeader('Content-Type', 'application/json'); response.end('Not supported endpoint to request servicenow simulator'); }; - -const getData = async (request: http.IncomingMessage) => { - let data: Record = {}; - - if (request.method === 'POST') { - const buffers = []; - - for await (const chunk of request) { - buffers.push(chunk); - } - - data = JSON.parse(Buffer.concat(buffers).toString()); - } - - return data; -}; diff --git a/x-pack/test/alerting_api_integration/common/fixtures/plugins/actions_simulators/server/simulator.ts b/x-pack/test/alerting_api_integration/common/fixtures/plugins/actions_simulators/server/simulator.ts new file mode 100644 index 0000000000000..d226859e25659 --- /dev/null +++ b/x-pack/test/alerting_api_integration/common/fixtures/plugins/actions_simulators/server/simulator.ts @@ -0,0 +1,92 @@ +/* + * 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 getPort from 'get-port'; +import http from 'http'; +import httpProxy from 'http-proxy'; +import { getProxyPort } from '../../../../lib/get_proxy_server'; +import { getDataFromRequest } from './data_handler'; + +export interface ProxyArgs { + config: string; + proxyHandler?: (proxyRes?: unknown, req?: unknown, res?: unknown) => void; +} + +export abstract class Simulator { + private _requestData: Record | undefined; + private _requestUrl: string | undefined; + private proxyServer: httpProxy | undefined; + private readonly proxyArgs: ProxyArgs | undefined; + protected server: http.Server; + + constructor(proxy?: ProxyArgs) { + this.server = http.createServer(this.baseHandler); + + if (proxy) { + this.proxyArgs = proxy; + } + } + + private createAndStartHttpProxyServer = (targetUrl: string) => { + if (!this.proxyArgs) { + return; + } + + this.proxyServer = httpProxy.createProxyServer({ + target: targetUrl, + secure: false, + selfHandleResponse: false, + }); + + this.proxyServer.on('proxyRes', (proxyRes: unknown, req: unknown, res: unknown) => { + if (this.proxyArgs?.proxyHandler) { + this.proxyArgs.proxyHandler(proxyRes, req, res); + } + }); + + const proxyPort = getProxyPort(this.proxyArgs.config); + this.proxyServer.listen(proxyPort); + }; + + private baseHandler = async (request: http.IncomingMessage, response: http.ServerResponse) => { + const data = await getDataFromRequest(request); + this._requestData = data; + this._requestUrl = new URL(request.url ?? '', `http://${request.headers.host}`).toString(); + + return this.handler(request, response, data); + }; + + protected abstract handler( + request: http.IncomingMessage, + response: http.ServerResponse, + data: Record + ): Promise; + + public async start() { + const port = await getPort({ port: getPort.makeRange(9000, 9100) }); + if (!this.server.listening) { + this.server.listen(port); + } + const url = `http://localhost:${port}`; + + this.createAndStartHttpProxyServer(url); + return url; + } + + public close() { + this.proxyServer?.close(); + this.server.close(); + } + + public get requestData() { + return this._requestData; + } + + public get requestUrl() { + return this._requestUrl; + } +} diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/stack/opsgenie.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/stack/opsgenie.ts new file mode 100644 index 0000000000000..e1011059b8532 --- /dev/null +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/stack/opsgenie.ts @@ -0,0 +1,747 @@ +/* + * 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 expect from '@kbn/expect'; + +import { FtrProviderContext } from '../../../../../../common/ftr_provider_context'; +import { + OpsgenieSimulator, + opsgenieSuccessResponse, +} from '../../../../../../common/fixtures/plugins/actions_simulators/server/opsgenie_simulation'; + +// eslint-disable-next-line import/no-default-export +export default function opsgenieTest({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + const configService = getService('config'); + + describe('Opsgenie', () => { + describe('action creation', () => { + const simulator = new OpsgenieSimulator({ + returnError: false, + proxy: { + config: configService.get('kbnTestServer.serverArgs'), + }, + }); + let simulatorUrl: string; + + before(async () => { + simulatorUrl = await simulator.start(); + }); + + after(() => { + simulator.close(); + }); + + it('should return 200 when creating the connector', async () => { + const { body: createdAction } = await supertest + .post('/api/actions/connector') + .set('kbn-xsrf', 'foo') + .send({ + name: 'An opsgenie action', + connector_type_id: '.opsgenie', + config: { + apiUrl: simulatorUrl, + }, + secrets: { + apiKey: '123', + }, + }) + .expect(200); + + expect(createdAction).to.eql({ + id: createdAction.id, + is_preconfigured: false, + is_deprecated: false, + name: 'An opsgenie action', + connector_type_id: '.opsgenie', + is_missing_secrets: false, + config: { + apiUrl: simulatorUrl, + }, + }); + }); + + it('should return 400 Bad Request when creating the connector without the apiUrl', async () => { + await supertest + .post('/api/actions/connector') + .set('kbn-xsrf', 'foo') + .send({ + name: 'An opsgenie action', + connector_type_id: '.opsgenie', + config: {}, + secrets: { + apiKey: '123', + }, + }) + .expect(400) + .then((resp: any) => { + expect(resp.body).to.eql({ + statusCode: 400, + error: 'Bad Request', + message: + 'error validating action type config: [apiUrl]: expected value of type [string] but got [undefined]', + }); + }); + }); + + it('should return 400 Bad Request when creating the connector with a apiUrl that is not allowed', async () => { + await supertest + .post('/api/actions/connector') + .set('kbn-xsrf', 'foo') + .send({ + name: 'An opsgenie action', + connector_type_id: '.opsgenie', + config: { + apiUrl: 'http://opsgenie.mynonexistent.com', + }, + secrets: { + apiKey: '123', + }, + }) + .expect(400) + .then((resp: any) => { + expect(resp.body).to.eql({ + statusCode: 400, + error: 'Bad Request', + message: + 'error validating action type config: error validating url: target url "http://opsgenie.mynonexistent.com" is not added to the Kibana config xpack.actions.allowedHosts', + }); + }); + }); + + it('should return 400 Bad Request when creating the connector without secrets', async () => { + await supertest + .post('/api/actions/connector') + .set('kbn-xsrf', 'foo') + .send({ + name: 'An opsgenie action', + connector_type_id: '.opsgenie', + config: { + apiUrl: simulatorUrl, + }, + }) + .expect(400) + .then((resp: any) => { + expect(resp.body).to.eql({ + statusCode: 400, + error: 'Bad Request', + message: + 'error validating action type secrets: [apiKey]: expected value of type [string] but got [undefined]', + }); + }); + }); + }); + + describe('executor', () => { + describe('validation', () => { + const simulator = new OpsgenieSimulator({ + proxy: { + config: configService.get('kbnTestServer.serverArgs'), + }, + }); + let simulatorUrl: string; + let opsgenieActionId: string; + + before(async () => { + simulatorUrl = await simulator.start(); + opsgenieActionId = await createConnector(simulatorUrl); + }); + + after(() => { + simulator.close(); + }); + + it('should fail when the params is empty', async () => { + const { body } = await supertest + .post(`/api/actions/connector/${opsgenieActionId}/_execute`) + .set('kbn-xsrf', 'foo') + .send({ + params: {}, + }); + expect(200); + + expect(Object.keys(body)).to.eql(['status', 'message', 'retry', 'connector_id']); + expect(body.connector_id).to.eql(opsgenieActionId); + expect(body.status).to.eql('error'); + }); + + it('should fail when the subAction is invalid', async () => { + const { body } = await supertest + .post(`/api/actions/connector/${opsgenieActionId}/_execute`) + .set('kbn-xsrf', 'foo') + .send({ + params: { subAction: 'invalidAction' }, + }) + .expect(200); + + expect(body).to.eql({ + connector_id: opsgenieActionId, + status: 'error', + retry: false, + message: 'an error occurred while running the action', + service_message: `Sub action "invalidAction" is not registered. Connector id: ${opsgenieActionId}. Connector name: Opsgenie. Connector type: .opsgenie`, + }); + }); + + it("should fail to create an alert when the message parameter isn't included", async () => { + const { body } = await supertest + .post(`/api/actions/connector/${opsgenieActionId}/_execute`) + .set('kbn-xsrf', 'foo') + .send({ + params: { subAction: 'createAlert', subActionParams: {} }, + }) + .expect(200); + + expect(body).to.eql({ + connector_id: opsgenieActionId, + status: 'error', + retry: false, + message: 'an error occurred while running the action', + service_message: + 'Request validation failed (Error: [message]: expected value of type [string] but got [undefined])', + }); + }); + + it("should fail to close an alert when the alias parameter isn't included", async () => { + const { body } = await supertest + .post(`/api/actions/connector/${opsgenieActionId}/_execute`) + .set('kbn-xsrf', 'foo') + .send({ + params: { subAction: 'closeAlert', subActionParams: {} }, + }) + .expect(200); + + expect(body).to.eql({ + connector_id: opsgenieActionId, + status: 'error', + retry: false, + message: 'an error occurred while running the action', + service_message: + 'Request validation failed (Error: [alias]: expected value of type [string] but got [undefined])', + }); + }); + + describe('optional parameters', async () => { + describe('responders', () => { + it('should fail to create an alert when the responders is an invalid type', async () => { + const { body } = await supertest + .post(`/api/actions/connector/${opsgenieActionId}/_execute`) + .set('kbn-xsrf', 'foo') + .send({ + params: { + subAction: 'createAlert', + subActionParams: { + message: 'hello', + responders: [ + { + name: 'sam', + type: 'invalidType', + }, + ], + }, + }, + }) + .expect(200); + + expect(body).to.eql({ + connector_id: opsgenieActionId, + status: 'error', + retry: false, + message: 'an error occurred while running the action', + service_message: + 'Request validation failed (Error: [responders.0]: types that failed validation:\n- [responders.0.0.type]: types that failed validation:\n - [responders.0.type.0]: expected value to equal [team]\n - [responders.0.type.1]: expected value to equal [user]\n - [responders.0.type.2]: expected value to equal [escalation]\n - [responders.0.type.3]: expected value to equal [schedule]\n- [responders.0.1.id]: expected value of type [string] but got [undefined])', + }); + }); + + it('should fail to create an alert when the responders is missing the id', async () => { + const { body } = await supertest + .post(`/api/actions/connector/${opsgenieActionId}/_execute`) + .set('kbn-xsrf', 'foo') + .send({ + params: { + subAction: 'createAlert', + subActionParams: { + message: 'hello', + responders: [ + { + type: 'schedule', + }, + ], + }, + }, + }) + .expect(200); + + expect(body).to.eql({ + connector_id: opsgenieActionId, + status: 'error', + retry: false, + message: 'an error occurred while running the action', + service_message: + 'Request validation failed (Error: [responders.0]: types that failed validation:\n- [responders.0.0.name]: expected value of type [string] but got [undefined]\n- [responders.0.1.id]: expected value of type [string] but got [undefined])', + }); + }); + + it('should succeed to create an alert when the responders has a valid team and id', async () => { + const { body } = await supertest + .post(`/api/actions/connector/${opsgenieActionId}/_execute`) + .set('kbn-xsrf', 'foo') + .send({ + params: { + subAction: 'createAlert', + subActionParams: { + message: 'hello', + responders: [ + { + id: '123', + type: 'team', + }, + { + id: '456', + type: 'team', + }, + ], + }, + }, + }) + .expect(200); + + expect(body).to.eql({ + connector_id: opsgenieActionId, + status: 'ok', + data: { + requestId: '43a29c5c-3dbf-4fa4-9c26-f4f71023e120', + result: 'Request will be processed', + took: 0.107, + }, + }); + }); + + it('should succeed to create an alert when the responders has a valid escalation and name', async () => { + const { body } = await supertest + .post(`/api/actions/connector/${opsgenieActionId}/_execute`) + .set('kbn-xsrf', 'foo') + .send({ + params: { + subAction: 'createAlert', + subActionParams: { + message: 'hello', + responders: [ + { + name: 'sam', + type: 'escalation', + }, + { + name: 'bob', + type: 'escalation', + }, + ], + }, + }, + }) + .expect(200); + + expect(body).to.eql({ + connector_id: opsgenieActionId, + status: 'ok', + data: { + requestId: '43a29c5c-3dbf-4fa4-9c26-f4f71023e120', + result: 'Request will be processed', + took: 0.107, + }, + }); + }); + }); + + describe('visibleTo', () => { + it('should fail to create an alert when the visibleTo uses the name field with type user', async () => { + const { body } = await supertest + .post(`/api/actions/connector/${opsgenieActionId}/_execute`) + .set('kbn-xsrf', 'foo') + .send({ + params: { + subAction: 'createAlert', + subActionParams: { + message: 'hello', + visibleTo: [ + { + name: 'sam', + type: 'user', + }, + ], + }, + }, + }) + .expect(200); + + expect(body).to.eql({ + connector_id: opsgenieActionId, + status: 'error', + retry: false, + message: 'an error occurred while running the action', + service_message: + 'Request validation failed (Error: [visibleTo.0]: types that failed validation:\n- [visibleTo.0.0.type]: expected value to equal [team]\n- [visibleTo.0.1.id]: expected value of type [string] but got [undefined]\n- [visibleTo.0.2.id]: expected value of type [string] but got [undefined]\n- [visibleTo.0.3.username]: expected value of type [string] but got [undefined])', + }); + }); + + it('should succeed to create an alert when the visibleTo is set to a user', async () => { + const { body } = await supertest + .post(`/api/actions/connector/${opsgenieActionId}/_execute`) + .set('kbn-xsrf', 'foo') + .send({ + params: { + subAction: 'createAlert', + subActionParams: { + message: 'hello', + visibleTo: [ + { + username: 'sam', + type: 'user', + }, + { + username: 'bob', + type: 'user', + }, + ], + }, + }, + }) + .expect(200); + + expect(body).to.eql({ + connector_id: opsgenieActionId, + status: 'ok', + data: { + requestId: '43a29c5c-3dbf-4fa4-9c26-f4f71023e120', + result: 'Request will be processed', + took: 0.107, + }, + }); + }); + }); + + describe('details', () => { + it('should fail to create an alert when the details field is a record of string to number', async () => { + const { body } = await supertest + .post(`/api/actions/connector/${opsgenieActionId}/_execute`) + .set('kbn-xsrf', 'foo') + .send({ + params: { + subAction: 'createAlert', + subActionParams: { + message: 'hello', + details: { + bananas: 1, + }, + }, + }, + }) + .expect(200); + + expect(body).to.eql({ + connector_id: opsgenieActionId, + status: 'error', + retry: false, + message: 'an error occurred while running the action', + service_message: + 'Request validation failed (Error: [details.bananas]: expected value of type [string] but got [number])', + }); + }); + + it('should succeed to create an alert when the details field a record of string to string', async () => { + const { body } = await supertest + .post(`/api/actions/connector/${opsgenieActionId}/_execute`) + .set('kbn-xsrf', 'foo') + .send({ + params: { + subAction: 'createAlert', + subActionParams: { + message: 'hello', + details: { + bananas: 'hello', + }, + }, + }, + }) + .expect(200); + + expect(body).to.eql({ + connector_id: opsgenieActionId, + status: 'ok', + data: { + requestId: '43a29c5c-3dbf-4fa4-9c26-f4f71023e120', + result: 'Request will be processed', + took: 0.107, + }, + }); + }); + }); + }); + }); + + describe('execution', () => { + describe('successful response simulator', () => { + const simulator = new OpsgenieSimulator({ + proxy: { + config: configService.get('kbnTestServer.serverArgs'), + }, + }); + let simulatorUrl: string; + let opsgenieActionId: string; + let createAlertUrl: string; + + before(async () => { + simulatorUrl = await simulator.start(); + createAlertUrl = createUrlString(simulatorUrl, 'v2/alerts'); + opsgenieActionId = await createConnector(simulatorUrl); + }); + + after(() => { + simulator.close(); + }); + + it('should create an alert', async () => { + const { body } = await supertest + .post(`/api/actions/connector/${opsgenieActionId}/_execute`) + .set('kbn-xsrf', 'foo') + .send({ + params: { subAction: 'createAlert', subActionParams: { message: 'message' } }, + }) + .expect(200); + + expect(simulator.requestData).to.eql({ message: 'message' }); + expect(simulator.requestUrl).to.eql(createAlertUrl); + expect(body).to.eql({ + status: 'ok', + connector_id: opsgenieActionId, + data: opsgenieSuccessResponse, + }); + }); + + it('should preserve the alias when it is 512 characters when creating an alert', async () => { + const alias = 'a'.repeat(512); + + const { body } = await supertest + .post(`/api/actions/connector/${opsgenieActionId}/_execute`) + .set('kbn-xsrf', 'foo') + .send({ + params: { + subAction: 'createAlert', + subActionParams: { message: 'message', alias }, + }, + }) + .expect(200); + + expect(simulator.requestData).to.eql({ message: 'message', alias }); + expect(simulator.requestUrl).to.eql(createAlertUrl); + expect(body).to.eql({ + status: 'ok', + connector_id: opsgenieActionId, + data: opsgenieSuccessResponse, + }); + }); + + it('should sha256 hash the alias when it is over 512 characters when creating an alert', async () => { + const alias = 'a'.repeat(513); + + // sha256 hash for 513 a characters + const hashedAlias = + 'sha-02425c0f5b0dabf3d2b9115f3f7723a02ad8bcfb1534a0d231614fd42b8188f6'; + + const { body } = await supertest + .post(`/api/actions/connector/${opsgenieActionId}/_execute`) + .set('kbn-xsrf', 'foo') + .send({ + params: { + subAction: 'createAlert', + subActionParams: { message: 'message', alias }, + }, + }) + .expect(200); + + expect(simulator.requestData).to.eql({ message: 'message', alias: hashedAlias }); + expect(simulator.requestUrl).to.eql(createAlertUrl); + expect(body).to.eql({ + status: 'ok', + connector_id: opsgenieActionId, + data: opsgenieSuccessResponse, + }); + }); + + it('should sha256 hash the alias when it is over 512 characters when closing an alert', async () => { + const alias = 'a'.repeat(513); + + // sha256 hash for 513 a characters + const hashedAlias = + 'sha-02425c0f5b0dabf3d2b9115f3f7723a02ad8bcfb1534a0d231614fd42b8188f6'; + + const { body } = await supertest + .post(`/api/actions/connector/${opsgenieActionId}/_execute`) + .set('kbn-xsrf', 'foo') + .send({ + params: { + subAction: 'closeAlert', + subActionParams: { alias }, + }, + }) + .expect(200); + + expect(simulator.requestData).to.eql({}); + expect(simulator.requestUrl).to.eql( + createCloseAlertUrl(simulatorUrl, `v2/alerts/${hashedAlias}/close`) + ); + expect(body).to.eql({ + status: 'ok', + connector_id: opsgenieActionId, + data: opsgenieSuccessResponse, + }); + }); + + it('should close an alert', async () => { + const { body } = await supertest + .post(`/api/actions/connector/${opsgenieActionId}/_execute`) + .set('kbn-xsrf', 'foo') + .send({ + params: { subAction: 'closeAlert', subActionParams: { alias: '123' } }, + }) + .expect(200); + + expect(simulator.requestData).to.eql({}); + expect(simulator.requestUrl).to.eql( + createCloseAlertUrl(simulatorUrl, 'v2/alerts/123/close') + ); + expect(body).to.eql({ + status: 'ok', + connector_id: opsgenieActionId, + data: opsgenieSuccessResponse, + }); + }); + + it('should close an alert with an alias that is 512 characters', async () => { + const alias = 'a'.repeat(512); + + const { body } = await supertest + .post(`/api/actions/connector/${opsgenieActionId}/_execute`) + .set('kbn-xsrf', 'foo') + .send({ + params: { subAction: 'closeAlert', subActionParams: { alias } }, + }) + .expect(200); + + expect(simulator.requestData).to.eql({}); + expect(simulator.requestUrl).to.eql( + createCloseAlertUrl(simulatorUrl, `v2/alerts/${alias}/close`) + ); + expect(body).to.eql({ + status: 'ok', + connector_id: opsgenieActionId, + data: opsgenieSuccessResponse, + }); + }); + }); + + describe('error response simulator', () => { + const simulator = new OpsgenieSimulator({ + returnError: true, + proxy: { + config: configService.get('kbnTestServer.serverArgs'), + }, + }); + + let simulatorUrl: string; + let opsgenieActionId: string; + + before(async () => { + simulatorUrl = await simulator.start(); + opsgenieActionId = await createConnector(simulatorUrl); + }); + + after(() => { + simulator.close(); + }); + + it('should return a failure when attempting to create an alert', async () => { + const { body } = await supertest + .post(`/api/actions/connector/${opsgenieActionId}/_execute`) + .set('kbn-xsrf', 'foo') + .send({ + params: { + subAction: 'createAlert', + subActionParams: { message: 'message', note: 'a note' }, + }, + }) + .expect(200); + + expect(simulator.requestData).to.eql({ message: 'message', note: 'a note' }); + expect(body).to.eql({ + status: 'error', + message: 'an error occurred while running the action', + retry: false, + connector_id: opsgenieActionId, + service_message: 'Status code: undefined. Message: Message: failed', + }); + }); + + it('should return a failure when attempting to close an alert', async () => { + const { body } = await supertest + .post(`/api/actions/connector/${opsgenieActionId}/_execute`) + .set('kbn-xsrf', 'foo') + .send({ + params: { + subAction: 'closeAlert', + subActionParams: { note: 'a note', alias: '123' }, + }, + }) + .expect(200); + + expect(simulator.requestData).to.eql({ note: 'a note' }); + expect(body).to.eql({ + status: 'error', + message: 'an error occurred while running the action', + retry: false, + connector_id: opsgenieActionId, + service_message: 'Status code: undefined. Message: Message: failed', + }); + }); + }); + }); + + const createConnector = async (url: string) => { + const { body } = await supertest + .post('/api/actions/connector') + .set('kbn-xsrf', 'foo') + .send({ + name: 'An Opsgenie simulator', + connector_type_id: '.opsgenie', + config: { + apiUrl: url, + }, + secrets: { + apiKey: '123', + }, + }) + .expect(200); + + return body.id; + }; + }); + }); +} + +const createCloseAlertUrl = (baseUrl: string, path: string) => { + return createUrlString(baseUrl, path, { identifierType: 'alias' }); +}; + +const createUrlString = (baseUrl: string, path: string, queryParams?: Record) => { + const fullURL = new URL(path, baseUrl); + + for (const [key, value] of Object.entries(queryParams ?? {})) { + fullURL.searchParams.set(key, value); + } + + return fullURL.toString(); +}; diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/index.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/index.ts index 5207b0c711411..34fd7d16b26ff 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/index.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/index.ts @@ -29,6 +29,7 @@ export default function connectorsTests({ loadTestFile, getService }: FtrProvide loadTestFile(require.resolve('./connector_types/stack/email')); loadTestFile(require.resolve('./connector_types/stack/es_index')); loadTestFile(require.resolve('./connector_types/stack/es_index_preconfigured')); + loadTestFile(require.resolve('./connector_types/stack/opsgenie')); loadTestFile(require.resolve('./connector_types/stack/pagerduty')); loadTestFile(require.resolve('./connector_types/stack/server_log')); loadTestFile(require.resolve('./connector_types/stack/slack')); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/alerts.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/alerts.ts index 8f1b8047e4331..707fab5d57a3d 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/alerts.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/alerts.ts @@ -1237,6 +1237,7 @@ instanceStateValue: true expect(eventEnd <= dateNow).to.equal(true); expect(event?.event?.outcome).to.equal(outcome); + expect(event?.kibana?.alerting?.outcome).to.equal(outcome); expect(event?.kibana?.saved_objects).to.eql([ { diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/builtin_alert_types/index_threshold/alert.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/builtin_alert_types/index_threshold/alert.ts index c06eb41759d63..4dae8cdccd1cb 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/builtin_alert_types/index_threshold/alert.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/builtin_alert_types/index_threshold/alert.ts @@ -55,9 +55,6 @@ export default function ruleTests({ getService }: FtrProviderContext) { const endDateMillis = Date.now() + (RULE_INTERVALS_TO_WRITE - 1) * RULE_INTERVAL_MILLIS; endDate = new Date(endDateMillis).toISOString(); - // write documents from now to the future end date in 3 groups - await createEsDocumentsInGroups(3); - await createDataStream(es, ES_TEST_DATA_STREAM_NAME); }); @@ -72,6 +69,9 @@ export default function ruleTests({ getService }: FtrProviderContext) { // never fire; the tests ensure the ones that should fire, do fire, and // those that shouldn't fire, do not fire. it('runs correctly: count all < >', async () => { + // write documents from now to the future end date in 3 groups + await createEsDocumentsInGroups(3); + await createRule({ name: 'never fire', aggType: 'count', @@ -106,6 +106,9 @@ export default function ruleTests({ getService }: FtrProviderContext) { }); it('runs correctly: count grouped <= =>', async () => { + // write documents from now to the future end date in 3 groups + await createEsDocumentsInGroups(3); + await createRule({ name: 'never fire', aggType: 'count', @@ -150,6 +153,9 @@ export default function ruleTests({ getService }: FtrProviderContext) { }); it('runs correctly: sum all between', async () => { + // write documents from now to the future end date in 3 groups + await createEsDocumentsInGroups(3); + await createRule({ name: 'never fire', aggType: 'sum', @@ -184,6 +190,9 @@ export default function ruleTests({ getService }: FtrProviderContext) { }); it('runs correctly: avg all', async () => { + // write documents from now to the future end date in 3 groups + await createEsDocumentsInGroups(3); + // this never fires because of bad fields error await createRule({ name: 'never fire', @@ -220,6 +229,9 @@ export default function ruleTests({ getService }: FtrProviderContext) { }); it('runs correctly: max grouped', async () => { + // write documents from now to the future end date in 3 groups + await createEsDocumentsInGroups(3); + await createRule({ name: 'never fire', aggType: 'max', @@ -266,6 +278,8 @@ export default function ruleTests({ getService }: FtrProviderContext) { }); it('runs correctly: max grouped on float', async () => { + // write documents from now to the future end date in 3 groups + await createEsDocumentsInGroups(3); await createRule({ name: 'never fire', aggType: 'max', @@ -305,6 +319,9 @@ export default function ruleTests({ getService }: FtrProviderContext) { }); it('runs correctly: max grouped on unsigned long', async () => { + // write documents from now to the future end date in 3 groups + await createEsDocumentsInGroups(3); + await createRule({ name: 'never fire', aggType: 'max', @@ -344,6 +361,9 @@ export default function ruleTests({ getService }: FtrProviderContext) { }); it('runs correctly: min grouped', async () => { + // write documents from now to the future end date in 3 groups + await createEsDocumentsInGroups(3); + await createRule({ name: 'never fire', aggType: 'min', @@ -390,6 +410,9 @@ export default function ruleTests({ getService }: FtrProviderContext) { }); it('runs correctly and populates recovery context', async () => { + // write documents from now to the future end date in 3 groups + await createEsDocumentsInGroups(3); + // This rule should be active initially when the number of documents is below the threshold // and then recover when we add more documents. await createRule({ @@ -438,6 +461,9 @@ export default function ruleTests({ getService }: FtrProviderContext) { }); it('runs correctly over a data stream: count all < >', async () => { + // write documents from now to the future end date in 3 groups + await createEsDocumentsInGroups(3); + await createRule({ name: 'never fire', aggType: 'count', @@ -477,6 +503,35 @@ export default function ruleTests({ getService }: FtrProviderContext) { } }); + it('runs correctly: filters by Kuery', async () => { + // add documents that have timestamp as "now" + await createEsDocumentsWithGroups({ + es, + esTestIndexTool, + endDate: new Date().toISOString(), + intervals: 5, + intervalMillis: 5000, + groups: 3, + indexName: ES_TEST_INDEX_NAME, + }); + + await createRule({ + name: 'always fire', + aggType: 'count', + groupBy: 'all', + thresholdComparator: '>', + timeWindowSize: 3000, + threshold: [-1], + filterKuery: 'group: group-0', + }); + + const docs = await waitForDocs(1); + const doc = docs[0]; + const { message } = doc._source.params; + + expect(message).to.contain('Value: 5'); + }); + async function createEsDocumentsInGroups( groups: number, indexName: string = ES_TEST_INDEX_NAME @@ -513,6 +568,7 @@ export default function ruleTests({ getService }: FtrProviderContext) { threshold: number[]; notifyWhen?: string; indexName?: string; + filterKuery?: string; } async function createRule(params: CreateRuleParams): Promise { @@ -584,6 +640,7 @@ export default function ruleTests({ getService }: FtrProviderContext) { timeWindowUnit: 's', thresholdComparator: params.thresholdComparator, threshold: params.threshold, + filterKuery: params.filterKuery, }, }); diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/event_log.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/event_log.ts index 2e63bed197864..e2a3736e57764 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/event_log.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/event_log.ts @@ -670,6 +670,11 @@ export function validateEvent(event: IValidatedEvent, params: ValidateEventLogPa expect( isSavedObjectInEvent(event, spaceId, savedObject.type, savedObject.id, savedObject.rel) ).to.be(true); + + // event?.kibana?.alerting?.outcome is only populated for alerts + if (savedObject.type === 'alert') { + expect(event?.kibana?.alerting?.outcome).to.equal(outcome); + } } expect(event?.message).to.eql(message); diff --git a/x-pack/test/api_integration/apis/aiops/explain_log_rate_spikes.ts b/x-pack/test/api_integration/apis/aiops/explain_log_rate_spikes.ts index a2e1f158a73e2..2804fc3fc3e0e 100644 --- a/x-pack/test/api_integration/apis/aiops/explain_log_rate_spikes.ts +++ b/x-pack/test/api_integration/apis/aiops/explain_log_rate_spikes.ts @@ -75,13 +75,21 @@ export default ({ getService }: FtrProviderContext) => { await esArchiver.unload('x-pack/test/functional/es_archives/ml/ecommerce'); }); - it('should return full data without streaming', async () => { + async function requestWithoutStreaming(body: ApiExplainLogRateSpikes['body']) { const resp = await supertest .post(`/internal/aiops/explain_log_rate_spikes`) .set('kbn-xsrf', 'kibana') - .send(requestBody) + .send(body) .expect(200); + // compression is on by default so if the request body is undefined + // the response header should include "gzip" and otherwise be "undefined" + if (body.compressResponse === undefined) { + expect(resp.header['content-encoding']).to.be('gzip'); + } else if (body.compressResponse === false) { + expect(resp.header['content-encoding']).to.be(undefined); + } + expect(Buffer.isBuffer(resp.body)).to.be(true); const chunks: string[] = resp.body.toString().split('\n'); @@ -131,34 +139,64 @@ export default ({ getService }: FtrProviderContext) => { histograms.forEach((h, index) => { expect(h.histogram.length).to.be(20); }); + } + + it('should return full data without streaming with compression with flushFix', async () => { + await requestWithoutStreaming(requestBody); + }); + + it('should return full data without streaming with compression without flushFix', async () => { + await requestWithoutStreaming({ ...requestBody, flushFix: false }); }); - it('should return data in chunks with streaming', async () => { - const response = await fetch(`${kibanaServerUrl}/internal/aiops/explain_log_rate_spikes`, { + it('should return full data without streaming without compression with flushFix', async () => { + await requestWithoutStreaming({ ...requestBody, compressResponse: false }); + }); + + it('should return full data without streaming without compression without flushFix', async () => { + await requestWithoutStreaming({ ...requestBody, compressResponse: false, flushFix: false }); + }); + + async function requestWithStreaming(body: ApiExplainLogRateSpikes['body']) { + const resp = await fetch(`${kibanaServerUrl}/internal/aiops/explain_log_rate_spikes`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'kbn-xsrf': 'stream', }, - body: JSON.stringify(requestBody), + body: JSON.stringify(body), }); - expect(response.ok).to.be(true); - expect(response.status).to.be(200); + // compression is on by default so if the request body is undefined + // the response header should include "gzip" and otherwise be "null" + if (body.compressResponse === undefined) { + expect(resp.headers.get('content-encoding')).to.be('gzip'); + } else if (body.compressResponse === false) { + expect(resp.headers.get('content-encoding')).to.be(null); + } + + expect(resp.ok).to.be(true); + expect(resp.status).to.be(200); - const stream = response.body; + const stream = resp.body; expect(stream).not.to.be(null); if (stream !== null) { const data: any[] = []; + let chunkCounter = 0; + const parseStreamCallback = (c: number) => (chunkCounter = c); - for await (const action of parseStream(stream)) { + for await (const action of parseStream(stream, parseStreamCallback)) { expect(action.type).not.to.be('error'); data.push(action); } + // If streaming works correctly we should receive more than one chunk. + expect(chunkCounter).to.be.greaterThan(1); + expect(data.length).to.be(expected.actionsLength); + const addChangePointsActions = data.filter((d) => d.type === expected.changePointFilter); expect(addChangePointsActions.length).to.greaterThan(0); @@ -189,6 +227,22 @@ export default ({ getService }: FtrProviderContext) => { expect(h.histogram.length).to.be(20); }); } + } + + it('should return data in chunks with streaming with compression with flushFix', async () => { + await requestWithStreaming(requestBody); + }); + + it('should return data in chunks with streaming with compression without flushFix', async () => { + await requestWithStreaming({ ...requestBody, flushFix: false }); + }); + + it('should return data in chunks with streaming without compression with flushFix', async () => { + await requestWithStreaming({ ...requestBody, compressResponse: false }); + }); + + it('should return data in chunks with streaming without compression without flushFix', async () => { + await requestWithStreaming({ ...requestBody, compressResponse: false, flushFix: false }); }); it('should return an error for non existing index without streaming', async () => { diff --git a/x-pack/test/api_integration/apis/aiops/parse_stream.ts b/x-pack/test/api_integration/apis/aiops/parse_stream.ts index f3da52e6024bb..70ee86bb64fd8 100644 --- a/x-pack/test/api_integration/apis/aiops/parse_stream.ts +++ b/x-pack/test/api_integration/apis/aiops/parse_stream.ts @@ -5,11 +5,16 @@ * 2.0. */ -export async function* parseStream(stream: NodeJS.ReadableStream) { +export async function* parseStream( + stream: NodeJS.ReadableStream, + callback?: (chunkCounter: number) => void +) { let partial = ''; + let chunkCounter = 0; try { for await (const value of stream) { + chunkCounter++; const full = `${partial}${value}`; const parts = full.split('\n'); const last = parts.pop(); @@ -25,4 +30,8 @@ export async function* parseStream(stream: NodeJS.ReadableStream) { } catch (error) { yield { type: 'error', payload: error.toString() }; } + + if (typeof callback === 'function') { + callback(chunkCounter); + } } diff --git a/x-pack/test/api_integration/apis/logs_ui/log_threshold_alert.ts b/x-pack/test/api_integration/apis/logs_ui/log_threshold_alert.ts index 43699de65e524..2ada34d4dcd5f 100644 --- a/x-pack/test/api_integration/apis/logs_ui/log_threshold_alert.ts +++ b/x-pack/test/api_integration/apis/logs_ui/log_threshold_alert.ts @@ -10,6 +10,8 @@ import sinon from 'sinon'; import { executeAlert, executeRatioAlert, + LogThresholdAlertFactory, + LogThresholdAlertLimit, } from '@kbn/infra-plugin/server/lib/alerting/log_threshold/log_threshold_executor'; import { Comparator, @@ -28,9 +30,13 @@ export default function ({ getService }: FtrProviderContext) { after(() => esArchiver.unload('x-pack/test/functional/es_archives/infra/alerts_test_data')); describe('without group by', () => { - it('should work', async () => { + it('should trigger alerts below the alert limit', async () => { const timestamp = new Date(DATES['alert-test-data'].gauge.max); - const alertFactory = sinon.fake(); + const alertFactory = sinon.fake() as SinonSpyOf; + const alertLimit = { + getValue: sinon.fake.returns(10), + setLimitReached: sinon.fake(), + } as SinonSpiesOf; const ruleParams = { count: { comparator: Comparator.GT_OR_EQ, @@ -46,6 +52,7 @@ export default function ({ getService }: FtrProviderContext) { }, ], }; + await executeAlert( ruleParams, '@timestamp', @@ -53,8 +60,10 @@ export default function ({ getService }: FtrProviderContext) { {}, esClient, alertFactory, + alertLimit, timestamp.valueOf() ); + expect(alertFactory.callCount).to.equal(1); expect(alertFactory.getCall(0).args).to.eql([ '*', @@ -74,13 +83,18 @@ export default function ({ getService }: FtrProviderContext) { }, ], ]); + expect(alertLimit.setLimitReached.calledOnceWith(false)).to.be(true); }); }); describe('with group by', () => { - it('should work', async () => { + it('should trigger alerts up to the alert limit', async () => { const timestamp = new Date(DATES['alert-test-data'].gauge.max); - const alertFactory = sinon.fake(); + const alertFactory = sinon.fake() as SinonSpyOf; + const alertLimit = { + getValue: sinon.fake.returns(2), + setLimitReached: sinon.fake(), + } as SinonSpiesOf; const ruleParams = { count: { comparator: Comparator.GT_OR_EQ, @@ -97,6 +111,7 @@ export default function ({ getService }: FtrProviderContext) { }, ], }; + await executeAlert( ruleParams, '@timestamp', @@ -104,8 +119,10 @@ export default function ({ getService }: FtrProviderContext) { {}, esClient, alertFactory, + alertLimit, timestamp.valueOf() ); + expect(alertFactory.callCount).to.equal(2); expect(alertFactory.getCall(0).args).to.eql([ 'dev', @@ -125,6 +142,64 @@ export default function ({ getService }: FtrProviderContext) { }, ], ]); + expect(alertLimit.setLimitReached.calledOnceWith(true)).to.be(true); + }); + + it('should limit alerts to the alert limit', async () => { + const timestamp = new Date(DATES['alert-test-data'].gauge.max); + const alertFactory = sinon.fake() as SinonSpyOf; + const alertLimit = { + getValue: sinon.fake.returns(1), + setLimitReached: sinon.fake(), + } as SinonSpiesOf; + const ruleParams = { + count: { + comparator: Comparator.GT_OR_EQ, + value: 1, + }, + timeUnit: 'm' as TimeUnit, + timeSize: 5, + groupBy: ['env'], + criteria: [ + { + field: 'env', + comparator: Comparator.NOT_EQ, + value: 'test', + }, + ], + }; + + await executeAlert( + ruleParams, + '@timestamp', + 'alerts-test-data', + {}, + esClient, + alertFactory, + alertLimit, + timestamp.valueOf() + ); + + expect(alertFactory.callCount).to.equal(1); + expect(alertFactory.getCall(0).args).to.eql([ + 'dev', + '2 log entries in the last 5 mins for dev. Alert when ≥ 1.', + 2, + 1, + [ + { + actionGroup: 'logs.threshold.fired', + context: { + conditions: 'env does not equal test', + group: 'dev', + isRatio: false, + matchingDocuments: 2, + reason: '2 log entries in the last 5 mins for dev. Alert when ≥ 1.', + }, + }, + ], + ]); + expect(alertLimit.setLimitReached.calledOnceWith(true)).to.be(true); }); }); }); @@ -134,9 +209,13 @@ export default function ({ getService }: FtrProviderContext) { after(() => esArchiver.unload('x-pack/test/functional/es_archives/infra/ten_thousand_plus')); describe('without group by', () => { - it('should work', async () => { + it('should trigger alerts below the alert limit', async () => { const timestamp = new Date(DATES.ten_thousand_plus.max); - const alertFactory = sinon.fake(); + const alertFactory = sinon.fake() as SinonSpyOf; + const alertLimit = { + getValue: sinon.fake.returns(2), + setLimitReached: sinon.fake(), + } as SinonSpiesOf; const ruleParams = { count: { comparator: Comparator.GT_OR_EQ, @@ -156,6 +235,7 @@ export default function ({ getService }: FtrProviderContext) { {}, esClient, alertFactory, + alertLimit, timestamp.valueOf() ); expect(alertFactory.callCount).to.equal(1); @@ -179,13 +259,18 @@ export default function ({ getService }: FtrProviderContext) { }, ], ]); + expect(alertLimit.setLimitReached.calledOnceWith(false)).to.be(true); }); }); describe('with group by', () => { - it('should work', async () => { + it('should trigger alerts below the alert limit', async () => { const timestamp = new Date(DATES.ten_thousand_plus.max); - const alertFactory = sinon.fake(); + const alertFactory = sinon.fake() as SinonSpyOf; + const alertLimit = { + getValue: sinon.fake.returns(2), + setLimitReached: sinon.fake(), + } as SinonSpiesOf; const ruleParams = { count: { comparator: Comparator.GT_OR_EQ, @@ -206,6 +291,7 @@ export default function ({ getService }: FtrProviderContext) { {}, esClient, alertFactory, + alertLimit, timestamp.valueOf() ); expect(alertFactory.callCount).to.equal(1); @@ -229,8 +315,18 @@ export default function ({ getService }: FtrProviderContext) { }, ], ]); + expect(alertLimit.setLimitReached.calledOnceWith(false)).to.be(true); }); }); }); }); } + +type SinonSpyOf any> = sinon.SinonSpy< + Parameters, + ReturnType +>; + +type SinonSpiesOf any>> = { + [Key in keyof SpyTarget]: SinonSpyOf; +}; diff --git a/x-pack/test/api_integration/apis/metrics_ui/inventory_threshold_alert.ts b/x-pack/test/api_integration/apis/metrics_ui/inventory_threshold_alert.ts index 999a89926cf5c..077d362960259 100644 --- a/x-pack/test/api_integration/apis/metrics_ui/inventory_threshold_alert.ts +++ b/x-pack/test/api_integration/apis/metrics_ui/inventory_threshold_alert.ts @@ -102,6 +102,14 @@ export default function ({ getService }: FtrProviderContext) { isNoData: false, isError: false, currentValue: 1.109, + context: { + cloud: undefined, + host: { name: 'host-0' }, + container: undefined, + orchestrator: undefined, + labels: { eventId: 'event-0', groupId: 'group-0' }, + tags: undefined, + }, }, }); }); @@ -125,6 +133,14 @@ export default function ({ getService }: FtrProviderContext) { isNoData: false, isError: false, currentValue: 1.0376666666666665, + context: { + cloud: undefined, + host: { name: 'host-0' }, + container: undefined, + orchestrator: undefined, + labels: { eventId: 'event-0', groupId: 'group-0' }, + tags: undefined, + }, }, }); }); @@ -157,6 +173,14 @@ export default function ({ getService }: FtrProviderContext) { isNoData: false, isError: false, currentValue: 79351.95, + context: { + cloud: undefined, + host: { name: 'host-0', network: {} }, + container: undefined, + orchestrator: undefined, + labels: undefined, + tags: undefined, + }, }, 'host-1': { metric: 'rx', @@ -170,6 +194,14 @@ export default function ({ getService }: FtrProviderContext) { isNoData: false, isError: false, currentValue: 10, + context: { + cloud: undefined, + host: { name: 'host-1', network: {} }, + container: undefined, + orchestrator: undefined, + labels: undefined, + tags: undefined, + }, }, }); }); @@ -198,6 +230,14 @@ export default function ({ getService }: FtrProviderContext) { isNoData: false, isError: false, currentValue: 79351.95, + context: { + cloud: undefined, + host: { name: 'host-0', network: {} }, + container: undefined, + orchestrator: undefined, + labels: undefined, + tags: undefined, + }, }, 'host-1': { metric: 'rx', @@ -211,6 +251,14 @@ export default function ({ getService }: FtrProviderContext) { isNoData: false, isError: false, currentValue: 10, + context: { + cloud: undefined, + host: { name: 'host-1', network: {} }, + container: undefined, + orchestrator: undefined, + labels: undefined, + tags: undefined, + }, }, }); }); @@ -240,6 +288,14 @@ export default function ({ getService }: FtrProviderContext) { isNoData: false, isError: false, currentValue: 125658.70833333333, + context: { + cloud: undefined, + host: { name: 'host-0', network: {} }, + container: undefined, + orchestrator: undefined, + labels: undefined, + tags: undefined, + }, }, 'host-1': { metric: 'rx', @@ -253,6 +309,14 @@ export default function ({ getService }: FtrProviderContext) { isNoData: false, isError: false, currentValue: 11.666666666666668, + context: { + cloud: undefined, + host: { name: 'host-1', network: {} }, + container: undefined, + orchestrator: undefined, + labels: undefined, + tags: undefined, + }, }, }); }); @@ -298,6 +362,14 @@ export default function ({ getService }: FtrProviderContext) { isNoData: false, isError: false, currentValue: 833.3333333333334, + context: { + cloud: undefined, + host: { name: 'host-0' }, + container: undefined, + orchestrator: undefined, + labels: { eventId: 'event-0', groupId: 'group-0' }, + tags: undefined, + }, }, 'host-1': { metric: 'custom', @@ -318,6 +390,14 @@ export default function ({ getService }: FtrProviderContext) { isNoData: false, isError: false, currentValue: 1000, + context: { + cloud: undefined, + host: { name: 'host-1' }, + container: undefined, + orchestrator: undefined, + labels: { eventId: 'event-1', groupId: 'group-0' }, + tags: undefined, + }, }, }); }); @@ -359,6 +439,14 @@ export default function ({ getService }: FtrProviderContext) { isNoData: false, isError: false, currentValue: 1133.3333333333333, + context: { + cloud: undefined, + host: { name: 'host-0' }, + container: undefined, + orchestrator: undefined, + labels: { eventId: 'event-0', groupId: 'group-0' }, + tags: undefined, + }, }, 'host-1': { metric: 'custom', @@ -379,6 +467,14 @@ export default function ({ getService }: FtrProviderContext) { isNoData: false, isError: false, currentValue: 1133.3333333333333, + context: { + cloud: undefined, + host: { name: 'host-1' }, + container: undefined, + orchestrator: undefined, + labels: { eventId: 'event-1', groupId: 'group-0' }, + tags: undefined, + }, }, }); }); @@ -411,6 +507,14 @@ export default function ({ getService }: FtrProviderContext) { isNoData: false, isError: false, currentValue: 0.3, + context: { + cloud: undefined, + host: { name: 'host-0' }, + container: undefined, + orchestrator: undefined, + labels: { eventId: 'event-0', groupId: 'group-0' }, + tags: undefined, + }, }, 'host-1': { metric: 'logRate', @@ -424,6 +528,14 @@ export default function ({ getService }: FtrProviderContext) { isNoData: false, isError: false, currentValue: 0.3, + context: { + cloud: undefined, + host: { name: 'host-1' }, + container: undefined, + orchestrator: undefined, + labels: { eventId: 'event-1', groupId: 'group-0' }, + tags: undefined, + }, }, }); }); @@ -453,6 +565,14 @@ export default function ({ getService }: FtrProviderContext) { isNoData: false, isError: false, currentValue: 0.3, + context: { + cloud: undefined, + host: { name: 'host-0' }, + container: undefined, + orchestrator: undefined, + labels: { eventId: 'event-0', groupId: 'group-0' }, + tags: undefined, + }, }, 'host-1': { metric: 'logRate', @@ -466,6 +586,14 @@ export default function ({ getService }: FtrProviderContext) { isNoData: false, isError: false, currentValue: 0.3, + context: { + cloud: undefined, + host: { name: 'host-1' }, + container: undefined, + orchestrator: undefined, + labels: { eventId: 'event-1', groupId: 'group-0' }, + tags: undefined, + }, }, }); }); @@ -499,6 +627,14 @@ export default function ({ getService }: FtrProviderContext) { isNoData: false, isError: false, currentValue: 43332.833333333336, + context: { + cloud: undefined, + host: undefined, + container: undefined, + orchestrator: undefined, + labels: undefined, + tags: undefined, + }, }, 'ed01e3a3-4787-42f6-b73e-ac9e97294e9d': { metric: 'rx', @@ -512,6 +648,14 @@ export default function ({ getService }: FtrProviderContext) { isNoData: false, isError: false, currentValue: 42783.833333333336, + context: { + cloud: undefined, + host: undefined, + container: undefined, + orchestrator: undefined, + labels: undefined, + tags: undefined, + }, }, }); }); @@ -542,6 +686,14 @@ export default function ({ getService }: FtrProviderContext) { isNoData: false, isError: false, currentValue: 50197.666666666664, + context: { + cloud: undefined, + host: undefined, + container: undefined, + orchestrator: undefined, + labels: undefined, + tags: undefined, + }, }, 'ed01e3a3-4787-42f6-b73e-ac9e97294e9d': { metric: 'rx', @@ -555,6 +707,14 @@ export default function ({ getService }: FtrProviderContext) { isNoData: false, isError: false, currentValue: 50622.066666666666, + context: { + cloud: undefined, + host: undefined, + container: undefined, + orchestrator: undefined, + labels: undefined, + tags: undefined, + }, }, }); }); diff --git a/x-pack/test/api_integration/apis/ml/notifications/count_notifications.ts b/x-pack/test/api_integration/apis/ml/notifications/count_notifications.ts index 58932ea199b5d..fa3e12448be07 100644 --- a/x-pack/test/api_integration/apis/ml/notifications/count_notifications.ts +++ b/x-pack/test/api_integration/apis/ml/notifications/count_notifications.ts @@ -16,40 +16,57 @@ export default ({ getService }: FtrProviderContext) => { const ml = getService('ml'); describe('GET notifications count', () => { - before(async () => { - await ml.api.initSavedObjects(); - await ml.testResources.setKibanaTimeZoneToUTC(); + describe('when no ML entities present', () => { + it('return a default response', async () => { + const { body, status } = await supertest + .get(`/api/ml/notifications/count`) + .query({ lastCheckedAt: moment().subtract(7, 'd').valueOf() }) + .auth(USER.ML_POWERUSER, ml.securityCommon.getPasswordForUser(USER.ML_POWERUSER)) + .set(COMMON_REQUEST_HEADERS); + ml.api.assertResponseStatusCode(200, status, body); - const adJobConfig = ml.commonConfig.getADFqSingleMetricJobConfig('fq_job'); - await ml.api.createAnomalyDetectionJob(adJobConfig); - - await ml.api.waitForJobNotificationsToIndex('fq_job'); + expect(body.info).to.eql(0); + expect(body.warning).to.eql(0); + expect(body.error).to.eql(0); + }); }); - after(async () => { - await ml.api.cleanMlIndices(); - await ml.testResources.cleanMLSavedObjects(); - }); + describe('when ML entities exist', () => { + before(async () => { + await ml.api.initSavedObjects(); + await ml.testResources.setKibanaTimeZoneToUTC(); - it('return notifications count by level', async () => { - const { body, status } = await supertest - .get(`/api/ml/notifications/count`) - .query({ lastCheckedAt: moment().subtract(7, 'd').valueOf() }) - .auth(USER.ML_POWERUSER, ml.securityCommon.getPasswordForUser(USER.ML_POWERUSER)) - .set(COMMON_REQUEST_HEADERS); - ml.api.assertResponseStatusCode(200, status, body); - - expect(body.info).to.eql(1); - expect(body.warning).to.eql(0); - expect(body.error).to.eql(0); - }); + const adJobConfig = ml.commonConfig.getADFqSingleMetricJobConfig('fq_job'); + await ml.api.createAnomalyDetectionJob(adJobConfig); + + await ml.api.waitForJobNotificationsToIndex('fq_job'); + }); + + after(async () => { + await ml.api.cleanMlIndices(); + await ml.testResources.cleanMLSavedObjects(); + }); + + it('return notifications count by level', async () => { + const { body, status } = await supertest + .get(`/api/ml/notifications/count`) + .query({ lastCheckedAt: moment().subtract(7, 'd').valueOf() }) + .auth(USER.ML_POWERUSER, ml.securityCommon.getPasswordForUser(USER.ML_POWERUSER)) + .set(COMMON_REQUEST_HEADERS); + ml.api.assertResponseStatusCode(200, status, body); + + expect(body.info).to.eql(1); + expect(body.warning).to.eql(0); + expect(body.error).to.eql(0); + }); - it('returns an error for unauthorized user', async () => { - const { body, status } = await supertest - .get(`/api/ml/notifications/count`) - .auth(USER.ML_UNAUTHORIZED, ml.securityCommon.getPasswordForUser(USER.ML_UNAUTHORIZED)) - .set(COMMON_REQUEST_HEADERS); - ml.api.assertResponseStatusCode(403, status, body); + it('returns an error for unauthorized user', async () => { + const { body, status } = await supertest + .get(`/api/ml/notifications/count`) + .auth(USER.ML_UNAUTHORIZED, ml.securityCommon.getPasswordForUser(USER.ML_UNAUTHORIZED)) + .set(COMMON_REQUEST_HEADERS); + ml.api.assertResponseStatusCode(403, status, body); + }); }); }); }; diff --git a/x-pack/test/api_integration/apis/security/privileges.ts b/x-pack/test/api_integration/apis/security/privileges.ts index 3e6d18ef40840..987c22e35064f 100644 --- a/x-pack/test/api_integration/apis/security/privileges.ts +++ b/x-pack/test/api_integration/apis/security/privileges.ts @@ -14,70 +14,71 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ getService }: FtrProviderContext) { const supertest = getService('supertest'); + const expectedWithoutActions = { + global: ['all', 'read'], + space: ['all', 'read'], + features: { + graph: ['all', 'read', 'minimal_all', 'minimal_read'], + savedObjectsTagging: ['all', 'read', 'minimal_all', 'minimal_read'], + canvas: ['all', 'read', 'minimal_all', 'minimal_read'], + maps: ['all', 'read', 'minimal_all', 'minimal_read'], + generalCases: ['all', 'read', 'minimal_all', 'minimal_read', 'cases_delete'], + observabilityCases: ['all', 'read', 'minimal_all', 'minimal_read', 'cases_delete'], + fleetv2: ['all', 'read', 'minimal_all', 'minimal_read'], + fleet: ['all', 'read', 'minimal_all', 'minimal_read'], + actions: ['all', 'read', 'minimal_all', 'minimal_read'], + stackAlerts: ['all', 'read', 'minimal_all', 'minimal_read'], + ml: ['all', 'read', 'minimal_all', 'minimal_read'], + siem: ['all', 'read', 'minimal_all', 'minimal_read'], + uptime: ['all', 'read', 'minimal_all', 'minimal_read'], + securitySolutionCases: ['all', 'read', 'minimal_all', 'minimal_read', 'cases_delete'], + infrastructure: ['all', 'read', 'minimal_all', 'minimal_read'], + logs: ['all', 'read', 'minimal_all', 'minimal_read'], + apm: ['all', 'read', 'minimal_all', 'minimal_read'], + discover: [ + 'all', + 'read', + 'minimal_all', + 'minimal_read', + 'url_create', + 'store_search_session', + ], + visualize: ['all', 'read', 'minimal_all', 'minimal_read', 'url_create'], + dashboard: [ + 'all', + 'read', + 'minimal_all', + 'minimal_read', + 'url_create', + 'store_search_session', + ], + dev_tools: ['all', 'read', 'minimal_all', 'minimal_read'], + advancedSettings: ['all', 'read', 'minimal_all', 'minimal_read'], + indexPatterns: ['all', 'read', 'minimal_all', 'minimal_read'], + savedObjectsManagement: ['all', 'read', 'minimal_all', 'minimal_read'], + osquery: [ + 'all', + 'read', + 'minimal_all', + 'minimal_read', + 'live_queries_all', + 'live_queries_read', + 'run_saved_queries', + 'saved_queries_all', + 'saved_queries_read', + 'packs_all', + 'packs_read', + ], + }, + reserved: ['fleet-setup', 'ml_user', 'ml_admin', 'ml_apm_user', 'monitoring'], + }; + describe('Privileges', () => { describe('GET /api/security/privileges', () => { it('should return a privilege map with all known privileges, without actions', async () => { // If you're adding a privilege to the following, that's great! // If you're removing a privilege, this breaks backwards compatibility // Roles are associated with these privileges, and we shouldn't be removing them in a minor version. - const expected = { - global: ['all', 'read'], - space: ['all', 'read'], - features: { - graph: ['all', 'read', 'minimal_all', 'minimal_read'], - savedObjectsTagging: ['all', 'read', 'minimal_all', 'minimal_read'], - canvas: ['all', 'read', 'minimal_all', 'minimal_read'], - maps: ['all', 'read', 'minimal_all', 'minimal_read'], - generalCases: ['all', 'read', 'minimal_all', 'minimal_read', 'cases_delete'], - observabilityCases: ['all', 'read', 'minimal_all', 'minimal_read', 'cases_delete'], - fleetv2: ['all', 'read', 'minimal_all', 'minimal_read'], - fleet: ['all', 'read', 'minimal_all', 'minimal_read'], - actions: ['all', 'read', 'minimal_all', 'minimal_read'], - stackAlerts: ['all', 'read', 'minimal_all', 'minimal_read'], - ml: ['all', 'read', 'minimal_all', 'minimal_read'], - siem: ['all', 'read', 'minimal_all', 'minimal_read'], - uptime: ['all', 'read', 'minimal_all', 'minimal_read'], - securitySolutionCases: ['all', 'read', 'minimal_all', 'minimal_read', 'cases_delete'], - infrastructure: ['all', 'read', 'minimal_all', 'minimal_read'], - logs: ['all', 'read', 'minimal_all', 'minimal_read'], - apm: ['all', 'read', 'minimal_all', 'minimal_read'], - discover: [ - 'all', - 'read', - 'minimal_all', - 'minimal_read', - 'url_create', - 'store_search_session', - ], - visualize: ['all', 'read', 'minimal_all', 'minimal_read', 'url_create'], - dashboard: [ - 'all', - 'read', - 'minimal_all', - 'minimal_read', - 'url_create', - 'store_search_session', - ], - dev_tools: ['all', 'read', 'minimal_all', 'minimal_read'], - advancedSettings: ['all', 'read', 'minimal_all', 'minimal_read'], - indexPatterns: ['all', 'read', 'minimal_all', 'minimal_read'], - savedObjectsManagement: ['all', 'read', 'minimal_all', 'minimal_read'], - osquery: [ - 'all', - 'read', - 'minimal_all', - 'minimal_read', - 'live_queries_all', - 'live_queries_read', - 'run_saved_queries', - 'saved_queries_all', - 'saved_queries_read', - 'packs_all', - 'packs_read', - ], - }, - reserved: ['fleet-setup', 'ml_user', 'ml_admin', 'ml_apm_user', 'monitoring'], - }; await supertest .get('/api/security/privileges') @@ -89,7 +90,7 @@ export default function ({ getService }: FtrProviderContext) { // supertest uses assert.deepStrictEqual. // expect.js doesn't help us here. // and lodash's isEqual doesn't know how to compare Sets. - const success = isEqualWith(res.body, expected, (value, other, key) => { + const success = isEqualWith(res.body, expectedWithoutActions, (value, other, key) => { if (Array.isArray(value) && Array.isArray(other)) { if (key === 'reserved') { // order does not matter for the reserved privilege set. @@ -106,7 +107,9 @@ export default function ({ getService }: FtrProviderContext) { if (!success) { throw new Error( - `Expected ${util.inspect(res.body)} to equal ${util.inspect(expected)}` + `Expected ${util.inspect(res.body)} to equal ${util.inspect( + expectedWithoutActions + )}` ); } }) @@ -178,5 +181,115 @@ export default function ({ getService }: FtrProviderContext) { }); }); }); + + // In this non-Basic case, results should be exactly the same as not supplying the respectLicenseLevel flag + describe('GET /api/security/privileges?respectLicenseLevel=false', () => { + it('should return a privilege map with all known privileges, without actions', async () => { + // If you're adding a privilege to the following, that's great! + // If you're removing a privilege, this breaks backwards compatibility + // Roles are associated with these privileges, and we shouldn't be removing them in a minor version. + + await supertest + .get('/api/security/privileges?respectLicenseLevel=false') + .set('kbn-xsrf', 'xxx') + .send() + .expect(200) + .expect((res: any) => { + // when comparing privileges, the order of the features doesn't matter (but the order of the privileges does) + // supertest uses assert.deepStrictEqual. + // expect.js doesn't help us here. + // and lodash's isEqual doesn't know how to compare Sets. + const success = isEqualWith(res.body, expectedWithoutActions, (value, other, key) => { + if (Array.isArray(value) && Array.isArray(other)) { + if (key === 'reserved') { + // order does not matter for the reserved privilege set. + return isEqual(value.sort(), other.sort()); + } + // order matters for the rest, as the UI assumes they are returned in a descending order of permissiveness. + return isEqual(value, other); + } + + // Lodash types aren't correct, `undefined` should be supported as a return value here and it + // has special meaning. + return undefined as any; + }); + + if (!success) { + throw new Error( + `Expected ${util.inspect(res.body)} to equal ${util.inspect( + expectedWithoutActions + )}` + ); + } + }) + .expect(200); + }); + }); + + // In this non-Basic case, results should be exactly the same as not supplying the respectLicenseLevel flag + describe('GET /api/security/privileges?includeActions=true&respectLicenseLevel=false', () => { + // The UI assumes that no wildcards are present when calculating the effective set of privileges. + // If this changes, then the "privilege calculators" will need revisiting to account for these wildcards. + it('should return a privilege map with actions which do not include wildcards', async () => { + await supertest + .get('/api/security/privileges?includeActions=true') + .set('kbn-xsrf', 'xxx') + .send() + .expect(200) + .expect((res: any) => { + const { features, global, space, reserved } = res.body as RawKibanaPrivileges; + expect(features).to.be.an('object'); + expect(global).to.be.an('object'); + expect(space).to.be.an('object'); + expect(reserved).to.be.an('object'); + + Object.entries(features).forEach(([featureId, featurePrivs]) => { + Object.values(featurePrivs).forEach((actions) => { + expect(actions).to.be.an('array'); + actions.forEach((action) => { + expect(action).to.be.a('string'); + expect(action.indexOf('*')).to.eql( + -1, + `Feature ${featureId} with action ${action} cannot contain a wildcard` + ); + }); + }); + }); + + Object.entries(global).forEach(([privilegeId, actions]) => { + expect(actions).to.be.an('array'); + actions.forEach((action) => { + expect(action).to.be.a('string'); + expect(action.indexOf('*')).to.eql( + -1, + `Global privilege ${privilegeId} with action ${action} cannot contain a wildcard` + ); + }); + }); + + Object.entries(space).forEach(([privilegeId, actions]) => { + expect(actions).to.be.an('array'); + actions.forEach((action) => { + expect(action).to.be.a('string'); + expect(action.indexOf('*')).to.eql( + -1, + `Space privilege ${privilegeId} with action ${action} cannot contain a wildcard` + ); + }); + }); + + Object.entries(reserved).forEach(([privilegeId, actions]) => { + expect(actions).to.be.an('array'); + actions.forEach((action) => { + expect(action).to.be.a('string'); + expect(action.indexOf('*')).to.eql( + -1, + `Reserved privilege ${privilegeId} with action ${action} cannot contain a wildcard` + ); + }); + }); + }); + }); + }); }); } diff --git a/x-pack/test/api_integration/apis/security/privileges_basic.ts b/x-pack/test/api_integration/apis/security/privileges_basic.ts index dfc60aaebca34..3d470259267e4 100644 --- a/x-pack/test/api_integration/apis/security/privileges_basic.ts +++ b/x-pack/test/api_integration/apis/security/privileges_basic.ts @@ -79,6 +79,95 @@ export default function ({ getService }: FtrProviderContext) { }) .expect(200); }); + + it('should include sub-feature privileges when respectlicenseLevel is false', async () => { + const expected = { + global: ['all', 'read'], + space: ['all', 'read'], + features: { + graph: ['all', 'read', 'minimal_all', 'minimal_read'], + savedObjectsTagging: ['all', 'read', 'minimal_all', 'minimal_read'], + canvas: ['all', 'read', 'minimal_all', 'minimal_read'], + maps: ['all', 'read', 'minimal_all', 'minimal_read'], + generalCases: ['all', 'read', 'minimal_all', 'minimal_read', 'cases_delete'], + observabilityCases: ['all', 'read', 'minimal_all', 'minimal_read', 'cases_delete'], + fleetv2: ['all', 'read', 'minimal_all', 'minimal_read'], + fleet: ['all', 'read', 'minimal_all', 'minimal_read'], + actions: ['all', 'read', 'minimal_all', 'minimal_read'], + stackAlerts: ['all', 'read', 'minimal_all', 'minimal_read'], + ml: ['all', 'read', 'minimal_all', 'minimal_read'], + siem: ['all', 'read', 'minimal_all', 'minimal_read'], + uptime: ['all', 'read', 'minimal_all', 'minimal_read'], + securitySolutionCases: ['all', 'read', 'minimal_all', 'minimal_read', 'cases_delete'], + infrastructure: ['all', 'read', 'minimal_all', 'minimal_read'], + logs: ['all', 'read', 'minimal_all', 'minimal_read'], + apm: ['all', 'read', 'minimal_all', 'minimal_read'], + discover: [ + 'all', + 'read', + 'minimal_all', + 'minimal_read', + 'url_create', + 'store_search_session', + ], + visualize: ['all', 'read', 'minimal_all', 'minimal_read', 'url_create'], + dashboard: [ + 'all', + 'read', + 'minimal_all', + 'minimal_read', + 'url_create', + 'store_search_session', + ], + dev_tools: ['all', 'read', 'minimal_all', 'minimal_read'], + advancedSettings: ['all', 'read', 'minimal_all', 'minimal_read'], + indexPatterns: ['all', 'read', 'minimal_all', 'minimal_read'], + savedObjectsManagement: ['all', 'read', 'minimal_all', 'minimal_read'], + osquery: [ + 'all', + 'read', + 'minimal_all', + 'minimal_read', + 'live_queries_all', + 'live_queries_read', + 'run_saved_queries', + 'saved_queries_all', + 'saved_queries_read', + 'packs_all', + 'packs_read', + ], + }, + reserved: ['fleet-setup', 'ml_user', 'ml_admin', 'ml_apm_user', 'monitoring'], + }; + + await supertest + .get('/api/security/privileges?respectLicenseLevel=false') + .set('kbn-xsrf', 'xxx') + .send() + .expect(200) + .expect((res: any) => { + // when comparing privileges, the order of the privileges doesn't matter. + // supertest uses assert.deepStrictEqual. + // expect.js doesn't help us here. + // and lodash's isEqual doesn't know how to compare Sets. + const success = isEqualWith(res.body, expected, (value, other, key) => { + if (Array.isArray(value) && Array.isArray(other)) { + return isEqual(value.sort(), other.sort()); + } + + // Lodash types aren't correct, `undefined` should be supported as a return value here and it + // has special meaning. + return undefined as any; + }); + + if (!success) { + throw new Error( + `Expected ${util.inspect(res.body)} to equal ${util.inspect(expected)}` + ); + } + }) + .expect(200); + }); }); }); } diff --git a/x-pack/test/apm_api_integration/tests/service_nodes/get_service_nodes.spec.ts b/x-pack/test/apm_api_integration/tests/service_nodes/get_service_nodes.spec.ts index 5aeb0e7db72a4..6008480234668 100644 --- a/x-pack/test/apm_api_integration/tests/service_nodes/get_service_nodes.spec.ts +++ b/x-pack/test/apm_api_integration/tests/service_nodes/get_service_nodes.spec.ts @@ -21,7 +21,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { async function callApi() { return await apmApiClient.readUser({ - endpoint: 'GET /internal/apm/services/{serviceName}/serviceNodes', + endpoint: 'GET /internal/apm/services/{serviceName}/metrics/nodes', params: { path: { serviceName }, query: { diff --git a/x-pack/test/cases_api_integration/common/config.ts b/x-pack/test/cases_api_integration/common/config.ts index 6d3f59f30dc75..535fcca87183f 100644 --- a/x-pack/test/cases_api_integration/common/config.ts +++ b/x-pack/test/cases_api_integration/common/config.ts @@ -18,6 +18,7 @@ interface CreateTestConfigOptions { disabledPlugins?: string[]; ssl?: boolean; testFiles?: string[]; + publicBaseUrl?: boolean; } const enabledActionTypes = [ @@ -115,6 +116,7 @@ export function createTestConfig(name: string, options: CreateTestConfigOptions) ...xPackApiIntegrationTestsConfig.get('kbnTestServer'), serverArgs: [ ...xPackApiIntegrationTestsConfig.get('kbnTestServer.serverArgs'), + ...(options.publicBaseUrl ? ['--server.publicBaseUrl=https://localhost:5601'] : []), `--xpack.actions.allowedHosts=${JSON.stringify(['localhost', 'some.non.existent.com'])}`, `--xpack.actions.enabledActionTypes=${JSON.stringify(enabledActionTypes)}`, '--xpack.eventLog.logEntries=true', diff --git a/x-pack/test/cases_api_integration/common/lib/mock.ts b/x-pack/test/cases_api_integration/common/lib/mock.ts index 0d7185a1fabd7..f81d7e45cce9e 100644 --- a/x-pack/test/cases_api_integration/common/lib/mock.ts +++ b/x-pack/test/cases_api_integration/common/lib/mock.ts @@ -70,6 +70,14 @@ export const postCommentAlertReq: CommentRequestAlertType = { owner: 'securitySolutionFixture', }; +export const postCommentAlertMultipleIdsReq: CommentRequestAlertType = { + alertId: ['test-id-1', 'test-id-2'], + index: ['test-index', 'test-index-2'], + rule: { id: 'test-rule-id', name: 'test-index-id' }, + type: CommentType.alert, + owner: 'securitySolutionFixture', +}; + export const postCommentActionsReq: CommentRequestActionsType = { comment: 'comment text', actions: { @@ -85,6 +93,21 @@ export const postCommentActionsReq: CommentRequestActionsType = { owner: 'securitySolutionFixture', }; +export const postCommentActionsReleaseReq: CommentRequestActionsType = { + comment: 'comment text', + actions: { + targets: [ + { + hostname: 'host-name', + endpointId: 'endpoint-id', + }, + ], + type: 'unisolate', + }, + type: CommentType.actions, + owner: 'securitySolutionFixture', +}; + export const postExternalReferenceESReq: CommentRequestExternalReferenceNoSOType = { type: CommentType.externalReference, externalReferenceStorage: { type: ExternalReferenceStorageType.elasticSearchDoc }, diff --git a/x-pack/test/cases_api_integration/security_and_spaces/config_basic.ts b/x-pack/test/cases_api_integration/security_and_spaces/config_basic.ts index 98b7b1abe98e7..ce01d6132d601 100644 --- a/x-pack/test/cases_api_integration/security_and_spaces/config_basic.ts +++ b/x-pack/test/cases_api_integration/security_and_spaces/config_basic.ts @@ -12,4 +12,5 @@ export default createTestConfig('security_and_spaces', { license: 'basic', ssl: true, testFiles: [require.resolve('./tests/basic')], + publicBaseUrl: true, }); diff --git a/x-pack/test/cases_api_integration/security_and_spaces/config_no_public_base_url.ts b/x-pack/test/cases_api_integration/security_and_spaces/config_no_public_base_url.ts new file mode 100644 index 0000000000000..a47dcdbfcbab7 --- /dev/null +++ b/x-pack/test/cases_api_integration/security_and_spaces/config_no_public_base_url.ts @@ -0,0 +1,16 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { createTestConfig } from '../common/config'; + +// eslint-disable-next-line import/no-default-export +export default createTestConfig('security_and_spaces', { + license: 'trial', + ssl: true, + testFiles: [require.resolve('./tests/no_public_base_url')], + publicBaseUrl: false, +}); diff --git a/x-pack/test/cases_api_integration/security_and_spaces/config_trial.ts b/x-pack/test/cases_api_integration/security_and_spaces/config_trial.ts index b5328fd83c2cb..f6e7e39922091 100644 --- a/x-pack/test/cases_api_integration/security_and_spaces/config_trial.ts +++ b/x-pack/test/cases_api_integration/security_and_spaces/config_trial.ts @@ -12,4 +12,5 @@ export default createTestConfig('security_and_spaces', { license: 'trial', ssl: true, testFiles: [require.resolve('./tests/trial')], + publicBaseUrl: true, }); diff --git a/x-pack/test/cases_api_integration/security_and_spaces/tests/no_public_base_url/index.ts b/x-pack/test/cases_api_integration/security_and_spaces/tests/no_public_base_url/index.ts new file mode 100644 index 0000000000000..3b7fc6128b97c --- /dev/null +++ b/x-pack/test/cases_api_integration/security_and_spaces/tests/no_public_base_url/index.ts @@ -0,0 +1,24 @@ +/* + * 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 '../../../common/ftr_provider_context'; +import { createSpacesAndUsers, deleteSpacesAndUsers } from '../../../common/lib/authentication'; + +// eslint-disable-next-line import/no-default-export +export default ({ loadTestFile, getService }: FtrProviderContext): void => { + describe('cases security and spaces enabled: no_public_base_url', function () { + before(async () => { + await createSpacesAndUsers(getService); + }); + + after(async () => { + await deleteSpacesAndUsers(getService); + }); + + loadTestFile(require.resolve('./push')); + }); +}; diff --git a/x-pack/test/cases_api_integration/security_and_spaces/tests/no_public_base_url/push.ts b/x-pack/test/cases_api_integration/security_and_spaces/tests/no_public_base_url/push.ts new file mode 100644 index 0000000000000..0f3e521988c55 --- /dev/null +++ b/x-pack/test/cases_api_integration/security_and_spaces/tests/no_public_base_url/push.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 expect from '@kbn/expect'; +import { + postCommentUserReq, + postCommentAlertReq, + postCommentAlertMultipleIdsReq, + postCommentActionsReq, + postCommentActionsReleaseReq, + postExternalReferenceESReq, + persistableStateAttachment, +} from '../../../common/lib/mock'; +import { FtrProviderContext } from '../../../common/ftr_provider_context'; +import { ObjectRemover as ActionsRemover } from '../../../../alerting_api_integration/common/lib'; + +import { + pushCase, + deleteAllCaseItems, + createCaseWithConnector, + getRecordingServiceNowSimulatorServer, + bulkCreateAttachments, +} from '../../../common/lib/utils'; +import { RecordingServiceNowSimulator } from '../../../../alerting_api_integration/common/fixtures/plugins/actions_simulators/server/servicenow_simulation'; + +// eslint-disable-next-line import/no-default-export +export default ({ getService }: FtrProviderContext): void => { + const supertest = getService('supertest'); + const es = getService('es'); + + describe('push_case', () => { + describe('incident recorder server', () => { + const actionsRemover = new ActionsRemover(supertest); + let serviceNowSimulatorURL: string = ''; + let serviceNowServer: RecordingServiceNowSimulator; + + beforeEach(async () => { + const { server, url } = await getRecordingServiceNowSimulatorServer(); + serviceNowServer = server; + serviceNowSimulatorURL = url; + }); + + afterEach(async () => { + await deleteAllCaseItems(es); + await actionsRemover.removeAll(); + serviceNowServer.close(); + }); + + it('should push correctly without a publicBaseUrl', async () => { + const { postedCase, connector } = await createCaseWithConnector({ + supertest, + serviceNowSimulatorURL, + actionsRemover, + }); + + await pushCase({ + supertest, + caseId: postedCase.id, + connectorId: connector.id, + }); + + expect(serviceNowServer.incident).eql({ + short_description: postedCase.title, + description: `${postedCase.description}\n\nAdded by elastic.`, + severity: '2', + urgency: '2', + impact: '2', + category: 'software', + subcategory: 'os', + correlation_id: postedCase.id, + correlation_display: 'Elastic Case', + caller_id: 'admin', + opened_by: 'admin', + }); + }); + + it('should format the comments correctly', async () => { + const { postedCase, connector } = await createCaseWithConnector({ + supertest, + serviceNowSimulatorURL, + actionsRemover, + }); + + const patchedCase = await bulkCreateAttachments({ + supertest, + caseId: postedCase.id, + params: [ + postCommentUserReq, + postCommentAlertReq, + postCommentAlertMultipleIdsReq, + postCommentActionsReq, + postCommentActionsReleaseReq, + postExternalReferenceESReq, + persistableStateAttachment, + ], + }); + + await pushCase({ + supertest, + caseId: patchedCase.id, + connectorId: connector.id, + }); + + /** + * If the request contains the work_notes property then + * it is a create comment request + */ + const allCommentRequests = serviceNowServer.allRequestData.filter((request) => + Boolean(request.work_notes) + ); + + /** + * For each of these comments a request is made: + * postCommentUserReq, postCommentActionsReq, postCommentActionsReleaseReq, and a comment with the + * total alerts attach to a case. All other type of comments should be filtered. Specifically, + * postCommentAlertReq, postCommentAlertMultipleIdsReq, postExternalReferenceESReq, and persistableStateAttachment + */ + expect(allCommentRequests.length).be(4); + + // User comment: postCommentUserReq + expect(allCommentRequests[0].work_notes).eql('This is a cool comment\n\nAdded by elastic.'); + + // Isolate host comment: postCommentActionsReq + expect(allCommentRequests[1].work_notes).eql( + 'Isolated host host-name with comment: comment text\n\nAdded by elastic.' + ); + + // Unisolate host comment: postCommentActionsReleaseReq + expect(allCommentRequests[2].work_notes).eql( + 'Released host host-name with comment: comment text\n\nAdded by elastic.' + ); + + // Total alerts + expect(allCommentRequests[3].work_notes).eql('Elastic Alerts attached to the case: 3'); + }); + }); + }); +}; diff --git a/x-pack/test/cases_api_integration/security_and_spaces/tests/trial/cases/push_case.ts b/x-pack/test/cases_api_integration/security_and_spaces/tests/trial/cases/push_case.ts index cbc1b95fb3f47..1a7f53d4e3db9 100644 --- a/x-pack/test/cases_api_integration/security_and_spaces/tests/trial/cases/push_case.ts +++ b/x-pack/test/cases_api_integration/security_and_spaces/tests/trial/cases/push_case.ts @@ -19,6 +19,12 @@ import { defaultUser, postCommentUserReq, getPostCaseRequest, + postCommentAlertReq, + postCommentActionsReq, + postCommentActionsReleaseReq, + postCommentAlertMultipleIdsReq, + persistableStateAttachment, + postExternalReferenceESReq, } from '../../../../common/lib/mock'; import { getConfigurationRequest, @@ -40,6 +46,7 @@ import { calculateDuration, getRecordingServiceNowSimulatorServer, getComment, + bulkCreateAttachments, } from '../../../../common/lib/utils'; import { globalRead, @@ -108,9 +115,103 @@ export default ({ getService }: FtrProviderContext): void => { }); // the full string should look something like this: - // This is a brand new case of a bad meanie defacing data (created at 2022-09-12T20:22:14.328Z by super_full_name) + // This is a brand new case of a bad meanie defacing data.\n\nAdded by super_full_name. expect(serviceNowServer.incident?.description).to.contain('by super_full_name'); }); + + it('should map the fields and add the backlink to Kibana correctly', async () => { + const cookies = await loginUsers({ supertest: supertestWithoutAuth, users: [superUser] }); + + const { postedCase, connector } = await createCaseWithConnector({ + supertest, + serviceNowSimulatorURL, + actionsRemover, + auth: null, + headers: { Cookie: cookies[0].cookieString() }, + }); + + await pushCase({ + supertest, + caseId: postedCase.id, + connectorId: connector.id, + }); + + expect(serviceNowServer.incident).eql({ + short_description: postedCase.title, + description: `${postedCase.description}\n\nAdded by super_full_name.\nFor more details, view this case in Kibana.\nCase URL: https://localhost:5601/app/management/insightsAndAlerting/cases/${postedCase.id}`, + severity: '2', + urgency: '2', + impact: '2', + category: 'software', + subcategory: 'os', + correlation_id: postedCase.id, + correlation_display: 'Elastic Case', + caller_id: 'admin', + opened_by: 'admin', + }); + }); + + it('should format the comments correctly', async () => { + const { postedCase, connector } = await createCaseWithConnector({ + supertest, + serviceNowSimulatorURL, + actionsRemover, + }); + + const patchedCase = await bulkCreateAttachments({ + supertest, + caseId: postedCase.id, + params: [ + postCommentUserReq, + postCommentAlertReq, + postCommentAlertMultipleIdsReq, + postCommentActionsReq, + postCommentActionsReleaseReq, + postExternalReferenceESReq, + persistableStateAttachment, + ], + }); + + await pushCase({ + supertest, + caseId: patchedCase.id, + connectorId: connector.id, + }); + + /** + * If the request contains the work_notes property then + * it is a create comment request + */ + const allCommentRequests = serviceNowServer.allRequestData.filter((request) => + Boolean(request.work_notes) + ); + + /** + * For each of these comments a request is made: + * postCommentUserReq, postCommentActionsReq, postCommentActionsReleaseReq, and a comment with the + * total alerts attach to a case. All other type of comments should be filtered. Specifically, + * postCommentAlertReq, postCommentAlertMultipleIdsReq, postExternalReferenceESReq, and persistableStateAttachment + */ + expect(allCommentRequests.length).be(4); + + // User comment: postCommentUserReq + expect(allCommentRequests[0].work_notes).eql('This is a cool comment\n\nAdded by elastic.'); + + // Isolate host comment: postCommentActionsReq + expect(allCommentRequests[1].work_notes).eql( + 'Isolated host host-name with comment: comment text\n\nAdded by elastic.' + ); + + // Unisolate host comment: postCommentActionsReleaseReq + expect(allCommentRequests[2].work_notes).eql( + 'Released host host-name with comment: comment text\n\nAdded by elastic.' + ); + + // Total alerts + expect(allCommentRequests[3].work_notes).eql( + `Elastic Alerts attached to the case: 3\n\nFor more details, view the alerts in Kibana\nAlerts URL: https://localhost:5601/app/management/insightsAndAlerting/cases/${patchedCase.id}/?tabId=alerts` + ); + }); }); describe('memoryless server', () => { @@ -224,7 +325,7 @@ export default ({ getService }: FtrProviderContext): void => { expect(theCaseAfterUpdate.external_service?.connector_id).to.eql(pushConnector.id); }); - it('should create the mappings when pushing a case', async () => { + it('should push to a connector without mapping', async () => { // create a connector but not a configuration so that the mapping will not be present const connector = await createConnector({ supertest, @@ -257,7 +358,7 @@ export default ({ getService }: FtrProviderContext): void => { ); // there should be no mappings initially - let mappings = await getConnectorMappingsFromES({ es }); + const mappings = await getConnectorMappingsFromES({ es }); expect(mappings.body.hits.hits.length).to.eql(0); await pushCase({ @@ -265,13 +366,6 @@ export default ({ getService }: FtrProviderContext): void => { caseId: postedCase.id, connectorId: connector.id, }); - - // the mappings should now be created after the push - mappings = await getConnectorMappingsFromES({ es }); - expect(mappings.body.hits.hits.length).to.be(1); - expect( - mappings.body.hits.hits[0]._source?.['cases-connector-mappings'].mappings.length - ).to.be.above(0); }); it('pushes a comment appropriately', async () => { diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/create_ml.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/create_ml.ts index c94f73713e6a4..a29963ec3b6cb 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/create_ml.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/create_ml.ts @@ -89,7 +89,8 @@ export default ({ getService }: FtrProviderContext) => { } // FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/125033 - describe('Generating signals from ml anomalies', () => { + // FLAKY: https://github.com/elastic/kibana/issues/142993 + describe.skip('Generating signals from ml anomalies', () => { before(async () => { // Order is critical here: auditbeat data must be loaded before attempting to start the ML job, // as the job looks for certain indices on start diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/template_data/execution_events.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/template_data/execution_events.ts index 4a674c52fa1ed..6d732fbcca866 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/template_data/execution_events.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/template_data/execution_events.ts @@ -60,6 +60,7 @@ export const successfulExecution = [ }, alerting: { status: 'ok', + outcome: 'success', }, server_uuid: '5b2de169-2785-441b-ae8c-186a1936b17d', version: '8.2.0', @@ -445,6 +446,7 @@ export const failedGapExecution = [ }, alerting: { status: 'ok', + outcome: 'success', }, server_uuid: '5b2de169-2785-441b-ae8c-186a1936b17d', version: '8.2.0', @@ -508,6 +510,7 @@ export const partialWarningExecution = [ }, alerting: { status: 'ok', + outcome: 'success', }, server_uuid: '5b2de169-2785-441b-ae8c-186a1936b17d', version: '8.2.0', @@ -692,6 +695,7 @@ export const failedRanAfterDisabled = [ }, alerting: { status: 'error', + outcome: 'failure', }, server_uuid: '5b2de169-2785-441b-ae8c-186a1936b17d', version: '8.3.0', diff --git a/x-pack/test/fleet_api_integration/apis/agent_policy/agent_policy.ts b/x-pack/test/fleet_api_integration/apis/agent_policy/agent_policy.ts index e71c14a8054c8..277bafb998761 100644 --- a/x-pack/test/fleet_api_integration/apis/agent_policy/agent_policy.ts +++ b/x-pack/test/fleet_api_integration/apis/agent_policy/agent_policy.ts @@ -17,6 +17,7 @@ export default function (providerContext: FtrProviderContext) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); const kibanaServer = getService('kibanaServer'); + describe('fleet_agent_policies', () => { skipIfNoDockerRegistry(providerContext); describe('POST /api/fleet/agent_policies', () => { @@ -287,8 +288,20 @@ export default function (providerContext: FtrProviderContext) { setupFleetAndAgents(providerContext); after(async () => { await esArchiver.unload('x-pack/test/functional/es_archives/fleet/agents'); + if (systemPkgVersion) { + await supertest.delete(`/api/fleet/epm/packages/system-${systemPkgVersion}`); + } + if (packagePoliciesToDeleteIds.length > 0) { + await kibanaServer.savedObjects.bulkDelete({ + objects: packagePoliciesToDeleteIds.map((id) => ({ + id, + type: PACKAGE_POLICY_SAVED_OBJECT_TYPE, + })), + }); + } }); - + let systemPkgVersion: string; + const packagePoliciesToDeleteIds: string[] = []; const TEST_POLICY_ID = 'policy1'; it('should work with valid values', async () => { @@ -327,13 +340,43 @@ export default function (providerContext: FtrProviderContext) { }, } = await supertest.get(`/api/fleet/agent_policies/${policyId}`).expect(200); - const matches = packagePolicies[0].name.match(/^(.*)\s\(copy\s?([0-9]*)\)$/); + const matches = packagePolicies[0]?.name.match(/^(.*)\s\(copy\s?([0-9]*)\)$/); + if (matches) { return parseInt(matches[2], 10) || 1; } - return 0; } + + const policyId = 'package-policy-test-1'; + packagePoliciesToDeleteIds.push(policyId); + const getPkRes = await supertest + .get(`/api/fleet/epm/packages/system`) + .set('kbn-xsrf', 'xxxx') + .expect(200); + systemPkgVersion = getPkRes.body.item.version; + // we must first force install the system package to override package verification error on policy create + const installPromise = supertest + .post(`/api/fleet/epm/packages/system-${systemPkgVersion}`) + .set('kbn-xsrf', 'xxxx') + .send({ force: true }) + .expect(200); + + await Promise.all([ + installPromise, + kibanaServer.savedObjects.create({ + id: policyId, + type: PACKAGE_POLICY_SAVED_OBJECT_TYPE, + overwrite: true, + attributes: { + name: `system-1`, + package: { + name: 'system', + }, + }, + }), + ]); + const { body: { item: { id: originalPolicyId }, @@ -349,7 +392,6 @@ export default function (providerContext: FtrProviderContext) { namespace: 'default', }) .expect(200); - expect(await getSystemPackagePolicyCopyVersion(originalPolicyId)).to.be(0); const { diff --git a/x-pack/test/fleet_api_integration/apis/data_streams/list.ts b/x-pack/test/fleet_api_integration/apis/data_streams/list.ts index 72fea406bcbf9..3866002647285 100644 --- a/x-pack/test/fleet_api_integration/apis/data_streams/list.ts +++ b/x-pack/test/fleet_api_integration/apis/data_streams/list.ts @@ -23,6 +23,7 @@ export default function (providerContext: FtrProviderContext) { const pkgVersion = '0.1.0'; const logsTemplateName = `logs-${pkgName}.test_logs`; const metricsTemplateName = `metrics-${pkgName}.test_metrics`; + const notFleetTemplateName = `metrics-${pkgName}.test_metrics_not_fleet`; const uninstallPackage = async (name: string, version: string) => { await supertest.delete(`/api/fleet/epm/packages/${name}/${version}`).set('kbn-xsrf', 'xxxx'); @@ -69,6 +70,24 @@ export default function (providerContext: FtrProviderContext) { }) ); + // This stream should never be returned as it is not + // managed by fleet (it isnt added to a fleet managed data stream) + responses.push( + await es.transport.request({ + method: 'POST', + path: `/${notFleetTemplateName}-default/_doc`, + body: { + '@timestamp': '2015-01-01', + logs_test_name: 'test', + data_stream: { + dataset: `${pkgName}.test_metrics_not_fleet`, + namespace: 'default', + type: 'metrics', + }, + }, + }) + ); + return responses as IndexResponse[]; }; @@ -104,6 +123,10 @@ export default function (providerContext: FtrProviderContext) { method: 'DELETE', path: `/_data_stream/${metricsTemplateName}-default`, }); + await es.transport.request({ + method: 'DELETE', + path: `/_data_stream/${notFleetTemplateName}-default`, + }); } catch (e) { // Silently swallow errors here as not all tests seed data streams } diff --git a/x-pack/test/fleet_api_integration/apis/epm/get.ts b/x-pack/test/fleet_api_integration/apis/epm/get.ts index 2a63e1c8b3905..280922b2e4a33 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/get.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/get.ts @@ -144,6 +144,18 @@ export default function (providerContext: FtrProviderContext) { expect(packageInfo.name).to.equal('apache'); await uninstallPackage(testPkgName, testPkgVersion); }); + it('should return all fields for input only packages', async function () { + // input packages have to get their package info from the manifest directly + // not from the package registry. This is because they contain a field the registry + // does not support + const res = await supertest + .get(`/api/fleet/epm/packages/integration_to_input/0.9.1`) + .expect(200); + + const packageInfo = res.body.item; + expect(packageInfo.policy_templates.length).to.equal(1); + expect(packageInfo.policy_templates[0].vars).not.to.be(undefined); + }); describe('Pkg verification', () => { it('should return validation error for unverified input only pkg', async function () { const res = await supertest.get(`/api/fleet/epm/packages/input_only/0.1.0`).expect(400); diff --git a/x-pack/test/fleet_api_integration/apis/package_policy/create.ts b/x-pack/test/fleet_api_integration/apis/package_policy/create.ts index 10b1b709d188f..21a5fa0f6dc2a 100644 --- a/x-pack/test/fleet_api_integration/apis/package_policy/create.ts +++ b/x-pack/test/fleet_api_integration/apis/package_policy/create.ts @@ -446,6 +446,72 @@ export default function (providerContext: FtrProviderContext) { expect(policy.name).to.equal(nameWithWhitespace.trim()); }); + describe('input only packages', () => { + it('should return 400 if dataset not provided for input only pkg', async function () { + await supertest + .post(`/api/fleet/package_policies`) + .set('kbn-xsrf', 'xxxx') + .send({ + policy_id: agentPolicyId, + package: { + name: 'integration_to_input', + version: '0.9.1', + }, + name: 'integration_to_input-1', + description: '', + namespace: 'default', + inputs: { + 'logs-logfile': { + enabled: true, + streams: { + 'integration_to_input.logs': { + enabled: true, + vars: { + paths: ['/tmp/test.log'], + tags: ['tag1'], + ignore_older: '72h', + }, + }, + }, + }, + }, + }) + .expect(400); + }); + it('should successfully create an input only package policy with all required vars', async function () { + await supertest + .post(`/api/fleet/package_policies`) + .set('kbn-xsrf', 'xxxx') + .send({ + policy_id: agentPolicyId, + package: { + name: 'integration_to_input', + version: '0.9.1', + }, + name: 'integration_to_input-2', + description: '', + namespace: 'default', + inputs: { + 'logs-logfile': { + enabled: true, + streams: { + 'integration_to_input.logs': { + enabled: true, + vars: { + paths: ['/tmp/test.log'], + tags: ['tag1'], + ignore_older: '72h', + 'data_stream.dataset': 'generic', + }, + }, + }, + }, + }, + }) + .expect(200); + }); + }); + describe('Simplified package policy', () => { it('should work with valid values', async () => { await supertest diff --git a/x-pack/test/functional/apps/dashboard/group2/dashboard_tagging.ts b/x-pack/test/functional/apps/dashboard/group2/dashboard_tagging.ts index 535e287cfc5eb..1bd258233a7cc 100644 --- a/x-pack/test/functional/apps/dashboard/group2/dashboard_tagging.ts +++ b/x-pack/test/functional/apps/dashboard/group2/dashboard_tagging.ts @@ -32,7 +32,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await listingTable.waitUntilTableIsLoaded(); // open the filter dropdown - const filterButton = await find.byCssSelector('.euiFilterGroup .euiFilterButton'); + const filterButton = await find.byCssSelector( + '.euiFilterGroup .euiPopover:nth-child(2) .euiFilterButton' + ); await filterButton.click(); await testSubjects.click( `tag-searchbar-option-${PageObjects.tagManagement.testSubjFriendly(dashboardTag)}` diff --git a/x-pack/test/functional/apps/dashboard/group3/drilldowns/dashboard_to_dashboard_drilldown.ts b/x-pack/test/functional/apps/dashboard/group3/drilldowns/dashboard_to_dashboard_drilldown.ts index 1323f62f2a4f9..3b1f9c2065180 100644 --- a/x-pack/test/functional/apps/dashboard/group3/drilldowns/dashboard_to_dashboard_drilldown.ts +++ b/x-pack/test/functional/apps/dashboard/group3/drilldowns/dashboard_to_dashboard_drilldown.ts @@ -37,9 +37,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const spaces = getService('spaces'); const elasticChart = getService('elasticChart'); - // Failing: See https://github.com/elastic/kibana/issues/142913 - // Failing: See https://github.com/elastic/kibana/issues/142912 - describe.skip('Dashboard to dashboard drilldown', function () { + describe('Dashboard to dashboard drilldown', function () { describe('Create & use drilldowns', () => { before(async () => { log.debug('Dashboard Drilldowns:initTests'); 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 48bcf11c0db07..e70e4b59dc31d 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 @@ -18,6 +18,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { 'dashboard', 'timeToVisualize', 'common', + 'discover', ]); const elasticChart = getService('elasticChart'); const fieldEditor = getService('fieldEditor'); @@ -156,8 +157,6 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await browser.switchToWindow(discoverWindowHandle); await PageObjects.header.waitUntilLoadingHasFinished(); - await PageObjects.common.sleep(15000); - const actualIndexPattern = await ( await testSubjects.find('discover-dataView-switch-link') ).getVisibleText(); @@ -165,6 +164,16 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const actualDiscoverQueryHits = await testSubjects.getVisibleText('discoverQueryHits'); expect(actualDiscoverQueryHits).to.be('14,005'); + + const prevDataViewId = await PageObjects.discover.getCurrentDataViewId(); + + await PageObjects.discover.addRuntimeField( + '_bytes-runtimefield', + `emit(doc["bytes"].value.toString())` + ); + await PageObjects.discover.clickFieldListItemToggle('_bytes-runtimefield'); + const newDataViewId = await PageObjects.discover.getCurrentDataViewId(); + expect(newDataViewId).not.to.equal(prevDataViewId); }); }); } diff --git a/x-pack/test/functional/apps/lens/group1/index.ts b/x-pack/test/functional/apps/lens/group1/index.ts index c01a43ce8c6ab..aa2b078a50a6b 100644 --- a/x-pack/test/functional/apps/lens/group1/index.ts +++ b/x-pack/test/functional/apps/lens/group1/index.ts @@ -74,6 +74,7 @@ export default ({ getService, loadTestFile, getPageObjects }: FtrProviderContext } else { loadTestFile(require.resolve('./smokescreen')); loadTestFile(require.resolve('./ad_hoc_data_view')); + loadTestFile(require.resolve('./partition')); loadTestFile(require.resolve('./persistent_context')); loadTestFile(require.resolve('./table_dashboard')); loadTestFile(require.resolve('./table')); diff --git a/x-pack/test/functional/apps/lens/group1/partition.ts b/x-pack/test/functional/apps/lens/group1/partition.ts new file mode 100644 index 0000000000000..45c4d1b1dfda0 --- /dev/null +++ b/x-pack/test/functional/apps/lens/group1/partition.ts @@ -0,0 +1,148 @@ +/* + * 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 expect from '@kbn/expect'; +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ getService, getPageObjects }: FtrProviderContext) { + const PageObjects = getPageObjects(['visualize', 'lens', 'common']); + const testSubjects = getService('testSubjects'); + + describe('lens partition charts', () => { + before(async () => { + await PageObjects.visualize.navigateToNewVisualization(); + await PageObjects.visualize.clickVisType('lens'); + await PageObjects.lens.goToTimeRange(); + }); + + it('should be able to nest up to 3 levels for Pie charts', async () => { + await PageObjects.lens.switchToVisualization('pie'); + + await PageObjects.lens.configureDimension({ + dimension: 'lnsPie_sizeByDimensionPanel > lns-empty-dimension', + operation: 'average', + field: 'bytes', + }); + + for (const field of ['ip', 'extension.raw', 'geo.dest']) { + await PageObjects.lens.configureDimension({ + dimension: 'lnsPie_sliceByDimensionPanel > lns-empty-dimension', + operation: 'terms', + field, + }); + } + }); + + it('should not expose the grouping switch in Pie', async () => { + await PageObjects.lens.openDimensionEditor( + 'lnsPie_sliceByDimensionPanel > lns-dimensionTrigger' + ); + + expect(await testSubjects.exists('indexPattern-nesting-switch')).to.eql(false); + expect(await testSubjects.exists('indexPattern-nesting-select')).to.eql(false); + + await PageObjects.lens.closeDimensionEditor(); + }); + + it('should switch to donut charts keeping all dimensions', async () => { + await PageObjects.lens.switchToVisualization('donut'); + + expect( + await testSubjects.exists('lnsPie_sliceByDimensionPanel > lns-empty-dimension') + ).to.eql(false); + + expect( + (await testSubjects.findAll('lnsPie_sliceByDimensionPanel > lns-dimensionTrigger')).length + ).to.eql(3); + }); + + it('should not expose the grouping switch in Donut', async () => { + await PageObjects.lens.openDimensionEditor( + 'lnsPie_sliceByDimensionPanel > lns-dimensionTrigger' + ); + + expect(await testSubjects.exists('indexPattern-nesting-switch')).to.eql(false); + expect(await testSubjects.exists('indexPattern-nesting-select')).to.eql(false); + + await PageObjects.lens.closeDimensionEditor(); + }); + + it('should switch to treemap chart and keep only the first 2 dimensions', async () => { + await PageObjects.lens.switchToVisualization('treemap'); + + expect( + await testSubjects.exists('lnsPie_groupByDimensionPanel > lns-empty-dimension') + ).to.eql(false); + + expect( + (await testSubjects.findAll('lnsPie_groupByDimensionPanel > lns-dimensionTrigger')).length + ).to.eql(2); + }); + + it('should not expose the grouping switch in Treemap', async () => { + await PageObjects.lens.openDimensionEditor( + 'lnsPie_groupByDimensionPanel > lns-dimensionTrigger' + ); + + expect(await testSubjects.exists('indexPattern-nesting-switch')).to.eql(false); + expect(await testSubjects.exists('indexPattern-nesting-select')).to.eql(false); + + await PageObjects.lens.closeDimensionEditor(); + }); + + it('should switch to Mosaic chart and distribute dimensions as vertical and horizontal', async () => { + await PageObjects.lens.switchToVisualization('mosaic'); + + expect( + await testSubjects.exists('lnsPie_sliceByDimensionPanel > lns-empty-dimension') + ).to.eql(false); + + expect( + (await testSubjects.findAll('lnsPie_verticalAxisDimensionPanel > lns-dimensionTrigger')) + .length + ).to.eql(1); + + expect( + (await testSubjects.findAll('lnsPie_horizontalAxisDimensionPanel > lns-dimensionTrigger')) + .length + ).to.eql(1); + }); + + it('should expose the grouping switch in Mosaic', async () => { + await PageObjects.lens.openDimensionEditor( + 'lnsPie_verticalAxisDimensionPanel > lns-dimensionTrigger' + ); + + expect(await testSubjects.exists('indexPattern-nesting-switch')).to.eql(true); + + await PageObjects.lens.closeDimensionEditor(); + }); + + it('should switch to Waffle chart', async () => { + await PageObjects.lens.switchToVisualization('waffle'); + + expect( + await testSubjects.exists('lnsPie_groupByDimensionPanel > lns-empty-dimension') + ).to.eql(false); + + expect( + (await testSubjects.findAll('lnsPie_groupByDimensionPanel > lns-dimensionTrigger')).length + ).to.eql(1); + }); + + it('should expose the grouping switch in Waffle', async () => { + await PageObjects.lens.openDimensionEditor( + 'lnsPie_groupByDimensionPanel > lns-dimensionTrigger' + ); + + expect(await testSubjects.exists('indexPattern-nesting-switch')).to.eql(false); + expect(await testSubjects.exists('indexPattern-nesting-select')).to.eql(false); + + await PageObjects.lens.closeDimensionEditor(); + }); + }); +} diff --git a/x-pack/test/functional/apps/lens/group3/lens_tagging.ts b/x-pack/test/functional/apps/lens/group3/lens_tagging.ts index d4d9f084a64f7..42bb90e84a903 100644 --- a/x-pack/test/functional/apps/lens/group3/lens_tagging.ts +++ b/x-pack/test/functional/apps/lens/group3/lens_tagging.ts @@ -106,7 +106,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await listingTable.waitUntilTableIsLoaded(); // open the filter dropdown - const filterButton = await find.byCssSelector('.euiFilterGroup .euiFilterButton'); + const filterButton = await find.byCssSelector( + '.euiFilterGroup .euiPopover:nth-child(2) .euiFilterButton' + ); await filterButton.click(); await testSubjects.click( `tag-searchbar-option-${PageObjects.tagManagement.testSubjFriendly(lensTag)}` diff --git a/x-pack/test/functional/apps/lens/group3/open_in_lens/agg_based/gauge.ts b/x-pack/test/functional/apps/lens/group3/open_in_lens/agg_based/gauge.ts new file mode 100644 index 0000000000000..076be5b663ee3 --- /dev/null +++ b/x-pack/test/functional/apps/lens/group3/open_in_lens/agg_based/gauge.ts @@ -0,0 +1,37 @@ +/* + * 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 expect from '@kbn/expect'; +import { FtrProviderContext } from '../../../../../ftr_provider_context'; + +export default function ({ getPageObjects, getService }: FtrProviderContext) { + const { visualize, lens, timePicker } = getPageObjects(['visualize', 'lens', 'timePicker']); + + describe('Gauge', function describeIndexTests() { + const isNewChartsLibraryEnabled = true; + + before(async () => { + await visualize.initTests(isNewChartsLibraryEnabled); + }); + + beforeEach(async () => { + await visualize.navigateToNewAggBasedVisualization(); + await visualize.clickGauge(); + await visualize.clickNewSearch(); + await timePicker.setDefaultAbsoluteRange(); + }); + + it('should show the "Edit Visualization in Lens" menu item', async () => { + expect(await visualize.hasNavigateToLensButton()).to.eql(true); + }); + + it('should convert to Lens', async () => { + await visualize.navigateToLensFromAnotherVisulization(); + await lens.waitForVisualization('gaugeChart'); + }); + }); +} diff --git a/x-pack/test/functional/apps/lens/group3/open_in_lens/agg_based/goal.ts b/x-pack/test/functional/apps/lens/group3/open_in_lens/agg_based/goal.ts new file mode 100644 index 0000000000000..97083c498a453 --- /dev/null +++ b/x-pack/test/functional/apps/lens/group3/open_in_lens/agg_based/goal.ts @@ -0,0 +1,48 @@ +/* + * 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 expect from '@kbn/expect'; +import { FtrProviderContext } from '../../../../../ftr_provider_context'; + +export default function ({ getPageObjects, getService }: FtrProviderContext) { + const { visualize, lens, timePicker } = getPageObjects(['visualize', 'lens', 'timePicker']); + + describe('Goal', function describeIndexTests() { + const isNewChartsLibraryEnabled = true; + + before(async () => { + await visualize.initTests(isNewChartsLibraryEnabled); + }); + + beforeEach(async () => { + await visualize.navigateToNewAggBasedVisualization(); + await visualize.clickGoal(); + await visualize.clickNewSearch(); + await timePicker.setDefaultAbsoluteRange(); + }); + + it('should show the "Edit Visualization in Lens" menu item', async () => { + expect(await visualize.hasNavigateToLensButton()).to.eql(true); + }); + + it('should convert to Lens', async () => { + await visualize.navigateToLensFromAnotherVisulization(); + await lens.waitForVisualization('mtrVis'); + expect((await lens.getMetricVisualizationData()).length).to.be.equal(1); + expect(await lens.getMetricVisualizationData()).to.eql([ + { + title: 'Count', + subtitle: undefined, + extraText: '', + value: '140.05%', + color: 'rgba(245, 247, 250, 1)', + showingBar: true, + }, + ]); + }); + }); +} diff --git a/x-pack/test/functional/apps/lens/group3/open_in_lens/agg_based/index.ts b/x-pack/test/functional/apps/lens/group3/open_in_lens/agg_based/index.ts index 66de13c67d94c..0737c7ffeeb50 100644 --- a/x-pack/test/functional/apps/lens/group3/open_in_lens/agg_based/index.ts +++ b/x-pack/test/functional/apps/lens/group3/open_in_lens/agg_based/index.ts @@ -11,5 +11,9 @@ export default function ({ loadTestFile }: FtrProviderContext) { describe('Agg based Vis to Lens', function () { loadTestFile(require.resolve('./pie')); loadTestFile(require.resolve('./metric')); + loadTestFile(require.resolve('./xy')); + loadTestFile(require.resolve('./gauge')); + loadTestFile(require.resolve('./goal')); + loadTestFile(require.resolve('./table')); }); } 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 f81f5200e678a..caeeb5c935d85 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 @@ -11,8 +11,6 @@ import { FtrProviderContext } from '../../../../../ftr_provider_context'; export default function ({ getPageObjects, getService }: FtrProviderContext) { const { visualize, lens, timePicker } = getPageObjects(['visualize', 'lens', 'timePicker']); - const testSubjects = getService('testSubjects'); - describe('Metric', function describeIndexTests() { const isNewChartsLibraryEnabled = true; @@ -28,13 +26,11 @@ 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 to Lens', async () => { - const button = await testSubjects.find('visualizeEditInLensButton'); - await button.click(); + await visualize.navigateToLensFromAnotherVisulization(); await lens.waitForVisualization('mtrVis'); expect((await lens.getMetricVisualizationData()).length).to.be.equal(1); expect(await lens.getMetricVisualizationData()).to.eql([ diff --git a/x-pack/test/functional/apps/lens/group3/open_in_lens/agg_based/pie.ts b/x-pack/test/functional/apps/lens/group3/open_in_lens/agg_based/pie.ts index 1640a6a14631d..ed08f1ea5ae09 100644 --- a/x-pack/test/functional/apps/lens/group3/open_in_lens/agg_based/pie.ts +++ b/x-pack/test/functional/apps/lens/group3/open_in_lens/agg_based/pie.ts @@ -17,8 +17,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { 'header', ]); - const testSubjects = getService('testSubjects'); const pieChart = getService('pieChart'); + const testSubjects = getService('testSubjects'); describe('Pie', function describeIndexTests() { const isNewChartsLibraryEnabled = true; @@ -35,8 +35,24 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { }); it('should hide the "Edit Visualization in Lens" menu item if no split slices were defined', async () => { - const button = await testSubjects.exists('visualizeEditInLensButton'); - expect(button).to.eql(false); + expect(await visualize.hasNavigateToLensButton()).to.eql(false); + }); + + it('should hide the "Edit Visualization in Lens" menu item if more than 3 split slices were defined', async () => { + await visEditor.clickBucket('Split slices'); + await visEditor.selectAggregation('Terms'); + await visEditor.selectField('machine.os.raw'); + await visEditor.clickBucket('Split slices'); + await visEditor.selectAggregation('Terms', 'buckets', false, 1); + await visEditor.selectField('bytes', 'buckets', false, 1); + await visEditor.clickBucket('Split slices'); + await visEditor.selectAggregation('Terms', 'buckets', false, 2); + await visEditor.selectField('bytes', 'buckets', false, 2); + await visEditor.clickBucket('Split slices'); + await visEditor.selectAggregation('Terms', 'buckets', false, 3); + await visEditor.selectField('bytes', 'buckets', false, 3); + await header.waitUntilLoadingHasFinished(); + expect(await visualize.hasNavigateToLensButton()).to.eql(false); }); it('should show the "Edit Visualization in Lens" menu item', async () => { @@ -46,23 +62,85 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await header.waitUntilLoadingHasFinished(); await visEditor.clickGo(isNewChartsLibraryEnabled); - const button = await testSubjects.exists('visualizeEditInLensButton'); - expect(button).to.eql(true); + expect(await visualize.hasNavigateToLensButton()).to.eql(true); }); - it('should convert to Lens', async () => { - const expectedTableData = ['ios', 'osx', 'win 7', 'win 8', 'win xp']; + it('should convert aggregation with params', async () => { + await visEditor.clickMetricEditor(); + await visEditor.selectAggregation('Sum', 'metrics'); + await visEditor.selectField('machine.ram', 'metrics'); await visEditor.clickBucket('Split slices'); await visEditor.selectAggregation('Terms'); await visEditor.selectField('machine.os.raw'); + await visEditor.clickGo(); await header.waitUntilLoadingHasFinished(); + + await visualize.navigateToLensFromAnotherVisulization(); + await lens.waitForVisualization('partitionVisChart'); + + expect(await lens.getLayerCount()).to.be(1); + + const sliceByText = await lens.getDimensionTriggerText('lnsPie_sliceByDimensionPanel', 0); + const sizeByText = await lens.getDimensionTriggerText('lnsPie_sizeByDimensionPanel', 0); + + const dimensions = await testSubjects.findAll('lns-dimensionTrigger'); + expect(dimensions).to.have.length(2); + expect(sliceByText).to.be('machine.os.raw: Descending'); + expect(sizeByText).to.be('Sum of machine.ram'); + }); + + it('should convert terms to slice by', async () => { + const expectedTableData = ['ios', 'osx', 'win 7', 'win 8', 'win xp']; + await visEditor.clickBucket('Split slices'); + await visEditor.selectAggregation('Terms'); + await visEditor.selectField('machine.os.raw'); await visEditor.clickGo(isNewChartsLibraryEnabled); + await header.waitUntilLoadingHasFinished(); - const button = await testSubjects.find('visualizeEditInLensButton'); - await button.click(); + await visualize.navigateToLensFromAnotherVisulization(); await lens.waitForVisualization('partitionVisChart'); + const sliceByText = await lens.getDimensionTriggerText('lnsPie_sliceByDimensionPanel', 0); + const sizeByText = await lens.getDimensionTriggerText('lnsPie_sizeByDimensionPanel', 0); + + const dimensions = await testSubjects.findAll('lns-dimensionTrigger'); + expect(dimensions).to.have.length(2); + expect(sliceByText).to.be('machine.os.raw: Descending'); + expect(sizeByText).to.be('Count'); + await pieChart.expectPieChartLabels(expectedTableData, isNewChartsLibraryEnabled); }); + + it('should convert types correctly', async () => { + await visEditor.clickBucket('Split slices'); + await visEditor.selectAggregation('Terms'); + await visEditor.selectField('machine.os.raw'); + + await visEditor.clickGo(isNewChartsLibraryEnabled); + await header.waitUntilLoadingHasFinished(); + + await visualize.navigateToLensFromAnotherVisulization(); + await lens.waitForVisualization('partitionVisChart'); + + let chartSwitcher = await testSubjects.find('lnsChartSwitchPopover'); + let type = await chartSwitcher.getVisibleText(); + expect(type).to.be('Donut'); + + const goBackBtn = await testSubjects.find('lnsApp_goBackToAppButton'); + goBackBtn.click(); + + await visEditor.clickOptionsTab(); + const isDonutButton = await testSubjects.find('visTypePieIsDonut'); + await isDonutButton.click(); + await visEditor.clickGo(isNewChartsLibraryEnabled); + await header.waitUntilLoadingHasFinished(); + + await visualize.navigateToLensFromAnotherVisulization(); + await lens.waitForVisualization('partitionVisChart'); + + chartSwitcher = await testSubjects.find('lnsChartSwitchPopover'); + type = await chartSwitcher.getVisibleText(); + expect(type).to.be('Pie'); + }); }); } 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 new file mode 100644 index 0000000000000..09466bd7f1c70 --- /dev/null +++ b/x-pack/test/functional/apps/lens/group3/open_in_lens/agg_based/table.ts @@ -0,0 +1,190 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import expect from '@kbn/expect'; +import { FtrProviderContext } from '../../../../../ftr_provider_context'; + +export default function ({ getPageObjects, getService }: FtrProviderContext) { + const { visualize, visEditor, lens, timePicker, header } = getPageObjects([ + 'visualize', + 'lens', + 'visEditor', + 'timePicker', + 'header', + ]); + + const testSubjects = getService('testSubjects'); + + describe('Table', function describeIndexTests() { + const isNewChartsLibraryEnabled = true; + + before(async () => { + await visualize.initTests(isNewChartsLibraryEnabled); + }); + + beforeEach(async () => { + await visualize.navigateToNewAggBasedVisualization(); + await visualize.clickDataTable(); + await visualize.clickNewSearch(); + await timePicker.setDefaultAbsoluteRange(); + }); + + it('should not allow converting of unsupported aggregations', async () => { + await visEditor.clickMetricEditor(); + await visEditor.selectAggregation('Serial diff', 'metrics'); + await visEditor.clickBucket('Split rows'); + await visEditor.selectAggregation('Date histogram'); + await visEditor.clickGo(); + await header.waitUntilLoadingHasFinished(); + const button = await testSubjects.exists('visualizeEditInLensButton'); + expect(button).to.eql(false); + }); + + it('should show the "Edit Visualization in Lens" menu item', async () => { + const button = await testSubjects.exists('visualizeEditInLensButton'); + expect(button).to.eql(true); + }); + + 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 header.waitUntilLoadingHasFinished(); + + const button = await testSubjects.find('visualizeEditInLensButton'); + await button.click(); + await lens.waitForVisualization('lnsDataTable'); + + 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'); + }); + + it('should convert total function to summary row', async () => { + await visEditor.clickMetricEditor(); + await visEditor.selectAggregation('Average', 'metrics'); + await visEditor.selectField('machine.ram', 'metrics'); + await visEditor.clickOptionsTab(); + const showTotalSwitch = await testSubjects.find('showTotal'); + await showTotalSwitch.click(); + await visEditor.clickGo(); + await header.waitUntilLoadingHasFinished(); + + const button = await testSubjects.find('visualizeEditInLensButton'); + await button.click(); + await lens.waitForVisualization('lnsDataTable'); + + 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'); + + await lens.openDimensionEditor('lnsDatatable_metrics > lns-dimensionTrigger'); + const summaryRowFunction = await testSubjects.find('lnsDatatable_summaryrow_function'); + expect(await summaryRowFunction.getVisibleText()).to.be('Sum'); + }); + + it('should convert sibling pipeline aggregation', async () => { + await visEditor.clickMetricEditor(); + await visEditor.selectAggregation('Max Bucket', 'metrics'); + await visEditor.clickGo(); + await header.waitUntilLoadingHasFinished(); + + const button = await testSubjects.find('visualizeEditInLensButton'); + await button.click(); + await lens.waitForVisualization('lnsDataTable'); + + expect(await lens.getLayerCount()).to.be(1); + + const metricText = await lens.getDimensionTriggerText('lnsDatatable_metrics', 0); + const splitRowText = await lens.getDimensionTriggerText('lnsDatatable_rows', 0); + + const dimensions = await testSubjects.findAll('lns-dimensionTrigger'); + expect(dimensions).to.have.length(2); + expect(metricText).to.be('Overall Max of Count'); + expect(splitRowText).to.be('@timestamp'); + }); + + it('should convert parent pipeline aggregation', async () => { + await visEditor.clickMetricEditor(); + await visEditor.selectAggregation('Cumulative sum', 'metrics'); + await visEditor.clickBucket('Split rows'); + await visEditor.selectAggregation('Date histogram'); + await visEditor.clickGo(); + await header.waitUntilLoadingHasFinished(); + + const button = await testSubjects.find('visualizeEditInLensButton'); + await button.click(); + await lens.waitForVisualization('lnsDataTable'); + + expect(await lens.getLayerCount()).to.be(1); + + const metricText = await lens.getDimensionTriggerText('lnsDatatable_metrics', 0); + const splitRowText = await lens.getDimensionTriggerText('lnsDatatable_rows', 0); + + const dimensions = await testSubjects.findAll('lns-dimensionTrigger'); + expect(dimensions).to.have.length(2); + expect(metricText).to.be('Cumulative Sum of Count'); + expect(splitRowText).to.be('@timestamp'); + }); + + it('should convert split rows and split table to split table rows', async () => { + await visEditor.clickBucket('Split rows'); + await visEditor.selectAggregation('Date histogram'); + await visEditor.clickBucket('Split table'); + await visEditor.selectAggregation('Terms', 'buckets', false, 1); + await visEditor.selectField('bytes', 'buckets', false, 1); + await visEditor.clickGo(); + await header.waitUntilLoadingHasFinished(); + + const button = await testSubjects.find('visualizeEditInLensButton'); + await button.click(); + await lens.waitForVisualization('lnsDataTable'); + + expect(await lens.getLayerCount()).to.be(1); + + const metricText = await lens.getDimensionTriggerText('lnsDatatable_metrics', 0); + const splitRowText1 = await lens.getDimensionTriggerText('lnsDatatable_rows', 0); + const splitRowText2 = await lens.getDimensionTriggerText('lnsDatatable_rows', 1); + + const dimensions = await testSubjects.findAll('lns-dimensionTrigger'); + expect(dimensions).to.have.length(3); + expect(metricText).to.be('Count'); + expect(splitRowText1).to.be('@timestamp'); + expect(splitRowText2).to.be('bytes: Descending'); + }); + + it('should convert percentage column', async () => { + await visEditor.clickOptionsTab(); + await visEditor.setSelectByOptionText('datatableVisualizationPercentageCol', 'Count'); + await visEditor.clickGo(); + await header.waitUntilLoadingHasFinished(); + + const button = await testSubjects.find('visualizeEditInLensButton'); + await button.click(); + await lens.waitForVisualization('lnsDataTable'); + + expect(await lens.getLayerCount()).to.be(1); + + const metricText = await lens.getDimensionTriggerText('lnsDatatable_metrics', 0); + const percentageColumnText = await lens.getDimensionTriggerText('lnsDatatable_metrics', 1); + + await lens.openDimensionEditor('lnsDatatable_metrics > lns-dimensionTrigger', 0, 1); + const format = await testSubjects.find('indexPattern-dimension-format'); + expect(await format.getVisibleText()).to.be('Percent'); + + const dimensions = await testSubjects.findAll('lns-dimensionTrigger'); + expect(dimensions).to.have.length(2); + expect(metricText).to.be('Count'); + expect(percentageColumnText).to.be('Count percentages'); + }); + }); +} 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 new file mode 100644 index 0000000000000..161a3549e856c --- /dev/null +++ b/x-pack/test/functional/apps/lens/group3/open_in_lens/agg_based/xy.ts @@ -0,0 +1,73 @@ +/* + * 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 expect from '@kbn/expect'; +import { FtrProviderContext } from '../../../../../ftr_provider_context'; + +export default function ({ getPageObjects, getService }: FtrProviderContext) { + const { visualize, visEditor, lens, timePicker, header, visChart } = getPageObjects([ + 'visualize', + 'lens', + 'visEditor', + 'timePicker', + 'header', + 'visChart', + ]); + + const testSubjects = getService('testSubjects'); + const retry = getService('retry'); + + describe('XY', function describeIndexTests() { + const isNewChartsLibraryEnabled = true; + + before(async () => { + await visualize.initTests(isNewChartsLibraryEnabled); + }); + + beforeEach(async () => { + await visualize.navigateToNewAggBasedVisualization(); + await visualize.clickLineChart(); + await visualize.clickNewSearch(); + await timePicker.setDefaultAbsoluteRange(); + }); + + it('should show the "Edit Visualization in Lens" menu item', async () => { + const button = await testSubjects.exists('visualizeEditInLensButton'); + expect(button).to.eql(true); + }); + + it('should hide the "Edit Visualization in Lens" menu item if dot size aggregation is defined', async () => { + await visEditor.clickBucket('Dot size', 'metrics'); + 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); + }); + + it('should convert to Lens', async () => { + await visEditor.clickBucket('Split series'); + await visEditor.selectAggregation('Terms'); + await visEditor.selectField('machine.os.raw'); + await header.waitUntilLoadingHasFinished(); + await visEditor.clickGo(isNewChartsLibraryEnabled); + const expectedData = await visChart.getLegendEntriesXYCharts('xyVisChart'); + + const button = await testSubjects.find('visualizeEditInLensButton'); + await button.click(); + await lens.waitForVisualization('xyVisChart'); + const data = await lens.getCurrentChartDebugState('xyVisChart'); + await retry.try(async () => { + const dimensions = await testSubjects.findAll('lns-dimensionTrigger'); + expect(dimensions).to.have.length(2); + expect(await dimensions[0].getVisibleText()).to.be('Count'); + expect(await dimensions[1].getVisibleText()).to.be('machine.os.raw: Descending'); + }); + expect(data?.legend?.items.map((item) => item.name)).to.eql(expectedData); + }); + }); +} diff --git a/x-pack/test/functional/apps/lens/group3/open_in_lens/tsvb/dashboard.ts b/x-pack/test/functional/apps/lens/group3/open_in_lens/tsvb/dashboard.ts index bd74e109326bf..292aaa3a36f05 100644 --- a/x-pack/test/functional/apps/lens/group3/open_in_lens/tsvb/dashboard.ts +++ b/x-pack/test/functional/apps/lens/group3/open_in_lens/tsvb/dashboard.ts @@ -45,8 +45,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await panelActions.openContextMenu(); await panelActions.clickEdit(); - const button = await testSubjects.find('visualizeEditInLensButton'); - await button.click(); + await visualize.navigateToLensFromAnotherVisulization(); await lens.waitForVisualization('xyVisChart'); await retry.try(async () => { const dimensions = await testSubjects.findAll('lns-dimensionTrigger'); @@ -74,8 +73,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await panelActions.openContextMenu(); await panelActions.clickEdit(); - const button = await testSubjects.find('visualizeEditInLensButton'); - await button.click(); + await visualize.navigateToLensFromAnotherVisulization(); await lens.waitForVisualization('legacyMtrVis'); await retry.try(async () => { const dimensions = await testSubjects.findAll('lns-dimensionTrigger'); diff --git a/x-pack/test/functional/apps/lens/group3/open_in_lens/tsvb/gauge.ts b/x-pack/test/functional/apps/lens/group3/open_in_lens/tsvb/gauge.ts index bb2bc9a15ce9b..872ce7a58a22c 100644 --- a/x-pack/test/functional/apps/lens/group3/open_in_lens/tsvb/gauge.ts +++ b/x-pack/test/functional/apps/lens/group3/open_in_lens/tsvb/gauge.ts @@ -9,9 +9,16 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../../../../ftr_provider_context'; export default function ({ getPageObjects, getService }: FtrProviderContext) { - const { visualize, visualBuilder, lens } = getPageObjects(['visualBuilder', 'visualize', 'lens']); + const { visualize, visualBuilder, lens, header } = getPageObjects([ + 'visualBuilder', + 'visualize', + 'lens', + 'header', + ]); const testSubjects = getService('testSubjects'); + const retry = getService('retry'); + const find = getService('find'); describe('Gauge', function describeIndexTests() { before(async () => { @@ -28,17 +35,94 @@ 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 to Lens', async () => { - const button = await testSubjects.find('visualizeEditInLensButton'); - await button.click(); + await visualize.navigateToLensFromAnotherVisulization(); await lens.waitForVisualization('mtrVis'); const metricData = await lens.getMetricVisualizationData(); expect(metricData[0].title).to.eql('Count of records'); }); + + it('should convert metric with params', async () => { + await visualBuilder.selectAggType('Value Count'); + await visualBuilder.setFieldForAggregation('bytes'); + + await header.waitUntilLoadingHasFinished(); + + await visualize.navigateToLensFromAnotherVisulization(); + await lens.waitForVisualization('mtrVis'); + await retry.try(async () => { + const layers = await find.allByCssSelector(`[data-test-subj^="lns-layerPanel-"]`); + expect(layers).to.have.length(1); + + const dimensions = await testSubjects.findAll('lns-dimensionTrigger'); + expect(dimensions).to.have.length(2); + expect(await dimensions[0].getVisibleText()).to.be('Count of bytes'); + expect(await dimensions[1].getVisibleText()).to.be('overall_max(count(bytes))'); + }); + }); + + it('should not allow converting of unsupported metric', async () => { + await visualBuilder.selectAggType('Counter Rate'); + await visualBuilder.setFieldForAggregation('machine.ram'); + + await header.waitUntilLoadingHasFinished(); + + expect(await visualize.hasNavigateToLensButton()).to.be(false); + }); + + it('should not allow converting of not valid panel', async () => { + await visualBuilder.selectAggType('Value Count'); + await header.waitUntilLoadingHasFinished(); + expect(await visualize.hasNavigateToLensButton()).to.be(false); + }); + + it('should convert color ranges', async () => { + await visualBuilder.setMetricsGroupByTerms('extension.raw'); + + await visualBuilder.clickPanelOptions('gauge'); + + await visualBuilder.setColorRuleOperator('>= greater than or equal'); + await visualBuilder.setColorRuleValue(10); + await visualBuilder.setColorPickerValue('#54B399', 2); + + await visualBuilder.createColorRule(); + + await visualBuilder.setColorRuleOperator('>= greater than or equal'); + await visualBuilder.setColorRuleValue(100, 1); + await visualBuilder.setColorPickerValue('#54A000', 4); + + await header.waitUntilLoadingHasFinished(); + await visualize.navigateToLensFromAnotherVisulization(); + + await lens.waitForVisualization('mtrVis'); + await retry.try(async () => { + const closePalettePanels = await testSubjects.findAll( + 'lns-indexPattern-PalettePanelContainerBack' + ); + if (closePalettePanels.length) { + await lens.closePalettePanel(); + await lens.closeDimensionEditor(); + } + + const dimensions = await testSubjects.findAll('lns-dimensionTrigger'); + expect(dimensions).to.have.length(3); + + dimensions[0].click(); + + await lens.openPalettePanel('lnsMetric'); + const colorStops = await lens.getPaletteColorStops(); + + expect(colorStops).to.eql([ + { stop: '', color: 'rgba(104, 188, 0, 1)' }, + { stop: '10', color: 'rgba(84, 179, 153, 1)' }, + { stop: '100', color: 'rgba(84, 160, 0, 1)' }, + { stop: '', color: undefined }, + ]); + }); + }); }); } diff --git a/x-pack/test/functional/apps/lens/group3/open_in_lens/tsvb/index.ts b/x-pack/test/functional/apps/lens/group3/open_in_lens/tsvb/index.ts index 1093b0e154947..ea859195e6346 100644 --- a/x-pack/test/functional/apps/lens/group3/open_in_lens/tsvb/index.ts +++ b/x-pack/test/functional/apps/lens/group3/open_in_lens/tsvb/index.ts @@ -13,5 +13,6 @@ export default function ({ loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./gauge')); loadTestFile(require.resolve('./timeseries')); loadTestFile(require.resolve('./dashboard')); + loadTestFile(require.resolve('./top_n')); }); } diff --git a/x-pack/test/functional/apps/lens/group3/open_in_lens/tsvb/metric.ts b/x-pack/test/functional/apps/lens/group3/open_in_lens/tsvb/metric.ts index 273473b67a31e..794a2be110a32 100644 --- a/x-pack/test/functional/apps/lens/group3/open_in_lens/tsvb/metric.ts +++ b/x-pack/test/functional/apps/lens/group3/open_in_lens/tsvb/metric.ts @@ -9,9 +9,15 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../../../../ftr_provider_context'; export default function ({ getPageObjects, getService }: FtrProviderContext) { - const { visualize, visualBuilder, lens } = getPageObjects(['visualBuilder', 'visualize', 'lens']); + const { visualize, visualBuilder, lens, header } = getPageObjects([ + 'visualBuilder', + 'visualize', + 'lens', + 'header', + ]); const testSubjects = getService('testSubjects'); + const retry = getService('retry'); describe('Metric', function describeIndexTests() { before(async () => { @@ -28,17 +34,98 @@ 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 to Lens', async () => { - const button = await testSubjects.find('visualizeEditInLensButton'); - await button.click(); + await visualize.navigateToLensFromAnotherVisulization(); await lens.waitForVisualization('mtrVis'); const metricData = await lens.getMetricVisualizationData(); expect(metricData[0].title).to.eql('Count of records'); }); + + it('should draw static value', async () => { + await visualBuilder.selectAggType('Static Value'); + await visualBuilder.setStaticValue(10); + + await header.waitUntilLoadingHasFinished(); + + await visualize.navigateToLensFromAnotherVisulization(); + await lens.waitForVisualization('mtrVis'); + await retry.try(async () => { + 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('10'); + }); + }); + + it('should convert metric with params', async () => { + await visualBuilder.selectAggType('Value Count'); + await visualBuilder.setFieldForAggregation('bytes'); + + await header.waitUntilLoadingHasFinished(); + + await visualize.navigateToLensFromAnotherVisulization(); + await lens.waitForVisualization('mtrVis'); + await retry.try(async () => { + 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('Count of bytes'); + }); + }); + + it('should not allow converting of unsupported metric', async () => { + await visualBuilder.selectAggType('Counter Rate'); + await visualBuilder.setFieldForAggregation('machine.ram'); + + await header.waitUntilLoadingHasFinished(); + + expect(await visualize.hasNavigateToLensButton()).to.be(false); + }); + + it('should not allow converting of not valid panel', async () => { + await visualBuilder.selectAggType('Value Count'); + await header.waitUntilLoadingHasFinished(); + expect(await visualize.hasNavigateToLensButton()).to.be(false); + }); + + it('should convert color ranges', async () => { + await visualBuilder.clickPanelOptions('metric'); + await visualBuilder.setColorRuleOperator('>= greater than or equal'); + await visualBuilder.setColorRuleValue(10); + await visualBuilder.setColorPickerValue('#54B399'); + + await header.waitUntilLoadingHasFinished(); + await visualize.navigateToLensFromAnotherVisulization(); + + await lens.waitForVisualization('mtrVis'); + await retry.try(async () => { + const closePalettePanels = await testSubjects.findAll( + 'lns-indexPattern-PalettePanelContainerBack' + ); + if (closePalettePanels.length) { + await lens.closePalettePanel(); + await lens.closeDimensionEditor(); + } + + const dimensions = await testSubjects.findAll('lns-dimensionTrigger'); + expect(dimensions).to.have.length(1); + + dimensions[0].click(); + + await lens.openPalettePanel('lnsMetric'); + const colorStops = await lens.getPaletteColorStops(); + + expect(colorStops).to.eql([ + { stop: '10', color: 'rgba(84, 179, 153, 1)' }, + { stop: '', color: undefined }, + ]); + }); + }); }); } diff --git a/x-pack/test/functional/apps/lens/group3/open_in_lens/tsvb/timeseries.ts b/x-pack/test/functional/apps/lens/group3/open_in_lens/tsvb/timeseries.ts index 17e3a6b1bee8a..4c0c7e66b1ba3 100644 --- a/x-pack/test/functional/apps/lens/group3/open_in_lens/tsvb/timeseries.ts +++ b/x-pack/test/functional/apps/lens/group3/open_in_lens/tsvb/timeseries.ts @@ -27,20 +27,19 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await visualize.initTests(); }); - it('should show the "Edit Visualization in Lens" menu item for a count aggregation', async () => { + beforeEach(async () => { await visualize.navigateToNewVisualization(); await visualize.clickVisualBuilder(); await visualBuilder.checkVisualBuilderIsPresent(); await visualBuilder.resetPage(); - const isMenuItemVisible = await find.existsByCssSelector( - '[data-test-subj="visualizeEditInLensButton"]' - ); - expect(isMenuItemVisible).to.be(true); + }); + + it('should show the "Edit Visualization in Lens" menu item for a count aggregation', async () => { + expect(await visualize.hasNavigateToLensButton()).to.be(true); }); it('visualizes field to Lens and loads fields to the dimesion editor', async () => { - const button = await testSubjects.find('visualizeEditInLensButton'); - await button.click(); + await visualize.navigateToLensFromAnotherVisulization(); await lens.waitForVisualization('xyVisChart'); await retry.try(async () => { const dimensions = await testSubjects.findAll('lns-dimensionTrigger'); @@ -51,6 +50,9 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { }); it('navigates back to TSVB when the Back button is clicked', async () => { + await visualize.navigateToLensFromAnotherVisulization(); + await lens.waitForVisualization('xyVisChart'); + const goBackBtn = await testSubjects.find('lnsApp_goBackToAppButton'); goBackBtn.click(); await visualBuilder.checkVisualBuilderIsPresent(); @@ -63,25 +65,126 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { it('should preserve app filters in lens', async () => { await filterBar.addFilter('extension', 'is', 'css'); await header.waitUntilLoadingHasFinished(); - const button = await testSubjects.find('visualizeEditInLensButton'); - await button.click(); + await visualize.navigateToLensFromAnotherVisulization(); await lens.waitForVisualization('xyVisChart'); expect(await filterBar.hasFilter('extension', 'css')).to.be(true); }); it('should preserve query in lens', async () => { - const goBackBtn = await testSubjects.find('lnsApp_goBackToAppButton'); - goBackBtn.click(); - await visualBuilder.checkVisualBuilderIsPresent(); await queryBar.setQuery('machine.os : ios'); await queryBar.submitQuery(); await header.waitUntilLoadingHasFinished(); - const button = await testSubjects.find('visualizeEditInLensButton'); - await button.click(); + await visualize.navigateToLensFromAnotherVisulization(); await lens.waitForVisualization('xyVisChart'); expect(await queryBar.getQueryString()).to.equal('machine.os : ios'); }); + + it('should draw a reference line', async () => { + await visualBuilder.createNewAggSeries(); + await visualBuilder.selectAggType('Static Value'); + await visualBuilder.setStaticValue(10); + + await header.waitUntilLoadingHasFinished(); + + await visualize.navigateToLensFromAnotherVisulization(); + await lens.waitForVisualization('xyVisChart'); + await retry.try(async () => { + const layers = await find.allByCssSelector(`[data-test-subj^="lns-layerPanel-"]`); + + const referenceLineDimensions = await testSubjects.findAllDescendant( + 'lns-dimensionTrigger', + layers[0] + ); + expect(referenceLineDimensions).to.have.length(1); + expect(await referenceLineDimensions[0].getVisibleText()).to.be('Static value: 10'); + + const dimensions = await testSubjects.findAllDescendant('lns-dimensionTrigger', layers[1]); + expect(dimensions).to.have.length(2); + expect(await dimensions[0].getVisibleText()).to.be('@timestamp'); + expect(await dimensions[1].getVisibleText()).to.be('Count of records'); + }); + }); + + it('should convert metric with params', async () => { + await visualBuilder.selectAggType('Counter Rate'); + await visualBuilder.setFieldForAggregation('machine.ram'); + + await header.waitUntilLoadingHasFinished(); + + await visualize.navigateToLensFromAnotherVisulization(); + await lens.waitForVisualization('xyVisChart'); + await retry.try(async () => { + 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('@timestamp'); + expect(await dimensions[1].getVisibleText()).to.eql( + 'Counter rate of machine.ram per second' + ); + }); + }); + + it('should not allow converting of not valid panel', async () => { + await visualBuilder.selectAggType('Counter Rate'); + await header.waitUntilLoadingHasFinished(); + expect(await visualize.hasNavigateToLensButton()).to.be(false); + }); + + it('should not allow converting of unsupported aggregations', async () => { + await visualBuilder.selectAggType('Sum of Squares'); + await visualBuilder.setFieldForAggregation('machine.ram'); + + await header.waitUntilLoadingHasFinished(); + expect(await visualize.hasNavigateToLensButton()).to.be(false); + }); + + it('should convert parent pipeline aggregation with terms', async () => { + await visualBuilder.createNewAgg(); + + await visualBuilder.selectAggType('Cumulative Sum', 1); + await visualBuilder.setFieldForAggregation('Count', 1); + + await visualBuilder.setMetricsGroupByTerms('extension.raw'); + + await header.waitUntilLoadingHasFinished(); + await visualize.navigateToLensFromAnotherVisulization(); + + await lens.waitForVisualization('xyVisChart'); + await retry.try(async () => { + expect(await lens.getLayerCount()).to.be(1); + + const dimensions = await testSubjects.findAll('lns-dimensionTrigger'); + expect(dimensions).to.have.length(3); + expect(await dimensions[0].getVisibleText()).to.be('@timestamp'); + expect(await dimensions[1].getVisibleText()).to.eql('Cumulative sum of Records'); + expect(await dimensions[2].getVisibleText()).to.eql('Top 10 values of extension.raw'); + }); + }); + + it('should convert sibling pipeline aggregation with terms', async () => { + await visualBuilder.createNewAgg(); + + await visualBuilder.selectAggType('Overall Average', 1); + await visualBuilder.setFieldForAggregation('Count', 1); + + await visualBuilder.setMetricsGroupByTerms('extension.raw'); + + await header.waitUntilLoadingHasFinished(); + await visualize.navigateToLensFromAnotherVisulization(); + + await lens.waitForVisualization('xyVisChart'); + await retry.try(async () => { + expect(await lens.getLayerCount()).to.be(1); + + const dimensions = await testSubjects.findAll('lns-dimensionTrigger'); + expect(dimensions).to.have.length(3); + expect(await dimensions[0].getVisibleText()).to.be('@timestamp'); + expect(await dimensions[1].getVisibleText()).to.eql('overall_average(count())'); + expect(await dimensions[2].getVisibleText()).to.eql('Top 10 values of extension.raw'); + }); + }); }); } diff --git a/x-pack/test/functional/apps/lens/group3/open_in_lens/tsvb/top_n.ts b/x-pack/test/functional/apps/lens/group3/open_in_lens/tsvb/top_n.ts new file mode 100644 index 0000000000000..0631872fc9bd4 --- /dev/null +++ b/x-pack/test/functional/apps/lens/group3/open_in_lens/tsvb/top_n.ts @@ -0,0 +1,186 @@ +/* + * 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 expect from '@kbn/expect'; +import { FtrProviderContext } from '../../../../../ftr_provider_context'; + +export default function ({ getPageObjects, getService }: FtrProviderContext) { + const { visualize, visualBuilder, lens, header } = getPageObjects([ + 'visualBuilder', + 'visualize', + 'header', + 'lens', + ]); + + const testSubjects = getService('testSubjects'); + const retry = getService('retry'); + const filterBar = getService('filterBar'); + const queryBar = getService('queryBar'); + + describe('Top N', function describeIndexTests() { + before(async () => { + await visualize.initTests(); + }); + + beforeEach(async () => { + await visualize.navigateToNewVisualization(); + await visualize.clickVisualBuilder(); + await visualBuilder.checkVisualBuilderIsPresent(); + await visualBuilder.resetPage(); + await visualBuilder.clickTopN(); + await visualBuilder.checkTopNTabIsPresent(); + }); + + it('should not allow converting of not valid panel', async () => { + await visualBuilder.selectAggType('Max'); + await header.waitUntilLoadingHasFinished(); + expect(await visualize.hasNavigateToLensButton()).to.be(false); + }); + + it('should not allow converting of unsupported aggregations', async () => { + await visualBuilder.selectAggType('Sum of Squares'); + await visualBuilder.setFieldForAggregation('machine.ram'); + + await header.waitUntilLoadingHasFinished(); + expect(await visualize.hasNavigateToLensButton()).to.be(false); + }); + + it('should hide the "Edit Visualization in Lens" menu item for a sibling pipeline aggregations', async () => { + await visualBuilder.createNewAgg(); + + await visualBuilder.selectAggType('Overall Average', 1); + await visualBuilder.setFieldForAggregation('Count', 1); + await header.waitUntilLoadingHasFinished(); + expect(await visualize.hasNavigateToLensButton()).to.be(false); + }); + + it('should hide the "Edit Visualization in Lens" menu item for a parent pipeline aggregations', async () => { + await visualBuilder.clickPanelOptions('topN'); + await visualBuilder.setMetricsDataTimerangeMode('Last value'); + await visualBuilder.clickDataTab('topN'); + await visualBuilder.createNewAgg(); + + await visualBuilder.selectAggType('Cumulative Sum', 1); + await visualBuilder.setFieldForAggregation('Count', 1); + await header.waitUntilLoadingHasFinished(); + expect(await visualize.hasNavigateToLensButton()).to.be(false); + }); + + it('should show the "Edit Visualization in Lens" menu item for a count aggregation', async () => { + expect(await visualize.hasNavigateToLensButton()).to.be(true); + }); + + it('should convert to horizontal bar', async () => { + await visualBuilder.selectAggType('Max'); + await visualBuilder.setFieldForAggregation('memory', 0); + await visualize.navigateToLensFromAnotherVisulization(); + await lens.waitForVisualization('xyVisChart'); + const chartSwitcher = await testSubjects.find('lnsChartSwitchPopover'); + const type = await chartSwitcher.getVisibleText(); + expect(type).to.be('Bar horizontal'); + await retry.try(async () => { + const layerCount = await lens.getLayerCount(); + expect(layerCount).to.be(1); + + const yDimensionText = await lens.getDimensionTriggerText('lnsXY_yDimensionPanel', 0); + expect(yDimensionText).to.be('Maximum of memory'); + }); + }); + + it('should convert group by to vertical axis', async () => { + await visualBuilder.setMetricsGroupByTerms('extension.raw'); + await header.waitUntilLoadingHasFinished(); + await visualize.navigateToLensFromAnotherVisulization(); + await lens.waitForVisualization('xyVisChart'); + await retry.try(async () => { + const layerCount = await lens.getLayerCount(); + expect(layerCount).to.be(1); + + const xDimensionText = await lens.getDimensionTriggerText('lnsXY_xDimensionPanel', 0); + const yDimensionText = await lens.getDimensionTriggerText('lnsXY_yDimensionPanel', 0); + expect(xDimensionText).to.be('Top 10 values of extension.raw'); + expect(yDimensionText).to.be('Count of records'); + }); + }); + + it('should convert last value mode to reduced time range', async () => { + await visualBuilder.clickPanelOptions('topN'); + await visualBuilder.setMetricsDataTimerangeMode('Last value'); + await visualBuilder.setIntervalValue('1m'); + await visualBuilder.clickDataTab('topN'); + await header.waitUntilLoadingHasFinished(); + + await visualize.navigateToLensFromAnotherVisulization(); + await lens.waitForVisualization('xyVisChart'); + await lens.openDimensionEditor('lnsXY_yDimensionPanel > lns-dimensionTrigger'); + await testSubjects.click('indexPattern-advanced-accordion'); + const reducedTimeRange = await testSubjects.find('indexPattern-dimension-reducedTimeRange'); + expect(await reducedTimeRange.getVisibleText()).to.be('1 minute (1m)'); + await retry.try(async () => { + const layerCount = await lens.getLayerCount(); + expect(layerCount).to.be(1); + const yDimensionText = await lens.getDimensionTriggerText('lnsXY_yDimensionPanel', 0); + expect(yDimensionText).to.be('Count of records last 1m'); + }); + }); + + it('should convert static value to the separate layer with y dimension', async () => { + await visualBuilder.createNewAggSeries(); + await visualBuilder.selectAggType('Static Value', 1); + await visualBuilder.setStaticValue(10); + + await header.waitUntilLoadingHasFinished(); + + await visualize.navigateToLensFromAnotherVisulization(); + await lens.waitForVisualization('xyVisChart'); + await retry.try(async () => { + const layerCount = await lens.getLayerCount(); + expect(layerCount).to.be(2); + const yDimensionText1 = await lens.getDimensionTriggerText('lnsXY_yDimensionPanel', 0); + const yDimensionText2 = await lens.getDimensionTriggerText('lnsXY_yDimensionPanel', 1); + expect(yDimensionText1).to.be('Count of records'); + expect(yDimensionText2).to.be('10'); + }); + }); + + it('visualizes field to Lens and loads fields to the dimesion editor', async () => { + await visualize.navigateToLensFromAnotherVisulization(); + await lens.waitForVisualization('xyVisChart'); + await retry.try(async () => { + const yDimensionText = await lens.getDimensionTriggerText('lnsXY_yDimensionPanel', 0); + expect(yDimensionText).to.be('Count of records'); + }); + }); + + it('navigates back to TSVB when the Back button is clicked', async () => { + await visualize.navigateToLensFromAnotherVisulization(); + await lens.waitForVisualization('xyVisChart'); + const goBackBtn = await testSubjects.find('lnsApp_goBackToAppButton'); + goBackBtn.click(); + await visualBuilder.checkTopNTabIsPresent(); + }); + + it('should preserve app filters in lens', async () => { + await filterBar.addFilter('extension', 'is', 'css'); + await header.waitUntilLoadingHasFinished(); + await visualize.navigateToLensFromAnotherVisulization(); + await lens.waitForVisualization('xyVisChart'); + + expect(await filterBar.hasFilter('extension', 'css')).to.be(true); + }); + + it('should preserve query in lens', async () => { + await queryBar.setQuery('machine.os : ios'); + await queryBar.submitQuery(); + await header.waitUntilLoadingHasFinished(); + await visualize.navigateToLensFromAnotherVisulization(); + await lens.waitForVisualization('xyVisChart'); + + expect(await queryBar.getQueryString()).to.equal('machine.os : ios'); + }); + }); +} diff --git a/x-pack/test/functional/apps/management/feature_controls/management_security.ts b/x-pack/test/functional/apps/management/feature_controls/management_security.ts index c1e09d9f3eaab..87e6e4611a3fd 100644 --- a/x-pack/test/functional/apps/management/feature_controls/management_security.ts +++ b/x-pack/test/functional/apps/management/feature_controls/management_security.ts @@ -64,7 +64,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { expect(sections).to.have.length(2); expect(sections[0]).to.eql({ sectionId: 'insightsAndAlerting', - sectionLinks: ['triggersActions', 'cases', 'jobsListLink'], + sectionLinks: ['triggersActions', 'cases', 'triggersActionsConnectors', 'jobsListLink'], }); expect(sections[1]).to.eql({ sectionId: 'kibana', diff --git a/x-pack/test/functional/apps/ml/data_frame_analytics/classification_creation.ts b/x-pack/test/functional/apps/ml/data_frame_analytics/classification_creation.ts index ea95525062700..2ba4ac6f08350 100644 --- a/x-pack/test/functional/apps/ml/data_frame_analytics/classification_creation.ts +++ b/x-pack/test/functional/apps/ml/data_frame_analytics/classification_creation.ts @@ -13,8 +13,7 @@ export default function ({ getService }: FtrProviderContext) { const ml = getService('ml'); const editedDescription = 'Edited description'; - // FLAKY: https://github.com/elastic/kibana/issues/142102 - describe.skip('classification creation', function () { + describe('classification creation', function () { before(async () => { await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/ml/bm_classification'); await ml.testResources.createIndexPatternIfNeeded('ft_bank_marketing', '@timestamp'); @@ -93,8 +92,7 @@ export default function ({ getService }: FtrProviderContext) { }, ]; for (const testData of testDataList) { - // FLAKY: https://github.com/elastic/kibana/issues/142102 - describe.skip(`${testData.suiteTitle}`, function () { + describe(`${testData.suiteTitle}`, function () { after(async () => { await ml.api.deleteIndices(testData.destinationIndex); await ml.testResources.deleteIndexPatternByTitle(testData.destinationIndex); diff --git a/x-pack/test/functional/apps/ml/data_frame_analytics/cloning.ts b/x-pack/test/functional/apps/ml/data_frame_analytics/cloning.ts index a3314aabce725..3a33c95edba42 100644 --- a/x-pack/test/functional/apps/ml/data_frame_analytics/cloning.ts +++ b/x-pack/test/functional/apps/ml/data_frame_analytics/cloning.ts @@ -15,9 +15,7 @@ export default function ({ getService }: FtrProviderContext) { const esArchiver = getService('esArchiver'); const ml = getService('ml'); - // FLAKY: https://github.com/elastic/kibana/issues/142118 - // Failing: See https://github.com/elastic/kibana/issues/142118 - describe.skip('jobs cloning supported by UI form', function () { + describe('jobs cloning supported by UI form', function () { const testDataList: Array<{ suiteTitle: string; archive: string; @@ -137,8 +135,7 @@ export default function ({ getService }: FtrProviderContext) { }); for (const testData of testDataList) { - // FLAKY: https://github.com/elastic/kibana/issues/142118 - describe.skip(`${testData.suiteTitle}`, function () { + describe(`${testData.suiteTitle}`, function () { const cloneJobId = `${testData.job.id}_clone`; const cloneDestIndex = `${testData.job!.dest!.index}_clone`; diff --git a/x-pack/test/functional/apps/ml/data_frame_analytics/outlier_detection_creation.ts b/x-pack/test/functional/apps/ml/data_frame_analytics/outlier_detection_creation.ts index fb04cd793d9d8..947cd82cdd342 100644 --- a/x-pack/test/functional/apps/ml/data_frame_analytics/outlier_detection_creation.ts +++ b/x-pack/test/functional/apps/ml/data_frame_analytics/outlier_detection_creation.ts @@ -13,8 +13,7 @@ export default function ({ getService }: FtrProviderContext) { const ml = getService('ml'); const editedDescription = 'Edited description'; - // FLAKY: https://github.com/elastic/kibana/issues/142083 - describe.skip('outlier detection creation', function () { + describe('outlier detection creation', function () { before(async () => { await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/ml/ihp_outlier'); await ml.testResources.createIndexPatternIfNeeded('ft_ihp_outlier', '@timestamp'); @@ -109,8 +108,7 @@ export default function ({ getService }: FtrProviderContext) { ]; for (const testData of testDataList) { - // FLAKY: https://github.com/elastic/kibana/issues/142083 - describe.skip(`${testData.suiteTitle}`, function () { + describe(`${testData.suiteTitle}`, function () { after(async () => { await ml.api.deleteIndices(testData.destinationIndex); await ml.testResources.deleteIndexPatternByTitle(testData.destinationIndex); diff --git a/x-pack/test/functional/apps/ml/data_frame_analytics/regression_creation.ts b/x-pack/test/functional/apps/ml/data_frame_analytics/regression_creation.ts index 744b61a2a06ca..7a84c41aa4a66 100644 --- a/x-pack/test/functional/apps/ml/data_frame_analytics/regression_creation.ts +++ b/x-pack/test/functional/apps/ml/data_frame_analytics/regression_creation.ts @@ -13,8 +13,7 @@ export default function ({ getService }: FtrProviderContext) { const ml = getService('ml'); const editedDescription = 'Edited description'; - // FLAKY: https://github.com/elastic/kibana/issues/142095 - describe.skip('regression creation', function () { + describe('regression creation', function () { before(async () => { await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/ml/egs_regression'); await ml.testResources.createIndexPatternIfNeeded('ft_egs_regression', '@timestamp'); @@ -87,8 +86,7 @@ export default function ({ getService }: FtrProviderContext) { ]; for (const testData of testDataList) { - // FLAKY: https://github.com/elastic/kibana/issues/142095 - describe.skip(`${testData.suiteTitle}`, function () { + describe(`${testData.suiteTitle}`, function () { after(async () => { await ml.api.deleteIndices(testData.destinationIndex); await ml.testResources.deleteIndexPatternByTitle(testData.destinationIndex); diff --git a/x-pack/test/functional/apps/ml/data_frame_analytics/results_view_content.ts b/x-pack/test/functional/apps/ml/data_frame_analytics/results_view_content.ts index af023ea52d9b3..2bddf0a7d9512 100644 --- a/x-pack/test/functional/apps/ml/data_frame_analytics/results_view_content.ts +++ b/x-pack/test/functional/apps/ml/data_frame_analytics/results_view_content.ts @@ -14,8 +14,7 @@ export default function ({ getService }: FtrProviderContext) { const esArchiver = getService('esArchiver'); const ml = getService('ml'); - // Failing: See https://github.com/elastic/kibana/issues/142152 - describe.skip('results view content and total feature importance', function () { + describe('results view content and total feature importance', function () { const testDataList: Array<{ suiteTitle: string; archive: string; diff --git a/x-pack/test/functional/apps/remote_clusters/feature_controls/remote_clusters_security.ts b/x-pack/test/functional/apps/remote_clusters/feature_controls/remote_clusters_security.ts index 03e0c69a276f4..4e5f66e0c5bb6 100644 --- a/x-pack/test/functional/apps/remote_clusters/feature_controls/remote_clusters_security.ts +++ b/x-pack/test/functional/apps/remote_clusters/feature_controls/remote_clusters_security.ts @@ -15,8 +15,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { const appsMenu = getService('appsMenu'); const managementMenu = getService('managementMenu'); - // Failing: See https://github.com/elastic/kibana/issues/138129 - describe.skip('security', () => { + describe('security', () => { before(async () => { await kibanaServer.savedObjects.cleanStandardList(); await PageObjects.common.navigateToApp('home'); diff --git a/x-pack/test/functional/page_objects/gis_page.ts b/x-pack/test/functional/page_objects/gis_page.ts index be0d8c9aaf07f..3ad5b00279926 100644 --- a/x-pack/test/functional/page_objects/gis_page.ts +++ b/x-pack/test/functional/page_objects/gis_page.ts @@ -556,6 +556,7 @@ export class GisPageObject extends FtrService { this.log.debug(`Remove layer ${layerName}`); await this.openLayerPanel(layerName); await this.testSubjects.click(`mapRemoveLayerButton`); + await this.common.clickConfirmOnModal(); await this.waitForLayerDeleted(layerName); } diff --git a/x-pack/test/functional/page_objects/lens_page.ts b/x-pack/test/functional/page_objects/lens_page.ts index c37a9af94eb7e..883e21f1002a9 100644 --- a/x-pack/test/functional/page_objects/lens_page.ts +++ b/x-pack/test/functional/page_objects/lens_page.ts @@ -543,9 +543,12 @@ export function LensPageProvider({ getService, getPageObjects }: FtrProviderCont * @param dimension - the selector of the dimension panel to open * @param layerIndex - the index of the layer */ - async openDimensionEditor(dimension: string, layerIndex = 0) { + async openDimensionEditor(dimension: string, layerIndex = 0, dimensionIndex = 0) { await retry.try(async () => { - await testSubjects.click(`lns-layerPanel-${layerIndex} > ${dimension}`); + const dimensionEditor = ( + await testSubjects.findAll(`lns-layerPanel-${layerIndex} > ${dimension}`) + )[dimensionIndex]; + await dimensionEditor.click(); }); }, @@ -1586,5 +1589,21 @@ export function LensPageProvider({ getService, getPageObjects }: FtrProviderCont throw new Error(`Warning with text "${warningText}" not found`); } }, + + async getPaletteColorStops() { + const stops = await find.allByCssSelector( + `[data-test-subj^="lnsPalettePanel_dynamicColoring_range_value_"]` + ); + const colorsElements = await testSubjects.findAll('euiColorPickerAnchor'); + const colors = await Promise.all( + colorsElements.map((c) => c.getComputedStyle('background-color')) + ); + + return await Promise.all( + stops.map(async (stop, index) => { + return { stop: await stop.getAttribute('value'), color: colors[index] }; + }) + ); + }, }); } diff --git a/x-pack/test/functional/services/cases/common.ts b/x-pack/test/functional/services/cases/common.ts index 8a61358d04521..2eee4724d63a1 100644 --- a/x-pack/test/functional/services/cases/common.ts +++ b/x-pack/test/functional/services/cases/common.ts @@ -39,7 +39,7 @@ export function CasesCommonServiceProvider({ getService, getPageObject }: FtrPro this.openCaseSetStatusDropdown(); await testSubjects.click(`case-view-status-dropdown-${status}`); await header.waitUntilLoadingHasFinished(); - await testSubjects.existOrFail(`status-badge-${status}`); + await testSubjects.existOrFail(`case-status-badge-popover-button-${status}`); }, async openCaseSetStatusDropdown() { @@ -101,5 +101,14 @@ export function CasesCommonServiceProvider({ getService, getPageObject }: FtrPro await (await find.byClassName('euiSelectableListItem__content')).click(); await header.waitUntilLoadingHasFinished(); }, + + async selectAllRowsInAssigneesPopover() { + const rows = await find.allByCssSelector('.euiSelectableListItem__content'); + for (const row of rows) { + await row.click(); + } + + await header.waitUntilLoadingHasFinished(); + }, }; } diff --git a/x-pack/test/functional/services/cases/create.ts b/x-pack/test/functional/services/cases/create.ts index 872113f1a51be..0b4c62f572f23 100644 --- a/x-pack/test/functional/services/cases/create.ts +++ b/x-pack/test/functional/services/cases/create.ts @@ -16,6 +16,7 @@ export interface CreateCaseParams { tag?: string; severity?: CaseSeverity; owner?: string; + assignees?: []; } export function CasesCreateViewServiceProvider( @@ -55,38 +56,50 @@ export function CasesCreateViewServiceProvider( severity = CaseSeverity.LOW, owner, }: CreateCaseParams) { - await this.setCaseTitle(title); - - await this.setCaseTags(tag); - - // case description - const descriptionArea = await find.byCssSelector('textarea.euiMarkdownEditorTextArea'); - await descriptionArea.focus(); - await descriptionArea.type(description); + await this.setTitle(title); + await this.setDescription(description); + await this.setTags(tag); if (severity !== CaseSeverity.LOW) { - await common.clickAndValidate( - 'case-severity-selection', - `case-severity-selection-${severity}` - ); + await this.setSeverity(severity); } if (owner) { - await testSubjects.click(`${owner}RadioButton`); + await this.setSolution(owner); } - // save - await testSubjects.click('create-case-submit'); + await this.submitCase(); }, - async setCaseTitle(title: string) { + async setTitle(title: string) { await testSubjects.setValue('input', title); }, - async setCaseTags(tag: string) { + async setDescription(description: string) { + const descriptionArea = await find.byCssSelector('textarea.euiMarkdownEditorTextArea'); + await descriptionArea.focus(); + await descriptionArea.type(description); + }, + + async setTags(tag: string) { await comboBox.setCustom('caseTags', tag); }, + async setSolution(owner: string) { + await testSubjects.click(`${owner}RadioButton`); + }, + + async setSeverity(severity: CaseSeverity) { + await common.clickAndValidate( + 'case-severity-selection', + `case-severity-selection-${severity}` + ); + }, + + async submitCase() { + await testSubjects.click('create-case-submit'); + }, + async assertCreateCaseFlyoutVisible(expectVisible = true) { await retry.tryForTime(5000, async () => { if (expectVisible) { diff --git a/x-pack/test/functional/services/cases/single_case_view.ts b/x-pack/test/functional/services/cases/single_case_view.ts index aead59186b46d..bd9377ebd5abd 100644 --- a/x-pack/test/functional/services/cases/single_case_view.ts +++ b/x-pack/test/functional/services/cases/single_case_view.ts @@ -120,8 +120,12 @@ export function CasesSingleViewServiceProvider({ getService, getPageObject }: Ft }, async closeAssigneesPopover() { - await testSubjects.click('case-refresh'); - await header.waitUntilLoadingHasFinished(); + await retry.try(async () => { + // Click somewhere outside the popover + await testSubjects.click('header-page-title'); + await header.waitUntilLoadingHasFinished(); + await testSubjects.missingOrFail('euiSelectableList'); + }); }, }; } diff --git a/x-pack/test/functional_with_es_ssl/apps/cases/attachment_framework.ts b/x-pack/test/functional_with_es_ssl/apps/cases/attachment_framework.ts index f9bcd5946d400..2d16926b47660 100644 --- a/x-pack/test/functional_with_es_ssl/apps/cases/attachment_framework.ts +++ b/x-pack/test/functional_with_es_ssl/apps/cases/attachment_framework.ts @@ -145,7 +145,7 @@ export default ({ getPageObject, getService }: FtrProviderContext) => { query: { query: '', language: 'kuery' }, filters: [], datasourceStates: { - indexpattern: { + formBased: { layers: { '85863a23-73a0-4e11-9774-70f77b9a5898': { columns: { diff --git a/x-pack/test/functional_with_es_ssl/apps/cases/create_case_form.ts b/x-pack/test/functional_with_es_ssl/apps/cases/create_case_form.ts index 42ed68a9f36da..e601ce9381ed6 100644 --- a/x-pack/test/functional_with_es_ssl/apps/cases/create_case_form.ts +++ b/x-pack/test/functional_with_es_ssl/apps/cases/create_case_form.ts @@ -9,15 +9,22 @@ import expect from '@kbn/expect'; import uuid from 'uuid'; import { CaseSeverity } from '@kbn/cases-plugin/common/api'; import { FtrProviderContext } from '../../ftr_provider_context'; +import { + createUsersAndRoles, + deleteUsersAndRoles, +} from '../../../cases_api_integration/common/lib/authentication'; +import { users, roles, casesAllUser, casesAllUser2 } from './common'; -export default ({ getService }: FtrProviderContext) => { +export default ({ getService, getPageObject }: FtrProviderContext) => { describe('Create case', function () { const find = getService('find'); const cases = getService('cases'); const testSubjects = getService('testSubjects'); const config = getService('config'); + const comboBox = getService('comboBox'); + const header = getPageObject('header'); - before(async () => { + beforeEach(async () => { await cases.navigation.navigateToApp(); }); @@ -54,5 +61,33 @@ export default ({ getService }: FtrProviderContext) => { const button = await find.byCssSelector('[data-test-subj*="case-callout"] button'); expect(await button.getVisibleText()).equal('Add connector'); }); + + describe('Assignees', function () { + before(async () => { + await createUsersAndRoles(getService, users, roles); + await cases.api.activateUserProfiles([casesAllUser, casesAllUser2]); + }); + + after(async () => { + await deleteUsersAndRoles(getService, users, roles); + }); + + it('creates a case with assignees', async () => { + const caseTitle = 'test-' + uuid.v4(); + await cases.create.openCreateCasePage(); + + await cases.create.setTitle(caseTitle); + await comboBox.set('createCaseAssigneesComboBox', 'cases_all_user'); + await comboBox.set('createCaseAssigneesComboBox', 'cases_all_user2'); + await cases.create.setDescription('my description'); + + await cases.create.submitCase(); + + await header.waitUntilLoadingHasFinished(); + await testSubjects.existOrFail('case-view-title'); + await testSubjects.existOrFail('user-profile-assigned-user-group-cases_all_user'); + await testSubjects.existOrFail('user-profile-assigned-user-group-cases_all_user2'); + }); + }); }); }; diff --git a/x-pack/test/functional_with_es_ssl/apps/cases/list_view.ts b/x-pack/test/functional_with_es_ssl/apps/cases/list_view.ts index b212b48dc2e9d..f01bd4d95f13e 100644 --- a/x-pack/test/functional_with_es_ssl/apps/cases/list_view.ts +++ b/x-pack/test/functional_with_es_ssl/apps/cases/list_view.ts @@ -91,7 +91,7 @@ export default ({ getPageObject, getService }: FtrProviderContext) => { it('change the status of cases to in-progress correctly', async () => { await cases.casesTable.selectAndChangeStatusOfAllCases(CaseStatuses['in-progress']); await cases.casesTable.waitForTableToFinishLoading(); - await testSubjects.missingOrFail('status-badge-open'); + await testSubjects.missingOrFail('case-status-badge-open'); }); }); @@ -223,19 +223,23 @@ export default ({ getPageObject, getService }: FtrProviderContext) => { it('filters cases by status', async () => { await cases.casesTable.changeStatus(CaseStatuses['in-progress'], 0); - await testSubjects.existOrFail(`status-badge-${CaseStatuses['in-progress']}`); + await testSubjects.existOrFail(`case-status-badge-${CaseStatuses['in-progress']}`); await cases.casesTable.filterByStatus(CaseStatuses['in-progress']); await cases.casesTable.validateCasesTableHasNthRows(1); }); - it('filters cases by the first cases all user assignee', async () => { - await cases.casesTable.filterByAssignee('all'); - await cases.casesTable.validateCasesTableHasNthRows(1); - }); + describe('assignees filtering', () => { + it('filters cases by the first cases all user assignee', async () => { + await cases.casesTable.filterByAssignee('all'); + await cases.casesTable.validateCasesTableHasNthRows(1); + await testSubjects.exists('case-user-profile-avatar-cases_all_user'); + }); - it('filters cases by the casesAllUser2 assignee', async () => { - await cases.casesTable.filterByAssignee('2'); - await cases.casesTable.validateCasesTableHasNthRows(1); + it('filters cases by the casesAllUser2 assignee', async () => { + await cases.casesTable.filterByAssignee('2'); + await cases.casesTable.validateCasesTableHasNthRows(1); + await testSubjects.exists('case-user-profile-avatar-cases_all_user2'); + }); }); }); @@ -322,17 +326,17 @@ export default ({ getPageObject, getService }: FtrProviderContext) => { it('to in progress', async () => { await cases.casesTable.changeStatus(CaseStatuses['in-progress'], 0); - await testSubjects.existOrFail(`status-badge-${CaseStatuses['in-progress']}`); + await testSubjects.existOrFail(`case-status-badge-${CaseStatuses['in-progress']}`); }); it('to closed', async () => { await cases.casesTable.changeStatus(CaseStatuses.closed, 0); - await testSubjects.existOrFail(`status-badge-${CaseStatuses.closed}`); + await testSubjects.existOrFail(`case-status-badge-${CaseStatuses.closed}`); }); it('to open', async () => { await cases.casesTable.changeStatus(CaseStatuses.open, 0); - await testSubjects.existOrFail(`status-badge-${CaseStatuses.open}`); + await testSubjects.existOrFail(`case-status-badge-${CaseStatuses.open}`); }); }); diff --git a/x-pack/test/functional_with_es_ssl/apps/cases/view_case.ts b/x-pack/test/functional_with_es_ssl/apps/cases/view_case.ts index 18adfa55a3d1b..5a3862d5ac781 100644 --- a/x-pack/test/functional_with_es_ssl/apps/cases/view_case.ts +++ b/x-pack/test/functional_with_es_ssl/apps/cases/view_case.ts @@ -86,79 +86,100 @@ export default ({ getPageObject, getService }: FtrProviderContext) => { await find.byCssSelector('[data-test-subj*="tags-delete-action"]'); }); - it('changes a case status to in-progress via dropdown menu', async () => { - await cases.common.changeCaseStatusViaDropdownAndVerify(CaseStatuses['in-progress']); - // validate user action - await find.byCssSelector( - '[data-test-subj*="status-update-action"] [data-test-subj="status-badge-in-progress"]' - ); - // validates dropdown tag - await testSubjects.existOrFail('case-view-status-dropdown > status-badge-in-progress'); - }); + describe('status', () => { + it('changes a case status to in-progress via dropdown menu', async () => { + await cases.common.changeCaseStatusViaDropdownAndVerify(CaseStatuses['in-progress']); + // validate user action + await find.byCssSelector( + '[data-test-subj*="status-update-action"] [data-test-subj="case-status-badge-in-progress"]' + ); + // validates dropdown tag + await testSubjects.existOrFail( + 'case-view-status-dropdown > case-status-badge-popover-button-in-progress' + ); + }); - it('changes a case status to closed via dropdown-menu', async () => { - await cases.common.changeCaseStatusViaDropdownAndVerify(CaseStatuses.closed); + it('changes a case status to closed via dropdown-menu', async () => { + await cases.common.changeCaseStatusViaDropdownAndVerify(CaseStatuses.closed); - // validate user action - await find.byCssSelector( - '[data-test-subj*="status-update-action"] [data-test-subj="status-badge-closed"]' - ); - // validates dropdown tag - await testSubjects.existOrFail('case-view-status-dropdown > status-badge-closed'); - }); + // validate user action + await find.byCssSelector( + '[data-test-subj*="status-update-action"] [data-test-subj="case-status-badge-closed"]' + ); + // validates dropdown tag + await testSubjects.existOrFail( + 'case-view-status-dropdown > case-status-badge-popover-button-closed' + ); + }); - it("reopens a case from the 'reopen case' button", async () => { - await cases.common.changeCaseStatusViaDropdownAndVerify(CaseStatuses.closed); - await header.waitUntilLoadingHasFinished(); - await testSubjects.click('case-view-status-action-button'); - await header.waitUntilLoadingHasFinished(); + it("reopens a case from the 'reopen case' button", async () => { + await cases.common.changeCaseStatusViaDropdownAndVerify(CaseStatuses.closed); + await header.waitUntilLoadingHasFinished(); + await testSubjects.click('case-view-status-action-button'); + await header.waitUntilLoadingHasFinished(); + + await testSubjects.existOrFail( + 'header-page-supplements > case-status-badge-popover-button-open', + { + timeout: 5000, + } + ); - await testSubjects.existOrFail('header-page-supplements > status-badge-open', { - timeout: 5000, + // validate user action + await find.byCssSelector( + '[data-test-subj*="status-update-action"] [data-test-subj="case-status-badge-open"]' + ); + // validates dropdown tag + await testSubjects.existOrFail( + 'case-view-status-dropdown > case-status-badge-popover-button-open' + ); }); - // validate user action - await find.byCssSelector( - '[data-test-subj*="status-update-action"] [data-test-subj="status-badge-open"]' - ); - // validates dropdown tag - await testSubjects.existOrFail('case-view-status-dropdown > status-badge-open'); - }); + it("marks in progress a case from the 'mark in progress' button", async () => { + await cases.common.changeCaseStatusViaDropdownAndVerify(CaseStatuses.open); + await header.waitUntilLoadingHasFinished(); + await testSubjects.click('case-view-status-action-button'); + await header.waitUntilLoadingHasFinished(); - it("marks in progress a case from the 'mark in progress' button", async () => { - await cases.common.changeCaseStatusViaDropdownAndVerify(CaseStatuses.open); - await header.waitUntilLoadingHasFinished(); - await testSubjects.click('case-view-status-action-button'); - await header.waitUntilLoadingHasFinished(); + await testSubjects.existOrFail( + 'header-page-supplements > case-status-badge-popover-button-in-progress', + { + timeout: 5000, + } + ); - await testSubjects.existOrFail('header-page-supplements > status-badge-in-progress', { - timeout: 5000, + // validate user action + await find.byCssSelector( + '[data-test-subj*="status-update-action"] [data-test-subj="case-status-badge-in-progress"]' + ); + // validates dropdown tag + await testSubjects.existOrFail( + 'case-view-status-dropdown > case-status-badge-popover-button-in-progress' + ); }); - // validate user action - await find.byCssSelector( - '[data-test-subj*="status-update-action"] [data-test-subj="status-badge-in-progress"]' - ); - // validates dropdown tag - await testSubjects.existOrFail('case-view-status-dropdown > status-badge-in-progress'); - }); + it("closes a case from the 'close case' button", async () => { + await cases.common.changeCaseStatusViaDropdownAndVerify(CaseStatuses['in-progress']); + await header.waitUntilLoadingHasFinished(); + await testSubjects.click('case-view-status-action-button'); + await header.waitUntilLoadingHasFinished(); - it("closes a case from the 'close case' button", async () => { - await cases.common.changeCaseStatusViaDropdownAndVerify(CaseStatuses['in-progress']); - await header.waitUntilLoadingHasFinished(); - await testSubjects.click('case-view-status-action-button'); - await header.waitUntilLoadingHasFinished(); + await testSubjects.existOrFail( + 'header-page-supplements > case-status-badge-popover-button-closed', + { + timeout: 5000, + } + ); - await testSubjects.existOrFail('header-page-supplements > status-badge-closed', { - timeout: 5000, + // validate user action + await find.byCssSelector( + '[data-test-subj*="status-update-action"] [data-test-subj="case-status-badge-closed"]' + ); + // validates dropdown tag + await testSubjects.existOrFail( + 'case-view-status-dropdown >case-status-badge-popover-button-closed' + ); }); - - // validate user action - await find.byCssSelector( - '[data-test-subj*="status-update-action"] [data-test-subj="status-badge-closed"]' - ); - // validates dropdown tag - await testSubjects.existOrFail('case-view-status-dropdown > status-badge-closed'); }); }); @@ -256,27 +277,38 @@ export default ({ getPageObject, getService }: FtrProviderContext) => { }); describe('logs in with default user', () => { - createOneCaseBeforeDeleteAllAfter(getPageObject, getService); + beforeEach(async () => { + await createAndNavigateToCase(getPageObject, getService); + }); afterEach(async () => { - await cases.singleCase.closeAssigneesPopover(); + await cases.api.deleteAllCases(); }); it('shows the assign users popover when clicked', async () => { await testSubjects.missingOrFail('euiSelectableList'); - await cases.singleCase.openAssigneesPopover(); + await cases.singleCase.closeAssigneesPopover(); }); it('assigns a user from the popover', async () => { await cases.singleCase.openAssigneesPopover(); await cases.common.setSearchTextInAssigneesPopover('case'); await cases.common.selectFirstRowInAssigneesPopover(); + await cases.singleCase.closeAssigneesPopover(); + await header.waitUntilLoadingHasFinished(); + await testSubjects.existOrFail('user-profile-assigned-user-group-cases_all_user'); + }); + + it('assigns multiple users', async () => { + await cases.singleCase.openAssigneesPopover(); + await cases.common.setSearchTextInAssigneesPopover('case'); + await cases.common.selectAllRowsInAssigneesPopover(); - // navigate out of the modal await cases.singleCase.closeAssigneesPopover(); await header.waitUntilLoadingHasFinished(); await testSubjects.existOrFail('user-profile-assigned-user-group-cases_all_user'); + await testSubjects.existOrFail('user-profile-assigned-user-group-cases_all_user2'); }); }); diff --git a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alert_create_flyout.ts b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alert_create_flyout.ts index 46532fa570f46..a83d8de0a2cb8 100644 --- a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alert_create_flyout.ts +++ b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alert_create_flyout.ts @@ -43,6 +43,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await pageObjects.triggersActionsUI.clickCreateAlertButton(); await testSubjects.setValue('ruleNameInput', alertName); await testSubjects.click(`.es-query-SelectOption`); + await testSubjects.click('queryFormType_esQuery'); await testSubjects.click('selectIndexExpression'); const indexComboBox = await find.byCssSelector('#indexSelectSearchBox'); await indexComboBox.click(); @@ -112,8 +113,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await testSubjects.missingOrFail('confirmRuleCloseModal'); } - // Failing: See https://github.com/elastic/kibana/issues/126873 - describe.skip('create alert', function () { + describe('create alert', function () { before(async () => { await pageObjects.common.navigateToApp('triggersActions'); await testSubjects.click('rulesTab'); @@ -122,7 +122,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { afterEach(async () => { // Reset the Rules tab without reloading the entire page // This is safer than trying to close the alert flyout, which may or may not be open at the end of a test - await testSubjects.click('connectorsTab'); + await testSubjects.click('logsTab'); await testSubjects.click('rulesTab'); }); @@ -134,6 +134,13 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await testSubjects.click('onThrottleInterval'); await testSubjects.setValue('throttleInput', '10'); + // filterKuery validation + await testSubjects.setValue('filterKuery', 'group:'); + const filterKueryInput = await testSubjects.find('filterKuery'); + expect(await filterKueryInput.elementHasClass('euiFieldSearch-isInvalid')).to.eql(true); + await testSubjects.setValue('filterKuery', 'group: group-0'); + expect(await filterKueryInput.elementHasClass('euiFieldSearch-isInvalid')).to.eql(false); + await testSubjects.click('.slack-alerting-ActionTypeSelectOption'); await testSubjects.click('addNewActionConnectorButton-.slack'); const slackConnectorName = generateUniqueKey(); @@ -279,34 +286,42 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await discardNewRuleCreation(); }); - it('should successfully test valid es_query alert', async () => { + it('should show error when es_query is invalid', async () => { const alertName = generateUniqueKey(); await defineEsQueryAlert(alertName); - // Valid query - await testSubjects.setValue('queryJsonEditor', '{"query":{"match_all":{}}}', { + await testSubjects.setValue('queryJsonEditor', '', { + clearWithKeyboard: true, + }); + const queryJsonEditor = await testSubjects.find('queryJsonEditor'); + await queryJsonEditor.clearValue(); + // Invalid query + await testSubjects.setValue('queryJsonEditor', '{"query":{"foo":""}}', { clearWithKeyboard: true, }); await testSubjects.click('testQuery'); - await testSubjects.existOrFail('testQuerySuccess'); - await testSubjects.missingOrFail('testQueryError'); - + await testSubjects.missingOrFail('testQuerySuccess'); + await testSubjects.existOrFail('testQueryError'); + await testSubjects.setValue('queryJsonEditor', ''); await discardNewRuleCreation(); }); - it('should show error when es_query is invalid', async () => { + it('should successfully test valid es_query alert', async () => { const alertName = generateUniqueKey(); await defineEsQueryAlert(alertName); + await testSubjects.setValue('queryJsonEditor', '', { + clearWithKeyboard: true, + }); const queryJsonEditor = await testSubjects.find('queryJsonEditor'); await queryJsonEditor.clearValue(); - // Invalid query - await testSubjects.setValue('queryJsonEditor', JSON.stringify({ query: { foo: {} } }), { + // Valid query + await testSubjects.setValue('queryJsonEditor', '{"query":{"match_all":{}}}', { clearWithKeyboard: true, }); await testSubjects.click('testQuery'); - await testSubjects.missingOrFail('testQuerySuccess'); - await testSubjects.existOrFail('testQueryError'); + await testSubjects.existOrFail('testQuerySuccess'); + await testSubjects.missingOrFail('testQueryError'); await discardNewRuleCreation(); }); diff --git a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alerts_list.ts b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alerts_list.ts index 7262ff280faea..c1c5e391686a3 100644 --- a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alerts_list.ts +++ b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alerts_list.ts @@ -30,8 +30,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await testSubjects.click('rulesTab'); } - // Failing: See https://github.com/elastic/kibana/issues/141093 - describe.skip('rules list', function () { + describe('rules list', function () { const assertRulesLength = async (length: number) => { return await retry.try(async () => { const rules = await pageObjects.triggersActionsUI.getAlertsList(); @@ -198,6 +197,10 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await testSubjects.click('collapsedItemActions'); + await retry.waitForWithTimeout('disable button to show up', 30000, async () => { + return await testSubjects.isDisplayed('disableButton'); + }); + await testSubjects.click('disableButton'); await refreshAlertsList(); diff --git a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/connectors.ts b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/connectors.ts index cabbadb43ac57..c0e9a145fe47e 100644 --- a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/connectors.ts +++ b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/connectors.ts @@ -18,6 +18,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const retry = getService('retry'); const supertest = getService('supertest'); const objectRemover = new ObjectRemover(supertest); + const browser = getService('browser'); describe('Connectors', function () { before(async () => { @@ -26,8 +27,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { .set('kbn-xsrf', 'foo') .send(getTestActionData()) .expect(200); - await pageObjects.common.navigateToApp('triggersActions'); - await testSubjects.click('connectorsTab'); + await pageObjects.common.navigateToApp('triggersActionsConnectors'); objectRemover.add(createdAction.id, 'action', 'actions'); }); @@ -75,6 +75,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const updatedConnectorName = `${connectorName}updated`; const createdAction = await createConnector(connectorName); objectRemover.add(createdAction.id, 'action', 'actions'); + await browser.refresh(); await pageObjects.triggersActionsUI.searchConnectors(connectorName); @@ -112,6 +113,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const indexName = generateUniqueKey(); const createdAction = await createIndexConnector(connectorName, indexName); objectRemover.add(createdAction.id, 'action', 'actions'); + await browser.refresh(); await pageObjects.triggersActionsUI.searchConnectors(connectorName); @@ -141,6 +143,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const indexName = generateUniqueKey(); const createdAction = await createIndexConnector(connectorName, indexName); objectRemover.add(createdAction.id, 'action', 'actions'); + await browser.refresh(); await pageObjects.triggersActionsUI.searchConnectors(connectorName); @@ -168,6 +171,8 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const connectorName = generateUniqueKey(); const createdAction = await createConnector(connectorName); objectRemover.add(createdAction.id, 'action', 'actions'); + await browser.refresh(); + await pageObjects.triggersActionsUI.searchConnectors(connectorName); const searchResultsBeforeEdit = await pageObjects.triggersActionsUI.getConnectorsList(); @@ -195,6 +200,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await createConnector(connectorName); const createdAction = await createConnector(generateUniqueKey()); objectRemover.add(createdAction.id, 'action', 'actions'); + await browser.refresh(); await pageObjects.triggersActionsUI.searchConnectors(connectorName); @@ -220,6 +226,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await createConnector(connectorName); const createdAction = await createConnector(generateUniqueKey()); objectRemover.add(createdAction.id, 'action', 'actions'); + await browser.refresh(); await pageObjects.triggersActionsUI.searchConnectors(connectorName); @@ -285,7 +292,6 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { connector_type_id: '.slack', }) .expect(200); - await testSubjects.click('connectorsTab'); return createdAction; } @@ -303,7 +309,6 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { secrets: {}, }) .expect(200); - await testSubjects.click('connectorsTab'); return createdAction; } diff --git a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/details.ts b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/details.ts index 7af323fdee7c1..6c5de895ed1fd 100644 --- a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/details.ts +++ b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/details.ts @@ -437,7 +437,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await testSubjects.existOrFail('rulesList'); // delete connector - await pageObjects.triggersActionsUI.changeTabs('connectorsTab'); + await pageObjects.common.navigateToApp('triggersActionsConnectors'); await pageObjects.triggersActionsUI.searchConnectors(connector.name); await testSubjects.click('deleteConnector'); await testSubjects.existOrFail('deleteIdsConfirmation'); @@ -447,8 +447,11 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const toastTitle = await pageObjects.common.closeToast(); expect(toastTitle).to.eql('Deleted 1 connector'); + // Wait to ensure the table is finished loading + await pageObjects.triggersActionsUI.tableFinishedLoading(); + // click on first alert - await pageObjects.triggersActionsUI.changeTabs('rulesTab'); + await pageObjects.common.navigateToApp('triggersActions'); await pageObjects.triggersActionsUI.clickOnAlertInAlertsList(rule.name); const editButton = await testSubjects.find('openEditRuleFlyoutButton'); @@ -501,7 +504,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await testSubjects.existOrFail('rulesList'); // delete connector - await pageObjects.triggersActionsUI.changeTabs('connectorsTab'); + await pageObjects.common.navigateToApp('triggersActionsConnectors'); await pageObjects.triggersActionsUI.searchConnectors(connector.name); await testSubjects.click('deleteConnector'); await testSubjects.existOrFail('deleteIdsConfirmation'); @@ -511,8 +514,11 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const toastTitle = await pageObjects.common.closeToast(); expect(toastTitle).to.eql('Deleted 1 connector'); + // Wait to ensure the table is finished loading + await pageObjects.triggersActionsUI.tableFinishedLoading(); + // click on first rule - await pageObjects.triggersActionsUI.changeTabs('rulesTab'); + await pageObjects.common.navigateToApp('triggersActions'); await pageObjects.triggersActionsUI.clickOnAlertInAlertsList(alert.name); const editButton = await testSubjects.find('openEditRuleFlyoutButton'); @@ -553,7 +559,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { // verify content await testSubjects.existOrFail('rulesList'); - await pageObjects.triggersActionsUI.changeTabs('connectorsTab'); + await pageObjects.common.navigateToApp('triggersActionsConnectors'); await pageObjects.triggersActionsUI.searchConnectors('new connector'); await testSubjects.click('deleteConnector'); await testSubjects.existOrFail('deleteIdsConfirmation'); diff --git a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/home_page.ts b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/home_page.ts index 4769f01e8d4f0..77ece6d043a59 100644 --- a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/home_page.ts +++ b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/home_page.ts @@ -31,7 +31,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { it('Loads the Alerts page', async () => { await pageObjects.common.navigateToApp('triggersActions'); const headingText = await pageObjects.triggersActionsUI.getSectionHeadingText(); - expect(headingText).to.be('Rules and Connectors'); + expect(headingText).to.be('Rules'); }); }); @@ -45,8 +45,8 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { it('Loads the Alerts page but with error', async () => { await pageObjects.common.navigateToApp('triggersActions'); - const headingText = await pageObjects.triggersActionsUI.getRulesListTitle(); - expect(headingText).to.be('No permissions to create rules'); + const exists = await testSubjects.exists('noPermissionPrompt'); + expect(exists).to.be(true); }); }); @@ -60,26 +60,10 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }); it('Loads the Alerts page', async () => { - await log.debug('Checking for section heading to say Rules and Connectors.'); + await log.debug('Checking for section heading to say Rules.'); const headingText = await pageObjects.triggersActionsUI.getSectionHeadingText(); - expect(headingText).to.be('Rules and Connectors'); - }); - - describe('Connectors tab', () => { - it('renders the connectors tab', async () => { - // Navigate to the connectors tab - await pageObjects.triggersActionsUI.changeTabs('connectorsTab'); - - await pageObjects.header.waitUntilLoadingHasFinished(); - - // Verify url - const url = await browser.getCurrentUrl(); - expect(url).to.contain(`/connectors`); - - // Verify content - await testSubjects.existOrFail('actionsList'); - }); + expect(headingText).to.be('Rules'); }); describe('Alerts tab', () => { diff --git a/x-pack/test/functional_with_es_ssl/config.ts b/x-pack/test/functional_with_es_ssl/config.ts index fea3ffcf9233d..36b2b0ae44aee 100644 --- a/x-pack/test/functional_with_es_ssl/config.ts +++ b/x-pack/test/functional_with_es_ssl/config.ts @@ -61,6 +61,9 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { triggersActions: { pathname: '/app/management/insightsAndAlerting/triggersActions', }, + triggersActionsConnectors: { + pathname: '/app/management/insightsAndAlerting/triggersActionsConnectors', + }, }, esTestCluster: { ...xpackFunctionalConfig.get('esTestCluster'), diff --git a/x-pack/test/functional_with_es_ssl/page_objects/triggers_actions_ui_page.ts b/x-pack/test/functional_with_es_ssl/page_objects/triggers_actions_ui_page.ts index 2b17eb48a2afc..d26b1124f8271 100644 --- a/x-pack/test/functional_with_es_ssl/page_objects/triggers_actions_ui_page.ts +++ b/x-pack/test/functional_with_es_ssl/page_objects/triggers_actions_ui_page.ts @@ -61,6 +61,11 @@ export function TriggersActionsPageProvider({ getService }: FtrProviderContext) await this.clickCreateFirstConnectorButton(); } }, + async tableFinishedLoading() { + await find.byCssSelector( + '.euiBasicTable[data-test-subj="actionsTable"]:not(.euiBasicTable-loading)' + ); + }, async searchConnectors(searchText: string) { const searchBox = await find.byCssSelector('[data-test-subj="actionsList"] .euiFieldSearch'); await searchBox.click(); diff --git a/x-pack/test/load/config.ts b/x-pack/test/load/config.ts index dcaa2031c9c02..1419e6ea47c48 100644 --- a/x-pack/test/load/config.ts +++ b/x-pack/test/load/config.ts @@ -15,6 +15,9 @@ const APM_SERVER_URL = 'https://142fea2d3047486e925eb8b223559cae.apm.europe-west const APM_PUBLIC_TOKEN = 'pWFFEym07AKBBhUE2i'; const AGGS_SHARD_DELAY = process.env.LOAD_TESTING_SHARD_DELAY; const DISABLE_PLUGINS = process.env.LOAD_TESTING_DISABLE_PLUGINS; +const journeyName = process.env.GATLING_SIMULATIONS; +const testBuildId = process.env.BUILD_ID; +const branchName = process.env.KIBANA_BRANCH; export default async function ({ readConfigFile }: FtrConfigProviderContext) { const kibanaCommonTestsConfig = await readConfigFile( @@ -60,12 +63,12 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { ELASTIC_APM_SERVER_URL: APM_SERVER_URL, ELASTIC_APM_SECRET_TOKEN: APM_PUBLIC_TOKEN, ELASTIC_APM_GLOBAL_LABELS: Object.entries({ - simulation: process.env.GATLING_SIMULATIONS - ? process.env.GATLING_SIMULATIONS - : 'unknown simulation', + journeyName, + testBuildId, + branchName, }) - .filter(([, v]) => !!v) - .reduce((acc, [k, v]) => (acc ? `${acc},${k}=${v}` : `${k}=${v}`), ''), + .flatMap(([key, value]) => (value == null ? [] : `${key}=${value}`)) + .join(','), }, // delay shutdown by 150 seconds to ensure that APM can report the data it collects during test execution delayShutdown: 150_000, diff --git a/x-pack/test/saved_object_tagging/common/fixtures/es_archiver/visualize/data.json b/x-pack/test/saved_object_tagging/common/fixtures/es_archiver/visualize/data.json index f00485e25581f..24f68ba32f047 100644 --- a/x-pack/test/saved_object_tagging/common/fixtures/es_archiver/visualize/data.json +++ b/x-pack/test/saved_object_tagging/common/fixtures/es_archiver/visualize/data.json @@ -1,4 +1,4 @@ -{ +[{ "id": "tag-1", "type": "tag", "attributes": { @@ -8,8 +8,7 @@ }, "references": [], "updated_at": "2021-06-17T18:57:58.076Z" -} - +}, { "id": "tag-2", "type": "tag", @@ -20,8 +19,7 @@ }, "references": [], "updated_at": "2021-06-17T18:57:58.076Z" -} - +}, { "id": "tag-3", "type": "tag", @@ -32,8 +30,18 @@ }, "references": [], "updated_at": "2021-06-17T18:57:58.076Z" -} - +}, +{ + "id": "myextratag", + "type": "tag", + "attributes": { + "name": "myextratag", + "description": "We need one more", + "color": "#000000" + }, + "references": [], + "updated_at": "2021-06-17T18:57:58.076Z" +}, { "id": "logstash-*", "type": "index-pattern", @@ -45,8 +53,7 @@ }, "references": [], "updated_at": "2021-06-17T18:57:58.076Z" -} - +}, { "id": "vis-area-1", "type": "visualization", @@ -67,8 +74,7 @@ } ], "updated_at": "2021-06-17T18:57:58.076Z" -} - +}, { "id": "vis-area-2", "type": "visualization", @@ -89,8 +95,7 @@ } ], "updated_at": "2021-06-17T18:57:58.076Z" -} - +}, { "id": "vis-area-3", "type": "visualization", @@ -115,4 +120,4 @@ } ], "updated_at": "2021-06-17T18:57:58.076Z" -} +}] diff --git a/x-pack/test/saved_object_tagging/functional/tests/constants.ts b/x-pack/test/saved_object_tagging/functional/tests/constants.ts new file mode 100644 index 0000000000000..7c5a441e2cefe --- /dev/null +++ b/x-pack/test/saved_object_tagging/functional/tests/constants.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export const TAGFILTER_DROPDOWN_SELECTOR = + '.euiFilterGroup .euiPopover:nth-child(2) .euiFilterButton'; diff --git a/x-pack/test/saved_object_tagging/functional/tests/dashboard_integration.ts b/x-pack/test/saved_object_tagging/functional/tests/dashboard_integration.ts index 22c8b159b12ed..41b337ed6a8c2 100644 --- a/x-pack/test/saved_object_tagging/functional/tests/dashboard_integration.ts +++ b/x-pack/test/saved_object_tagging/functional/tests/dashboard_integration.ts @@ -7,6 +7,7 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../ftr_provider_context'; +import { TAGFILTER_DROPDOWN_SELECTOR } from './constants'; // eslint-disable-next-line import/no-default-export export default function ({ getPageObjects, getService }: FtrProviderContext) { @@ -22,7 +23,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { */ const selectFilterTags = async (...tagNames: string[]) => { // open the filter dropdown - const filterButton = await find.byCssSelector('.euiFilterGroup .euiFilterButton'); + const filterButton = await find.byCssSelector(TAGFILTER_DROPDOWN_SELECTOR); await filterButton.click(); // select the tags for (const tagName of tagNames) { diff --git a/x-pack/test/saved_object_tagging/functional/tests/maps_integration.ts b/x-pack/test/saved_object_tagging/functional/tests/maps_integration.ts index 97402fe5c76c7..fb484b61b96d5 100644 --- a/x-pack/test/saved_object_tagging/functional/tests/maps_integration.ts +++ b/x-pack/test/saved_object_tagging/functional/tests/maps_integration.ts @@ -7,6 +7,7 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../ftr_provider_context'; +import { TAGFILTER_DROPDOWN_SELECTOR } from './constants'; // eslint-disable-next-line import/no-default-export export default function ({ getPageObjects, getService }: FtrProviderContext) { @@ -21,7 +22,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { */ const selectFilterTags = async (...tagNames: string[]) => { // open the filter dropdown - const filterButton = await find.byCssSelector('.euiFilterGroup .euiFilterButton'); + const filterButton = await find.byCssSelector(TAGFILTER_DROPDOWN_SELECTOR); await filterButton.click(); // select the tags for (const tagName of tagNames) { diff --git a/x-pack/test/saved_object_tagging/functional/tests/visualize_integration.ts b/x-pack/test/saved_object_tagging/functional/tests/visualize_integration.ts index faf9e8aed8306..31daa97f534cb 100644 --- a/x-pack/test/saved_object_tagging/functional/tests/visualize_integration.ts +++ b/x-pack/test/saved_object_tagging/functional/tests/visualize_integration.ts @@ -7,6 +7,7 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../ftr_provider_context'; +import { TAGFILTER_DROPDOWN_SELECTOR } from './constants'; // eslint-disable-next-line import/no-default-export export default function ({ getPageObjects, getService }: FtrProviderContext) { @@ -15,14 +16,21 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { const listingTable = getService('listingTable'); const testSubjects = getService('testSubjects'); const find = getService('find'); - const PageObjects = getPageObjects(['visualize', 'tagManagement', 'visEditor', 'common']); + const retry = getService('retry'); + const PageObjects = getPageObjects([ + 'visualize', + 'tagManagement', + 'visEditor', + 'common', + 'header', + ]); /** * Select tags in the searchbar's tag filter. */ const selectFilterTags = async (...tagNames: string[]) => { // open the filter dropdown - const filterButton = await find.byCssSelector('.euiFilterGroup .euiFilterButton'); + const filterButton = await find.byCssSelector(TAGFILTER_DROPDOWN_SELECTOR); await filterButton.click(); // select the tags for (const tagName of tagNames) { @@ -46,10 +54,40 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { } await testSubjects.click('savedObjectTitle'); }; + // creates a simple markdown vis with a tag provided. + const createSimpleMarkdownVis = async (opts: Record) => { + const { visName, visText, tagName } = opts; + await PageObjects.visualize.navigateToNewVisualization(); + + await PageObjects.visualize.clickMarkdownWidget(); + await PageObjects.visEditor.setMarkdownTxt(visText); + await PageObjects.visEditor.clickGo(); + + await PageObjects.visualize.ensureSavePanelOpen(); + await PageObjects.visualize.setSaveModalValues(visName, { + saveAsNew: false, + redirectToOrigin: true, + }); + if (tagName) { + await selectSavedObjectTags(tagName); + } - // Failing: See https://github.com/elastic/kibana/issues/89958 - describe.skip('visualize integration', () => { + await testSubjects.click('confirmSaveSavedObjectButton'); + await retry.waitForWithTimeout('Save modal to disappear', 5000, () => + testSubjects + .missingOrFail('confirmSaveSavedObjectButton') + .then(() => true) + .catch(() => false) + ); + + await PageObjects.header.waitUntilLoadingHasFinished(); + }; + + describe('visualize integration', () => { before(async () => { + // clean up any left-over visualizations and tags from tests that didn't clean up after themselves + await kibanaServer.savedObjects.clean({ types: ['tag', 'visualization'] }); + await kibanaServer.importExport.load( 'x-pack/test/saved_object_tagging/common/fixtures/es_archiver/visualize/data.json' ); @@ -61,7 +99,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await kibanaServer.importExport.unload( 'x-pack/test/saved_object_tagging/common/fixtures/es_archiver/visualize/data.json' ); - await kibanaServer.savedObjects.clean({ types: ['tag'] }); + // clean up after test suite + await kibanaServer.savedObjects.clean({ types: ['tag', 'visualization'] }); await esArchiver.unload( 'x-pack/test/saved_object_tagging/common/fixtures/es_archiver/logstash_functional' ); @@ -76,7 +115,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { it('allows to manually type tag filter query', async () => { await listingTable.searchForItemWithName('tag:(tag-1)', { escape: false }); await listingTable.expectItemsCount('visualize', 2); - const itemNames = await listingTable.getAllItemsNames(); + const itemNames = await listingTable.getAllSelectableItemsNames(); expect(itemNames).to.eql(['Visualization 1 (tag-1)', 'Visualization 3 (tag-1 + tag-3)']); }); @@ -84,7 +123,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await selectFilterTags('tag-1'); await listingTable.expectItemsCount('visualize', 2); - const itemNames = await listingTable.getAllItemsNames(); + const itemNames = await listingTable.getAllSelectableItemsNames(); expect(itemNames).to.eql(['Visualization 1 (tag-1)', 'Visualization 3 (tag-1 + tag-3)']); }); @@ -92,32 +131,30 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await selectFilterTags('tag-2', 'tag-3'); await listingTable.expectItemsCount('visualize', 2); - const itemNames = await listingTable.getAllItemsNames(); + const itemNames = await listingTable.getAllSelectableItemsNames(); expect(itemNames).to.eql(['Visualization 2 (tag-2)', 'Visualization 3 (tag-1 + tag-3)']); }); }); describe('creating', () => { + before(async () => { + await PageObjects.visualize.gotoVisualizationLandingPage(); + // delete all visualizations to create new ones explicitly + await PageObjects.visualize.deleteAllVisualizations(); + }); it('allows to assign tags to the new visualization', async () => { await PageObjects.visualize.navigateToNewVisualization(); - - await PageObjects.visualize.clickMarkdownWidget(); - await PageObjects.visEditor.setMarkdownTxt('Just some markdown'); - await PageObjects.visEditor.clickGo(); - - await PageObjects.visualize.ensureSavePanelOpen(); - await PageObjects.visualize.setSaveModalValues('My new markdown viz'); - - await selectSavedObjectTags('tag-1'); - - await testSubjects.click('confirmSaveSavedObjectButton'); - await PageObjects.common.waitForSaveModalToClose(); + await createSimpleMarkdownVis({ + visText: 'Just some markdown', + visName: 'My new markdown viz', + tagName: 'myextratag', + }); await PageObjects.visualize.gotoVisualizationLandingPage(); await listingTable.waitUntilTableIsLoaded(); - await selectFilterTags('tag-1'); - const itemNames = await listingTable.getAllItemsNames(); + await selectFilterTags('myextratag'); + const itemNames = await listingTable.getAllSelectableItemsNames(); expect(itemNames).to.contain('My new markdown viz'); }); @@ -131,7 +168,10 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await PageObjects.visEditor.clickGo(); await PageObjects.visualize.ensureSavePanelOpen(); - await PageObjects.visualize.setSaveModalValues('vis-with-new-tag'); + await PageObjects.visualize.setSaveModalValues('vis-with-new-tag', { + saveAsNew: false, + redirectToOrigin: true, + }); await testSubjects.click('savedObjectTagSelector'); await testSubjects.click(`tagSelectorOption-action__create`); @@ -158,33 +198,43 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await listingTable.waitUntilTableIsLoaded(); await selectFilterTags('my-new-tag'); - const itemNames = await listingTable.getAllItemsNames(); + const itemNames = await listingTable.getAllSelectableItemsNames(); expect(itemNames).to.contain('vis-with-new-tag'); }); }); - // FLAKY: https://github.com/elastic/kibana/issues/88639 - describe.skip('editing', () => { - beforeEach(async () => { + describe('editing', () => { + before(async () => { await PageObjects.visualize.gotoVisualizationLandingPage(); - await listingTable.waitUntilTableIsLoaded(); + await PageObjects.visualize.deleteAllVisualizations(); + // create a vis to add a tag to during edit + await PageObjects.visualize.navigateToNewVisualization(); + await createSimpleMarkdownVis({ + visText: 'Edit me!', + visName: 'MarkdownViz', + }); }); it('allows to assign tags to an existing visualization', async () => { - await listingTable.clickItemLink('visualize', 'Visualization 1 (tag-1)'); - + await PageObjects.visualize.gotoVisualizationLandingPage(); + await listingTable.waitUntilTableIsLoaded(); + await listingTable.clickItemLink('visualize', 'MarkdownViz'); await PageObjects.visualize.ensureSavePanelOpen(); - await selectSavedObjectTags('tag-2'); - + await selectSavedObjectTags(...['myextratag']); await testSubjects.click('confirmSaveSavedObjectButton'); - await PageObjects.common.waitForSaveModalToClose(); + await retry.waitForWithTimeout('Save modal to disappear', 5000, () => + testSubjects + .missingOrFail('confirmSaveSavedObjectButton') + .then(() => true) + .catch(() => false) + ); await PageObjects.visualize.gotoVisualizationLandingPage(); await listingTable.waitUntilTableIsLoaded(); - await selectFilterTags('tag-2'); - const itemNames = await listingTable.getAllItemsNames(); - expect(itemNames).to.contain('Visualization 1 (tag-1)'); + await selectFilterTags('myextratag'); + const itemNames = await listingTable.getAllSelectableItemsNames(); + expect(itemNames).to.contain('MarkdownViz'); }); }); }); 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 4643b91303be0..80053108b46fa 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,7 +16,8 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const endpointTestResources = getService('endpointTestResources'); const policyTestResources = getService('policyTestResources'); - describe('When on the Trusted Apps list', function () { + // FLAKY: https://github.com/elastic/kibana/issues/114309 + describe.skip('When on the Trusted Apps list', function () { let indexedData: IndexedHostsAndAlertsResponse; before(async () => { const endpointPackage = await policyTestResources.getEndpointPackage(); diff --git a/x-pack/test/security_solution_endpoint_api_int/apis/endpoint_authz.ts b/x-pack/test/security_solution_endpoint_api_int/apis/endpoint_authz.ts index 6152bbfe150c6..9b7212b20b833 100644 --- a/x-pack/test/security_solution_endpoint_api_int/apis/endpoint_authz.ts +++ b/x-pack/test/security_solution_endpoint_api_int/apis/endpoint_authz.ts @@ -7,11 +7,8 @@ import { wrapErrorAndRejectPromise } from '@kbn/security-solution-plugin/common/endpoint/data_loaders/utils'; import { - ACTION_STATUS_ROUTE, AGENT_POLICY_SUMMARY_ROUTE, - BASE_POLICY_RESPONSE_ROUTE, GET_PROCESSES_ROUTE, - HOST_METADATA_LIST_ROUTE, ISOLATE_HOST_ROUTE, ISOLATE_HOST_ROUTE_V2, KILL_PROCESS_ROUTE, @@ -41,16 +38,6 @@ export default function ({ getService }: FtrProviderContext) { }); const apiList = [ - { - method: 'get', - path: HOST_METADATA_LIST_ROUTE, - body: undefined, - }, - { - method: 'get', - path: `${ACTION_STATUS_ROUTE}?agent_ids=1`, - body: undefined, - }, { method: 'get', path: `${AGENT_POLICY_SUMMARY_ROUTE}?package_name=endpoint`, @@ -61,11 +48,6 @@ export default function ({ getService }: FtrProviderContext) { path: '/api/endpoint/action_log/one?start_date=2021-12-01&end_date=2021-12-04', body: undefined, }, - { - method: 'get', - path: `${BASE_POLICY_RESPONSE_ROUTE}?agentId=1`, - body: undefined, - }, { method: 'post', path: ISOLATE_HOST_ROUTE, diff --git a/x-pack/test/stack_functional_integration/apps/telemetry/_telemetry.js b/x-pack/test/stack_functional_integration/apps/telemetry/_telemetry.js index d35102cae1b7f..46d8af2280264 100644 --- a/x-pack/test/stack_functional_integration/apps/telemetry/_telemetry.js +++ b/x-pack/test/stack_functional_integration/apps/telemetry/_telemetry.js @@ -11,6 +11,7 @@ export default ({ getService, getPageObjects }) => { const log = getService('log'); const browser = getService('browser'); const PageObjects = getPageObjects(['common']); + const retry = getService('retry'); describe('telemetry', function () { before(async () => { @@ -23,9 +24,11 @@ export default ({ getService, getPageObjects }) => { }); it('should show banner Help us improve the Elastic Stack', async () => { - const actualMessage = await PageObjects.common.getWelcomeText(); - log.debug(`### X-Pack Welcome Text: ${actualMessage}`); - expect(actualMessage).to.contain('Help us improve the Elastic Stack'); + await retry.tryForTime(20000, async () => { + const actualMessage = await PageObjects.common.getWelcomeText(); + log.debug(`### X-Pack Welcome Text: ${actualMessage}`); + expect(actualMessage).to.contain('Help us improve the Elastic Stack'); + }); }); }); }; diff --git a/x-pack/test/stack_functional_integration/configs/config.stack_functional_integration_base.js b/x-pack/test/stack_functional_integration/configs/config.stack_functional_integration_base.js index 00dd89acbc9ef..be05ce3e5e35a 100644 --- a/x-pack/test/stack_functional_integration/configs/config.stack_functional_integration_base.js +++ b/x-pack/test/stack_functional_integration/configs/config.stack_functional_integration_base.js @@ -12,6 +12,9 @@ import { REPO_ROOT } from '@kbn/utils'; import chalk from 'chalk'; import { esTestConfig, kbnTestConfig } from '@kbn/test'; import { TriggersActionsPageProvider } from '../../functional_with_es_ssl/page_objects/triggers_actions_ui_page'; +import { ReportingAPIProvider } from '../../upgrade/services/reporting_upgrade_services'; +import { MapsHelper } from '../../upgrade/services/maps_upgrade_services'; +import { RulesHelper } from '../../upgrade/services/rules_upgrade_services'; const log = new ToolingLog({ level: 'info', @@ -24,6 +27,7 @@ const testsFolder = '../apps'; const prepend = (testFile) => require.resolve(`${testsFolder}/${testFile}`); export default async ({ readConfigFile }) => { + const apiConfig = await readConfigFile(require.resolve('../../api_integration/config')); const xpackFunctionalConfig = await readConfigFile( require.resolve('../../functional/config.base.js') ); @@ -65,6 +69,13 @@ export default async ({ readConfigFile }) => { screenshots: { directory: resolve(INTEGRATION_TEST_ROOT, 'test/screenshots'), }, + services: { + ...apiConfig.get('services'), + ...xpackFunctionalConfig.get('services'), + reportingAPI: ReportingAPIProvider, + mapsHelper: MapsHelper, + rulesHelper: RulesHelper, + }, }; return settings; }; diff --git a/x-pack/test/upgrade/apps/dashboard/dashboard_smoke_tests.ts b/x-pack/test/upgrade/apps/dashboard/dashboard_smoke_tests.ts index b156f909d7a5d..341d4af0e4c64 100644 --- a/x-pack/test/upgrade/apps/dashboard/dashboard_smoke_tests.ts +++ b/x-pack/test/upgrade/apps/dashboard/dashboard_smoke_tests.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import moment from 'moment'; +import semver from 'semver'; import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ getPageObjects, getService }: FtrProviderContext) { @@ -24,7 +24,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { ]; const dashboardTests = [ - { name: 'flights', numPanels: 16 }, + { name: 'flights', numPanels: 15 }, { name: 'logs', numPanels: 10 }, { name: 'ecommerce', numPanels: 11 }, ]; @@ -41,12 +41,9 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { dashboardTests.forEach(({ name, numPanels }) => { it('should launch sample ' + name + ' data set dashboard', async () => { await PageObjects.home.launchSampleDashboard(name); + await PageObjects.timePicker.setCommonlyUsedTime('Last_1 year'); await PageObjects.header.waitUntilLoadingHasFinished(); await renderable.waitForRender(); - const todayYearMonthDay = moment().format('MMM D, YYYY'); - const fromTime = `${todayYearMonthDay} @ 00:00:00.000`; - const toTime = `${todayYearMonthDay} @ 23:59:59.999`; - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); const panelCount = await PageObjects.dashboard.getPanelCount(); expect(panelCount).to.be.above(numPanels); }); @@ -58,7 +55,11 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { log.debug('Checking saved searches rendered'); await dashboardExpect.savedSearchRowCount(49); log.debug('Checking input controls rendered'); - await dashboardExpect.controlCount(3); + if (semver.lt(process.env.ORIGINAL_VERSION!, '8.6.0-SNAPSHOT')) { + await dashboardExpect.inputControlItemCount(3); + } else { + await dashboardExpect.controlCount(3); + } log.debug('Checking tag cloud rendered'); await dashboardExpect.tagCloudWithValuesFound([ 'Sunny', diff --git a/yarn.lock b/yarn.lock index 6539efddf1481..37d42451920af 100644 --- a/yarn.lock +++ b/yarn.lock @@ -650,7 +650,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-syntax-jsx@^7.12.13", "@babel/plugin-syntax-jsx@^7.17.12", "@babel/plugin-syntax-jsx@^7.18.6": +"@babel/plugin-syntax-jsx@^7.17.12", "@babel/plugin-syntax-jsx@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz#a8feef63b010150abd97f1649ec296e849943ca0" integrity sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q== @@ -929,18 +929,7 @@ dependencies: "@babel/plugin-transform-react-jsx" "^7.18.6" -"@babel/plugin-transform-react-jsx@^7.12.12", "@babel/plugin-transform-react-jsx@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.18.6.tgz#2721e96d31df96e3b7ad48ff446995d26bc028ff" - integrity sha512-Mz7xMPxoy9kPS/JScj6fJs03TZ/fZ1dJPlMjRAgTaxaS0fUBk8FV/A2rRgfPsVCZqALNwMexD+0Uaf5zlcKPpw== - dependencies: - "@babel/helper-annotate-as-pure" "^7.18.6" - "@babel/helper-module-imports" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/plugin-syntax-jsx" "^7.18.6" - "@babel/types" "^7.18.6" - -"@babel/plugin-transform-react-jsx@^7.17.12": +"@babel/plugin-transform-react-jsx@^7.12.12", "@babel/plugin-transform-react-jsx@^7.17.12", "@babel/plugin-transform-react-jsx@^7.18.6": version "7.19.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.19.0.tgz#b3cbb7c3a00b92ec8ae1027910e331ba5c500eb9" integrity sha512-UVEvX3tXie3Szm3emi1+G63jyw1w5IcMY0FSKM+CRnKRI5Mr1YbCNgsSTwoTwKphQEG9P+QqmuRFneJPZuHNhg== @@ -1186,7 +1175,7 @@ core-js-pure "^3.0.0" regenerator-runtime "^0.13.4" -"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.0", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.15.4", "@babel/runtime@^7.17.8", "@babel/runtime@^7.18.3", "@babel/runtime@^7.19.0", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": +"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.0", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.15.4", "@babel/runtime@^7.17.8", "@babel/runtime@^7.18.3", "@babel/runtime@^7.19.0", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": version "7.19.0" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.19.0.tgz#22b11c037b094d27a8a2504ea4dcff00f50e2259" integrity sha512-eR8Lo9hnDS7tqkO7NsV+mKvCmv5boaXFSZ70DnfhcgiEne8hv9oCEd36Klw74EtizEqLsy4YnW8UWwpBVolHZA== @@ -1466,10 +1455,10 @@ dependencies: object-hash "^1.3.0" -"@elastic/charts@50.0.1": - version "50.0.1" - resolved "https://registry.yarnpkg.com/@elastic/charts/-/charts-50.0.1.tgz#a0ee66668c857be7cfea2e134e0b84930d1564c5" - integrity sha512-O1L8rot0dycTQo/0eW7aD2P4K3Bh1LtzMgRBXYZAtIpbzdxveRkl8fOlIkGxeeHE4YNvntUJaJWeyT+ngGg7QA== +"@elastic/charts@50.0.2": + version "50.0.2" + resolved "https://registry.yarnpkg.com/@elastic/charts/-/charts-50.0.2.tgz#45d37544d57af8d67a1033bbd78ebe3f58d9f662" + integrity sha512-Q2fPS/bwKCYfTE7/dFO9OdlFtQQ7NMhflbl4WnHjpBcDeqUsqE/6cHd8XyvY/+WFhH9fkyCzBlO/eRBA3KatmA== dependencies: "@popperjs/core" "^2.4.0" bezier-easing "^2.1.0" @@ -1733,24 +1722,6 @@ source-map "^0.5.7" stylis "4.0.13" -"@emotion/babel-plugin@^11.7.1": - version "11.7.1" - resolved "https://registry.yarnpkg.com/@emotion/babel-plugin/-/babel-plugin-11.7.1.tgz#853fc4985d89dab0ea8e17af2858473d1b11be7e" - integrity sha512-K3/6Y+J/sIAjplf3uIteWLhPuOyuMNnE+iyYnTF/m294vc6IL90kTHp7y8ldZYbpKlP17rpOWDKM9DvTcrOmNQ== - dependencies: - "@babel/helper-module-imports" "^7.12.13" - "@babel/plugin-syntax-jsx" "^7.12.13" - "@babel/runtime" "^7.13.10" - "@emotion/hash" "^0.8.0" - "@emotion/memoize" "^0.7.5" - "@emotion/serialize" "^1.0.2" - babel-plugin-macros "^2.6.1" - convert-source-map "^1.5.0" - escape-string-regexp "^4.0.0" - find-root "^1.1.0" - source-map "^0.5.7" - stylis "4.0.13" - "@emotion/babel-preset-css-prop@^11.10.0": version "11.10.0" resolved "https://registry.yarnpkg.com/@emotion/babel-preset-css-prop/-/babel-preset-css-prop-11.10.0.tgz#23922787561d8376782b0e9006323512fe797275" @@ -1771,7 +1742,7 @@ "@emotion/utils" "0.11.3" "@emotion/weak-memoize" "0.2.5" -"@emotion/cache@^11.10.0", "@emotion/cache@^11.10.3": +"@emotion/cache@^11.10.0", "@emotion/cache@^11.10.3", "@emotion/cache@^11.4.0": version "11.10.3" resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.10.3.tgz#c4f67904fad10c945fea5165c3a5a0583c164b87" integrity sha512-Psmp/7ovAa8appWh3g51goxu/z3iVms7JXOreq136D8Bbn6dYraPnmL6mdM8GThEx9vwSn92Fz+mGSjBzN8UPQ== @@ -1782,17 +1753,6 @@ "@emotion/weak-memoize" "^0.3.0" stylis "4.0.13" -"@emotion/cache@^11.4.0", "@emotion/cache@^11.9.3": - version "11.9.3" - resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.9.3.tgz#96638449f6929fd18062cfe04d79b29b44c0d6cb" - integrity sha512-0dgkI/JKlCXa+lEXviaMtGBL0ynpx4osh7rjOXE71q9bIF8G+XhJgvi+wDu0B0IdCVx37BffiwXlN9I3UuzFvg== - dependencies: - "@emotion/memoize" "^0.7.4" - "@emotion/sheet" "^1.1.1" - "@emotion/utils" "^1.0.0" - "@emotion/weak-memoize" "^0.2.5" - stylis "4.0.13" - "@emotion/core@^10.0.9": version "10.1.1" resolved "https://registry.yarnpkg.com/@emotion/core/-/core-10.1.1.tgz#c956c1365f2f2481960064bcb8c4732e5fb612c3" @@ -1833,7 +1793,7 @@ "@emotion/sheet" "^1.2.0" "@emotion/utils" "^1.2.0" -"@emotion/hash@0.8.0", "@emotion/hash@^0.8.0": +"@emotion/hash@0.8.0": version "0.8.0" resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.8.0.tgz#bbbff68978fefdbe68ccb533bc8cbe1d1afb5413" integrity sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow== @@ -1866,17 +1826,12 @@ resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.4.tgz#19bf0f5af19149111c40d98bb0cf82119f5d9eeb" integrity sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw== -"@emotion/memoize@^0.7.4", "@emotion/memoize@^0.7.5": - version "0.7.5" - resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.5.tgz#2c40f81449a4e554e9fc6396910ed4843ec2be50" - integrity sha512-igX9a37DR2ZPGYtV6suZ6whr8pTFtyHL3K/oLUotxpSVO2ASaprmAe2Dkq7tBo7CRY7MMDrAa9nuQP9/YG8FxQ== - "@emotion/memoize@^0.8.0": version "0.8.0" resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.8.0.tgz#f580f9beb67176fa57aae70b08ed510e1b18980f" integrity sha512-G/YwXTkv7Den9mXDO7AhLWkE3q+I92B+VqAE+dYG4NGPaHZGvt3G8Q0p9vmE+sq7rTGphUbAvmQ9YpbfMQGGlA== -"@emotion/react@^11.10.4": +"@emotion/react@^11.10.4", "@emotion/react@^11.8.1": version "11.10.4" resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.10.4.tgz#9dc6bccbda5d70ff68fdb204746c0e8b13a79199" integrity sha512-j0AkMpr6BL8gldJZ6XQsQ8DnS9TxEQu1R+OGmDZiWjBAJtCcbt0tS3I/YffoqHXxH6MjgI7KdMbYKw3MEiU9eA== @@ -1890,19 +1845,6 @@ "@emotion/weak-memoize" "^0.3.0" hoist-non-react-statics "^3.3.1" -"@emotion/react@^11.8.1": - version "11.9.3" - resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.9.3.tgz#f4f4f34444f6654a2e550f5dab4f2d360c101df9" - integrity sha512-g9Q1GcTOlzOEjqwuLF/Zd9LC+4FljjPjDfxSM7KmEakm+hsHXk+bYZ2q+/hTJzr0OUNkujo72pXLQvXj6H+GJQ== - dependencies: - "@babel/runtime" "^7.13.10" - "@emotion/babel-plugin" "^11.7.1" - "@emotion/cache" "^11.9.3" - "@emotion/serialize" "^1.0.4" - "@emotion/utils" "^1.1.0" - "@emotion/weak-memoize" "^0.2.5" - hoist-non-react-statics "^3.3.1" - "@emotion/serialize@^0.11.15", "@emotion/serialize@^0.11.16": version "0.11.16" resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-0.11.16.tgz#dee05f9e96ad2fb25a5206b6d759b2d1ed3379ad" @@ -1914,17 +1856,6 @@ "@emotion/utils" "0.11.3" csstype "^2.5.7" -"@emotion/serialize@^1.0.2", "@emotion/serialize@^1.0.4": - version "1.0.4" - resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-1.0.4.tgz#ff31fd11bb07999611199c2229e152faadc21a3c" - integrity sha512-1JHamSpH8PIfFwAMryO2bNka+y8+KA5yga5Ocf2d7ZEiJjb7xlLW7aknBGZqJLajuLOvJ+72vN+IBSwPlXD1Pg== - dependencies: - "@emotion/hash" "^0.8.0" - "@emotion/memoize" "^0.7.4" - "@emotion/unitless" "^0.7.5" - "@emotion/utils" "^1.0.0" - csstype "^3.0.2" - "@emotion/serialize@^1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-1.1.0.tgz#b1f97b1011b09346a40e9796c37a3397b4ea8ea8" @@ -1951,11 +1882,6 @@ resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-0.9.4.tgz#894374bea39ec30f489bbfc3438192b9774d32e5" integrity sha512-zM9PFmgVSqBw4zL101Q0HrBVTGmpAxFZH/pYx/cjJT5advXguvcgjHFTCaIO3enL/xr89vK2bh0Mfyj9aa0ANA== -"@emotion/sheet@^1.1.1": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-1.1.1.tgz#015756e2a9a3c7c5f11d8ec22966a8dbfbfac787" - integrity sha512-J3YPccVRMiTZxYAY0IOq3kd+hUP8idY8Kz6B/Cyo+JuXq52Ek+zbPbSQUrVQp95aJ+lsAW7DPL1P2Z+U1jGkKA== - "@emotion/sheet@^1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-1.2.0.tgz#771b1987855839e214fc1741bde43089397f7be5" @@ -1966,7 +1892,7 @@ resolved "https://registry.yarnpkg.com/@emotion/stylis/-/stylis-0.8.5.tgz#deacb389bd6ee77d1e7fcaccce9e16c5c7e78e04" integrity sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ== -"@emotion/unitless@0.7.5", "@emotion/unitless@^0.7.4", "@emotion/unitless@^0.7.5": +"@emotion/unitless@0.7.5", "@emotion/unitless@^0.7.4": version "0.7.5" resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.7.5.tgz#77211291c1900a700b8a78cfafda3160d76949ed" integrity sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg== @@ -1986,17 +1912,12 @@ resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-0.11.3.tgz#a759863867befa7e583400d322652a3f44820924" integrity sha512-0o4l6pZC+hI88+bzuaX/6BgOvQVhbt2PfmxauVaYOGgbsAw14wdKyvMCZXnsnsHys94iadcF+RG/wZyx6+ZZBw== -"@emotion/utils@^1.0.0", "@emotion/utils@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-1.1.0.tgz#86b0b297f3f1a0f2bdb08eeac9a2f49afd40d0cf" - integrity sha512-iRLa/Y4Rs5H/f2nimczYmS5kFJEbpiVvgN3XVfZ022IYhuNA1IRSHEizcof88LtCTXtl9S2Cxt32KgaXEu72JQ== - "@emotion/utils@^1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-1.2.0.tgz#9716eaccbc6b5ded2ea5a90d65562609aab0f561" integrity sha512-sn3WH53Kzpw8oQ5mgMmIzzyAaH2ZqFEbozVVBSYp538E06OSE6ytOp7pRAjNQR+Q/orwqdQYJSe2m3hCOeznkw== -"@emotion/weak-memoize@0.2.5", "@emotion/weak-memoize@^0.2.5": +"@emotion/weak-memoize@0.2.5": version "0.2.5" resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz#8eed982e2ee6f7f4e44c253e12962980791efd46" integrity sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA== @@ -2760,6 +2681,10 @@ version "0.0.0" uid "" +"@kbn/cases-components@link:bazel-bin/packages/kbn-cases-components": + version "0.0.0" + uid "" + "@kbn/chart-icons@link:bazel-bin/packages/kbn-chart-icons": version "0.0.0" uid "" @@ -6904,6 +6829,10 @@ version "0.0.0" uid "" +"@types/kbn__cases-components@link:bazel-bin/packages/kbn-cases-components/npm_module_types": + version "0.0.0" + uid "" + "@types/kbn__chart-icons@link:bazel-bin/packages/kbn-chart-icons/npm_module_types": version "0.0.0" uid "" @@ -9546,10 +9475,10 @@ object.fromentries "^2.0.0" prop-types "^15.7.0" -"@xmldom/xmldom@^0.7.0": - version "0.7.4" - resolved "https://registry.yarnpkg.com/@xmldom/xmldom/-/xmldom-0.7.4.tgz#93b2f9486c88b6464e97f76c9ab49b0a548fbe57" - integrity sha512-wdxC79cvO7PjSM34jATd/RYZuYWQ8y/R7MidZl1NYYlbpFn1+spfjkiR3ZsJfcaTs2IyslBN7VwBBJwrYKM+zw== +"@xmldom/xmldom@^0.8.3": + version "0.8.3" + resolved "https://registry.yarnpkg.com/@xmldom/xmldom/-/xmldom-0.8.3.tgz#beaf980612532aa9a3004aff7e428943aeaa0711" + integrity sha512-Lv2vySXypg4nfa51LY1nU8yDAGo/5YwF+EY/rUZgIbfvwVARcd67ttCM8SMsTeJy51YhHYavEq+FS6R0hW9PFQ== "@xobotyi/scrollbar-width@1.9.5": version "1.9.5" @@ -10564,7 +10493,7 @@ babel-plugin-jest-hoist@^26.6.2: "@types/babel__core" "^7.0.0" "@types/babel__traverse" "^7.0.6" -babel-plugin-macros@^2.0.0, babel-plugin-macros@^2.6.1: +babel-plugin-macros@^2.0.0: version "2.8.0" resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-2.8.0.tgz#0f958a7cc6556b1e65344465d99111a1e5e10138" integrity sha512-SEP5kJpfGYqYKpBrj5XU3ahw5p5GOHJ0U5ssOSQ/WBVdwkD2Dzlce95exQTs3jOVWPPKLBN2rlEWkCK7dSmLvg== @@ -12280,10 +12209,10 @@ core-js@^2.4.0, core-js@^2.5.0, core-js@^2.6.9: resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.9.tgz#6b4b214620c834152e179323727fc19741b084f2" integrity sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A== -core-js@^3.0.4, core-js@^3.25.1, core-js@^3.6.5, core-js@^3.8.2, core-js@^3.8.3: - version "3.25.1" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.25.1.tgz#5818e09de0db8956e16bf10e2a7141e931b7c69c" - integrity sha512-sr0FY4lnO1hkQ4gLDr24K0DGnweGO1QwSj5BpfQjpSJPdqWalja4cTps29Y/PJVG/P7FYlPDkH3hO+Tr0CvDgQ== +core-js@^3.0.4, core-js@^3.25.5, core-js@^3.6.5, core-js@^3.8.2, core-js@^3.8.3: + version "3.25.5" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.25.5.tgz#e86f651a2ca8a0237a5f064c2fe56cef89646e27" + integrity sha512-nbm6eZSjm+ZuBQxCUPQKQCoUEfFOXjUZ8dTTyikyKaWrTYmAVbykQfwsKE5dBK88u3QCkCrzsx/PPlKfhsvgpw== core-util-is@1.0.2, core-util-is@^1.0.2, core-util-is@~1.0.0: version "1.0.2" @@ -15543,12 +15472,7 @@ folktale@2.3.2: resolved "https://registry.yarnpkg.com/folktale/-/folktale-2.3.2.tgz#38231b039e5ef36989920cbf805bf6b227bf4fd4" integrity sha512-+8GbtQBwEqutP0v3uajDDoN64K2ehmHd0cjlghhxh0WpcfPzAIjPA03e1VvHlxL02FVGR0A6lwXsNQKn3H1RNQ== -follow-redirects@^1.0.0, follow-redirects@^1.14.0, follow-redirects@^1.14.9: - version "1.15.0" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.0.tgz#06441868281c86d0dda4ad8bdaead2d02dca89d4" - integrity sha512-aExlJShTV4qOUOL7yF1U5tvLCB0xQuudbf6toyYA0E/acBNw71mvjFTnLaRp50aQaYocMR0a/RMMBIHeZnGyjQ== - -follow-redirects@^1.15.0: +follow-redirects@^1.0.0, follow-redirects@^1.14.0, follow-redirects@^1.14.9, follow-redirects@^1.15.0: version "1.15.2" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== @@ -23576,10 +23500,10 @@ react-grid-layout@^1.3.4: react-draggable "^4.0.0" react-resizable "^3.0.4" -react-hook-form@^7.36.1: - version "7.36.1" - resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.36.1.tgz#82a311fe8cbe75e689fd4529f083b7c983da6520" - integrity sha512-EbYYkCG2p8ywe7ikOH2l02lAFMrrrslZi1I8fqd8ifDGNAkhomHZQzQsP6ksvzrWBKntRe8b5L5L7Zsd+Gm02Q== +react-hook-form@^7.37.0: + version "7.37.0" + resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.37.0.tgz#4d1738f092d3d8a3ade34ee892d97350b1032b19" + integrity sha512-6NFTxsnw+EXSpNNvLr5nFMjPdYKRryQcelTHg7zwBB6vAzfPIcZq4AExP4heVlwdzntepQgwiOQW4z7Mr99Lsg== react-input-autosize@^3.0.0: version "3.0.0" @@ -29142,12 +29066,12 @@ xdg-basedir@^4.0.0: resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13" integrity sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q== -xml-crypto@^2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/xml-crypto/-/xml-crypto-2.1.4.tgz#85b3c62fa0debc4956ee72cb2dfee65651e865b5" - integrity sha512-ModFeGOy67L/XXHcuepnYGF7DASEDw7fhvy+qIs1ORoH55G1IIr+fN0kaMtttwvmNFFMskD9AHro8wx352/mUg== +xml-crypto@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/xml-crypto/-/xml-crypto-3.0.0.tgz#e3342f9c9a94455d4700431ac9803493bf51cf81" + integrity sha512-vdmZOsWgjnFxYGY7OwCgxs+HLWzwvLgX2n0NSYWh3gudckQyNOmtJTT6ooOWEvDZSpC9qRjRs2bEXqKFi1oCHw== dependencies: - "@xmldom/xmldom" "^0.7.0" + "@xmldom/xmldom" "^0.8.3" xpath "0.0.32" xml-name-validator@^3.0.0: @@ -29335,20 +29259,7 @@ yargs@^15.0.2, yargs@^15.3.1, yargs@^15.4.1: y18n "^4.0.0" yargs-parser "^18.1.2" -yargs@^17.0.1, yargs@^17.2.1, yargs@~17.5.1: - version "17.5.1" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.5.1.tgz#e109900cab6fcb7fd44b1d8249166feb0b36e58e" - integrity sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA== - dependencies: - cliui "^7.0.2" - escalade "^3.1.1" - get-caller-file "^2.0.5" - require-directory "^2.1.1" - string-width "^4.2.3" - y18n "^5.0.5" - yargs-parser "^21.0.0" - -yargs@^17.6.0: +yargs@^17.0.1, yargs@^17.2.1, yargs@^17.6.0: version "17.6.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.6.0.tgz#e134900fc1f218bc230192bdec06a0a5f973e46c" integrity sha512-8H/wTDqlSwoSnScvV2N/JHfLWOKuh5MVla9hqLjK3nsfyy6Y4kDSYSvkU5YCUEPOSnRXfIyx3Sq+B/IWudTo4g== @@ -29374,6 +29285,19 @@ yargs@^3.15.0: window-size "^0.1.4" y18n "^3.2.0" +yargs@~17.5.1: + version "17.5.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.5.1.tgz#e109900cab6fcb7fd44b1d8249166feb0b36e58e" + integrity sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.3" + y18n "^5.0.5" + yargs-parser "^21.0.0" + yauzl@^2.10.0: version "2.10.0" resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9"