From 1417fd37f5cfa64e9e2ae2301cd93c78984f59e8 Mon Sep 17 00:00:00 2001 From: Jonathan Budzenski Date: Thu, 4 Jan 2024 07:53:09 -0600 Subject: [PATCH 01/57] skip failing test suite (#174176, #174177) --- .../public/components/actions/tags/edit_tags_flyout.test.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/cases/public/components/actions/tags/edit_tags_flyout.test.tsx b/x-pack/plugins/cases/public/components/actions/tags/edit_tags_flyout.test.tsx index b6ebaa03be06..a167d88f1bf6 100644 --- a/x-pack/plugins/cases/public/components/actions/tags/edit_tags_flyout.test.tsx +++ b/x-pack/plugins/cases/public/components/actions/tags/edit_tags_flyout.test.tsx @@ -16,7 +16,9 @@ import { waitFor } from '@testing-library/react'; jest.mock('../../../containers/api'); -describe('EditTagsFlyout', () => { +// Failing: See https://github.com/elastic/kibana/issues/174176 +// Failing: See https://github.com/elastic/kibana/issues/174177 +describe.skip('EditTagsFlyout', () => { let appMock: AppMockRenderer; /** From 7a613fb6cb252ee1e0e1e74a93644fc3a3b5d05b Mon Sep 17 00:00:00 2001 From: Kyle Pollich Date: Thu, 4 Jan 2024 09:22:20 -0500 Subject: [PATCH 02/57] [Fleet] Add `xpack.fleet.isAirGapped` flag (#174214) ## Summary Closes https://github.com/elastic/kibana/issues/173125 Adds a new `xpack.fleet.isAirGapped` flag to `kibana.yml` that allow users in air-gapped environments to inform Fleet that it should "fail fast" and skip unnecessary requests that won't be possible as Kibana doesn't have internet access. This PR also uses the new flag to skip the API request to the `product_versions` API if the airgapped flag is set to true. There are probably other places we could use this flag in a similar way, but they can be handled separately from this PR. ### Checklist Delete any items that are not applicable to this PR. - [x] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios --- docs/settings/fleet-settings.asciidoc | 2 ++ x-pack/plugins/fleet/common/types/index.ts | 1 + x-pack/plugins/fleet/server/config.ts | 1 + .../server/services/agents/versions.test.ts | 21 ++++++++++++++++--- .../fleet/server/services/agents/versions.ts | 5 +++++ 5 files changed, 27 insertions(+), 3 deletions(-) diff --git a/docs/settings/fleet-settings.asciidoc b/docs/settings/fleet-settings.asciidoc index a85c4b67063e..110af39a5cc4 100644 --- a/docs/settings/fleet-settings.asciidoc +++ b/docs/settings/fleet-settings.asciidoc @@ -24,6 +24,8 @@ See the {fleet-guide}/index.html[{fleet}] docs for more information about {fleet `xpack.fleet.agents.enabled` {ess-icon}:: Set to `true` (default) to enable {fleet}. +`xpack.fleet.isAirGapped`:: +Set to `true` to indicate {fleet} is running in an air-gapped environment. Refer to {fleet-guide}/air-gapped.html[Air-gapped environments] for details. Enabling this flag helps Fleet skip needless requests and improve the user experience for air-gapped environments. [[fleet-data-visualizer-settings]] diff --git a/x-pack/plugins/fleet/common/types/index.ts b/x-pack/plugins/fleet/common/types/index.ts index dfee7502c4ed..e822b1e8e579 100644 --- a/x-pack/plugins/fleet/common/types/index.ts +++ b/x-pack/plugins/fleet/common/types/index.ts @@ -16,6 +16,7 @@ import type { export interface FleetConfigType { enabled: boolean; + isAirGapped?: boolean; registryUrl?: string; registryProxyUrl?: string; agents: { diff --git a/x-pack/plugins/fleet/server/config.ts b/x-pack/plugins/fleet/server/config.ts index 0a817e0ccbfe..0ab132065092 100644 --- a/x-pack/plugins/fleet/server/config.ts +++ b/x-pack/plugins/fleet/server/config.ts @@ -126,6 +126,7 @@ export const config: PluginConfigDescriptor = { ], schema: schema.object( { + isAirGapped: schema.maybe(schema.boolean({ defaultValue: false })), registryUrl: schema.maybe(schema.uri({ scheme: ['http', 'https'] })), registryProxyUrl: schema.maybe(schema.uri({ scheme: ['http', 'https'] })), agents: schema.object({ diff --git a/x-pack/plugins/fleet/server/services/agents/versions.test.ts b/x-pack/plugins/fleet/server/services/agents/versions.test.ts index 15fa38d4949b..9f8a5091e3ee 100644 --- a/x-pack/plugins/fleet/server/services/agents/versions.test.ts +++ b/x-pack/plugins/fleet/server/services/agents/versions.test.ts @@ -8,9 +8,15 @@ import { readFile } from 'fs/promises'; import fetch from 'node-fetch'; +import type { DeepPartial } from 'utility-types'; + +import type { FleetConfigType } from '../../../public/plugin'; + +import { getAvailableVersions } from './versions'; let mockKibanaVersion = '300.0.0'; -let mockConfig = {}; +let mockConfig: DeepPartial = {}; + jest.mock('../app_context', () => { const { loggerMock } = jest.requireActual('@kbn/logging-mocks'); return { @@ -33,8 +39,6 @@ const emptyResponse = { text: jest.fn().mockResolvedValue(JSON.stringify({})), } as any; -import { getAvailableVersions } from './versions'; - describe('getAvailableVersions', () => { beforeEach(() => { mockedReadFile.mockReset(); @@ -204,4 +208,15 @@ describe('getAvailableVersions', () => { // Should sort, uniquify and filter out versions < 7.17 expect(res).toEqual(['8.1.0', '8.0.0', '7.17.0']); }); + + it('should not fetch from product versions API when air-gapped config is set', async () => { + mockKibanaVersion = '300.0.0'; + mockedReadFile.mockResolvedValue(`["8.1.0", "8.0.0", "7.17.0", "7.16.0"]`); + + mockConfig = { isAirGapped: true }; + const res = await getAvailableVersions({ ignoreCache: true }); + + expect(res).toEqual(['8.1.0', '8.0.0', '7.17.0']); + expect(mockedFetch).not.toBeCalled(); + }); }); diff --git a/x-pack/plugins/fleet/server/services/agents/versions.ts b/x-pack/plugins/fleet/server/services/agents/versions.ts index b5a09bc99e2c..39941e2d38fc 100644 --- a/x-pack/plugins/fleet/server/services/agents/versions.ts +++ b/x-pack/plugins/fleet/server/services/agents/versions.ts @@ -111,6 +111,11 @@ export const getAvailableVersions = async ({ }; async function fetchAgentVersionsFromApi() { + // If the airgapped flag is set, do not attempt to reach out to the product versions API + if (appContextService.getConfig()?.isAirGapped) { + return []; + } + const logger = appContextService.getLogger(); const options = { From 488edebdb2a5ae091fc67ccd2b42e967be626a7d Mon Sep 17 00:00:00 2001 From: Mykola Harmash Date: Thu, 4 Jan 2024 15:46:20 +0100 Subject: [PATCH 03/57] [ObsUX][Profiling, Infra] Add educational banners and tooltips (#174089) Closes https://github.com/elastic/kibana/issues/173269 ## Summary Adds educational banners and tooltips to the Profiling tab in Infra. https://github.com/elastic/kibana/assets/793851/f5a19fd1-4900-4f35-aa8c-f35230238fe4 ## How to test 1. Refer to docs to setup profiling [locally](https://github.com/elastic/observability-dev/blob/main/docs/profiling/on_prem.md#setting-profiling-on-prem) or [connected to oblt cluster](https://github.com/elastic/observability-dev/blob/main/docs/profiling/cloud.md#setting-up-local-kibana-to-oblt-clusters) 2. Open one of the hosts and make sure that you see the new banner and tooltips in the tabs. 3. Make sure the banner is dismissible and it's state is preserved when you refresh the page --------- Co-authored-by: Mike Birnstiehl <114418652+mdbirnstiehl@users.noreply.github.com> Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../overview/kpis/cpu_profiling_prompt.tsx | 4 +- .../tabs/overview/kpis/kpi_grid.tsx | 2 - .../asset_details/tabs/overview/overview.tsx | 2 + .../tabs/profiling/description_callout.tsx | 60 +++++++++++++++++++ .../tabs/profiling/profiling.tsx | 55 ++++++++++++++++- .../tabs/profiling/profiling_links.tsx | 2 +- .../observability/server/ui_settings.ts | 6 +- 7 files changed, 120 insertions(+), 11 deletions(-) create mode 100644 x-pack/plugins/infra/public/components/asset_details/tabs/profiling/description_callout.tsx diff --git a/x-pack/plugins/infra/public/components/asset_details/tabs/overview/kpis/cpu_profiling_prompt.tsx b/x-pack/plugins/infra/public/components/asset_details/tabs/overview/kpis/cpu_profiling_prompt.tsx index 291b255e7ce3..54651b46bcce 100644 --- a/x-pack/plugins/infra/public/components/asset_details/tabs/overview/kpis/cpu_profiling_prompt.tsx +++ b/x-pack/plugins/infra/public/components/asset_details/tabs/overview/kpis/cpu_profiling_prompt.tsx @@ -34,7 +34,7 @@ export function CpuProfilingPrompt() { })} - {i18n.translate('xpack.infra.cpuProfilingPrompt.p.viewCPUBreakdownUsingLabel', { + {i18n.translate('xpack.infra.cpuProfilingPrompt.promptText', { defaultMessage: 'View CPU Breakdown using', })} showTab('profiling')} flush="both" > - {i18n.translate('xpack.infra.cpuProfilingPrompt.profilingButtonEmptyLabel', { + {i18n.translate('xpack.infra.cpuProfilingPrompt.profilingLinkLabel', { defaultMessage: 'Profiling', })} diff --git a/x-pack/plugins/infra/public/components/asset_details/tabs/overview/kpis/kpi_grid.tsx b/x-pack/plugins/infra/public/components/asset_details/tabs/overview/kpis/kpi_grid.tsx index f1b8877cdca8..957cb7e628ee 100644 --- a/x-pack/plugins/infra/public/components/asset_details/tabs/overview/kpis/kpi_grid.tsx +++ b/x-pack/plugins/infra/public/components/asset_details/tabs/overview/kpis/kpi_grid.tsx @@ -13,7 +13,6 @@ import { findInventoryModel } from '@kbn/metrics-data-access-plugin/common'; import useAsync from 'react-use/lib/useAsync'; import { KPI_CHART_HEIGHT } from '../../../../../common/visualizations'; import { Kpi } from './kpi'; -import { CpuProfilingPrompt } from './cpu_profiling_prompt'; interface Props { dataView?: DataView; @@ -49,7 +48,6 @@ export const KPIGrid = ({ assetName, dataView, dateRange }: Props) => { assetName={assetName} height={KPI_CHART_HEIGHT} /> - {chartProps.id === 'cpuUsage' && } ))} diff --git a/x-pack/plugins/infra/public/components/asset_details/tabs/overview/overview.tsx b/x-pack/plugins/infra/public/components/asset_details/tabs/overview/overview.tsx index 83cf114d43b9..8da39ec6e6b7 100644 --- a/x-pack/plugins/infra/public/components/asset_details/tabs/overview/overview.tsx +++ b/x-pack/plugins/infra/public/components/asset_details/tabs/overview/overview.tsx @@ -21,6 +21,7 @@ import { useDatePickerContext } from '../../hooks/use_date_picker'; import { SectionSeparator } from './section_separator'; import { MetadataErrorCallout } from '../../components/metadata_error_callout'; import { useIntersectingState } from '../../hooks/use_intersecting_state'; +import { CpuProfilingPrompt } from './kpis/cpu_profiling_prompt'; export const Overview = () => { const ref = useRef(null); @@ -63,6 +64,7 @@ export const Overview = () => { + {fetchMetadataError && !metadataLoading ? : metadataSummarySection} diff --git a/x-pack/plugins/infra/public/components/asset_details/tabs/profiling/description_callout.tsx b/x-pack/plugins/infra/public/components/asset_details/tabs/profiling/description_callout.tsx new file mode 100644 index 000000000000..44f9b611fc8f --- /dev/null +++ b/x-pack/plugins/infra/public/components/asset_details/tabs/profiling/description_callout.tsx @@ -0,0 +1,60 @@ +/* + * 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, { useCallback } from 'react'; +import { i18n } from '@kbn/i18n'; +import { EuiButton, EuiCallOut, EuiFlexGroup, EuiLink, EuiSpacer, EuiText } from '@elastic/eui'; +import useLocalStorage from 'react-use/lib/useLocalStorage'; + +const LOCAL_STORAGE_KEY = 'infra-profiling-description-callout-dismissed'; + +export function DescriptionCallout() { + const [isDismissed, setIsDismissed] = useLocalStorage(LOCAL_STORAGE_KEY, false); + + const onDismissClick = useCallback(() => setIsDismissed(true), [setIsDismissed]); + + if (isDismissed) { + return null; + } + + return ( + <> + + + {i18n.translate('xpack.infra.profiling.descriptionCallout.body', { + defaultMessage: + 'Universal Profiling helps you optimize resource usage and find performance bottlenecks by showing which lines of code are consuming resources on your host, down to the application code, kernel, and third-party libraries.', + })} + + + + + {i18n.translate('xpack.infra.profiling.descriptionCallout.learnMore', { + defaultMessage: 'Learn more', + })} + + + {i18n.translate('xpack.infra.profiling.descriptionCallout.dismiss', { + defaultMessage: 'Dismiss', + })} + + + + + + ); +} diff --git a/x-pack/plugins/infra/public/components/asset_details/tabs/profiling/profiling.tsx b/x-pack/plugins/infra/public/components/asset_details/tabs/profiling/profiling.tsx index 5e34f0ca5027..0e8d888447a5 100644 --- a/x-pack/plugins/infra/public/components/asset_details/tabs/profiling/profiling.tsx +++ b/x-pack/plugins/infra/public/components/asset_details/tabs/profiling/profiling.tsx @@ -6,11 +6,13 @@ */ import { i18n } from '@kbn/i18n'; -import { EuiSpacer, EuiTabbedContent, type EuiTabbedContentProps } from '@elastic/eui'; +import { EuiLink, EuiSpacer, EuiTabbedContent, type EuiTabbedContentProps } from '@elastic/eui'; import React from 'react'; import { ProfilingEmptyState } from '@kbn/observability-shared-plugin/public'; import { EuiLoadingSpinner } from '@elastic/eui'; import { css } from '@emotion/react'; +import { EuiText } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n-react'; import { Flamegraph } from './flamegraph'; import { Functions } from './functions'; import { DatePicker } from '../../date_picker/date_picker'; @@ -19,6 +21,8 @@ import { useTabSwitcherContext } from '../../hooks/use_tab_switcher'; import { ContentTabIds } from '../../types'; import { ErrorPrompt } from './error_prompt'; import { Threads } from './threads'; +import { DescriptionCallout } from './description_callout'; +import { Popover } from '../common/popover'; export function Profiling() { const { activeTabId } = useTabSwitcherContext(); @@ -38,6 +42,30 @@ export function Profiling() { ), + append: ( + + + + {i18n.translate('xpack.infra.profiling.flamegraphTabLearnMoreLink', { + defaultMessage: 'Learn more', + })} + + ), + }} + /> + + + ), }, { id: 'functions', @@ -50,6 +78,30 @@ export function Profiling() { ), + append: ( + + + + {i18n.translate('xpack.infra.profiling.functionsTabLearnMoreLink', { + defaultMessage: 'Learn more', + })} + + ), + }} + /> + + + ), }, { id: 'threads', @@ -89,6 +141,7 @@ export function Profiling() { ) : ( <> + )} diff --git a/x-pack/plugins/infra/public/components/asset_details/tabs/profiling/profiling_links.tsx b/x-pack/plugins/infra/public/components/asset_details/tabs/profiling/profiling_links.tsx index 4922ce0eafea..1509da65d24d 100644 --- a/x-pack/plugins/infra/public/components/asset_details/tabs/profiling/profiling_links.tsx +++ b/x-pack/plugins/infra/public/components/asset_details/tabs/profiling/profiling_links.tsx @@ -51,7 +51,7 @@ export function ProfilingLinks({ target="_blank" > {i18n.translate('xpack.infra.flamegraph.profilingFeedbackLink', { - defaultMessage: 'Give feedback about profiling', + defaultMessage: 'Give feedback', })} diff --git a/x-pack/plugins/observability/server/ui_settings.ts b/x-pack/plugins/observability/server/ui_settings.ts index 5890dd4e1661..f52aedfd893b 100644 --- a/x-pack/plugins/observability/server/ui_settings.ts +++ b/x-pack/plugins/observability/server/ui_settings.ts @@ -245,11 +245,7 @@ export const uiSettings: Record = { description: i18n.translate( 'xpack.observability.enableInfrastructureProfilingIntegrationDescription', { - defaultMessage: - '{betaLabel} Enable Universal Profiling integration in the Infrastructure app.', - values: { - betaLabel: `[${betaLabel}]`, - }, + defaultMessage: 'Enable Universal Profiling integration in the Infrastructure app.', } ), schema: schema.boolean(), From effd9e7a196bd51c284d7785ce803c326cf85ea4 Mon Sep 17 00:00:00 2001 From: Pablo Machado Date: Thu, 4 Jan 2024 15:59:57 +0100 Subject: [PATCH 04/57] [Security Solution] Create new host flyout (#173392) ## Summary Create the Expandable Host flyout with the risk inputs panel. ![Screenshot 2023-12-22 at 16 56 12](https://github.com/elastic/kibana/assets/1490444/a1e14232-620d-4109-a1b6-04e45513e3ee) ### What is included * Host panel creation * Left risk inputs panel * Refactor user panel component to be reused by Host * Risk score section ### What is not included * Asset integration section * Asset criticality ### How to test it? * Enable experimental flag `newHostDetailsFlyout` * Create alerts with `host.name` field * Open the alerts page and click on the `host.name` field * It should not display the expandable risk input panel * Enable Risk engine * make sure it generates data for the host * Open the flyout once more and check if the expandable risk input panel opens --------- Co-authored-by: Tiago Vila Verde Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../common/experimental_features.ts | 8 +- .../security_solution/common/utility_types.ts | 7 + .../common/mock/storybook_providers.tsx | 17 +- .../entity_details_flyout/index.tsx | 4 +- .../risk_summary_flyout/risk_summary.test.tsx | 78 +++- .../risk_summary_flyout/risk_summary.tsx | 398 ++++++++++-------- .../hosts/containers/hosts/details/index.tsx | 4 +- .../host_details_left/index.test.tsx | 38 ++ .../host_details_left/index.tsx | 52 +++ .../host_right/content.stories.tsx | 88 ++++ .../entity_details/host_right/content.tsx | 64 +++ .../host_right/fields/basic_host_fields.tsx | 80 ++++ .../host_right/fields/cloud_fields.ts | 34 ++ .../fields/endpoint_policy_fields.test.tsx | 61 +++ .../fields/endpoint_policy_fields.tsx | 69 +++ .../host_right/fields/translations.ts | 131 ++++++ .../entity_details/host_right/header.test.tsx | 84 ++++ .../entity_details/host_right/header.tsx | 67 +++ .../host_right/hooks/use_observed_host.ts | 71 ++++ .../hooks/use_observed_host_fields.test.ts | 143 +++++++ .../hooks/use_observed_host_fields.ts | 35 ++ .../entity_details/host_right/index.test.tsx | 84 ++++ .../entity_details/host_right/index.tsx | 141 +++++++ .../flyout/entity_details/mocks/index.ts | 168 ++++++++ .../entity_details/shared/common.test.tsx | 45 ++ .../flyout/entity_details/shared/common.tsx | 26 ++ .../components/anomalies_field.test.tsx | 34 ++ .../shared/components/anomalies_field.tsx | 45 ++ .../components/entity_table/columns.tsx | 75 ++++ .../components/entity_table/index.test.tsx | 94 +++++ .../shared/components/entity_table/index.tsx | 45 ++ .../shared/components/entity_table/types.ts | 54 +++ .../left_panel/left_panel_content.tsx} | 12 +- .../left_panel/left_panel_header.tsx} | 28 +- .../components/observed_entity/index.test.tsx | 43 ++ .../components/observed_entity/index.tsx} | 82 ++-- .../components/observed_entity/types.ts | 27 ++ .../flyout/entity_details/shared/constants.ts | 8 + .../user_details_left/index.tsx | 19 +- .../entity_details/user_details_left/tabs.tsx | 20 +- .../user_right/content.stories.tsx | 2 +- .../entity_details/user_right/content.tsx | 26 +- .../entity_details/user_right/header.test.tsx | 2 +- .../entity_details/user_right/header.tsx | 9 +- .../user_right/hooks/translations.ts | 54 +++ .../user_right}/hooks/use_observed_user.ts | 34 +- .../hooks/use_observed_user_items.test.ts | 45 +- .../hooks/use_observed_user_items.ts | 71 ++++ .../entity_details/user_right/index.test.tsx | 13 +- .../entity_details/user_right/index.tsx | 6 +- .../entity_details/user_right/mocks/index.ts | 68 ++- .../security_solution/public/flyout/index.tsx | 15 + .../new_user_detail/__mocks__/index.ts | 40 +- .../side_panel/new_user_detail/columns.tsx | 89 +--- .../hooks/use_observed_user_items.ts | 48 --- .../new_user_detail/managed_user.tsx | 4 +- .../managed_user_accordion.tsx | 8 +- .../new_user_detail/observed_user.test.tsx | 51 --- .../new_user_detail/risk_score_field.test.tsx | 46 -- .../new_user_detail/risk_score_field.tsx | 79 ---- .../new_user_detail/translations.ts | 50 --- .../side_panel/new_user_detail/types.ts | 27 -- .../body/renderers/host_name.test.tsx | 40 ++ .../timeline/body/renderers/host_name.tsx | 71 +++- .../translations/translations/fr-FR.json | 9 - .../translations/translations/ja-JP.json | 9 - .../translations/translations/zh-CN.json | 9 - 67 files changed, 2648 insertions(+), 860 deletions(-) create mode 100644 x-pack/plugins/security_solution/public/flyout/entity_details/host_details_left/index.test.tsx create mode 100644 x-pack/plugins/security_solution/public/flyout/entity_details/host_details_left/index.tsx create mode 100644 x-pack/plugins/security_solution/public/flyout/entity_details/host_right/content.stories.tsx create mode 100644 x-pack/plugins/security_solution/public/flyout/entity_details/host_right/content.tsx create mode 100644 x-pack/plugins/security_solution/public/flyout/entity_details/host_right/fields/basic_host_fields.tsx create mode 100644 x-pack/plugins/security_solution/public/flyout/entity_details/host_right/fields/cloud_fields.ts create mode 100644 x-pack/plugins/security_solution/public/flyout/entity_details/host_right/fields/endpoint_policy_fields.test.tsx create mode 100644 x-pack/plugins/security_solution/public/flyout/entity_details/host_right/fields/endpoint_policy_fields.tsx create mode 100644 x-pack/plugins/security_solution/public/flyout/entity_details/host_right/fields/translations.ts create mode 100644 x-pack/plugins/security_solution/public/flyout/entity_details/host_right/header.test.tsx create mode 100644 x-pack/plugins/security_solution/public/flyout/entity_details/host_right/header.tsx create mode 100644 x-pack/plugins/security_solution/public/flyout/entity_details/host_right/hooks/use_observed_host.ts create mode 100644 x-pack/plugins/security_solution/public/flyout/entity_details/host_right/hooks/use_observed_host_fields.test.ts create mode 100644 x-pack/plugins/security_solution/public/flyout/entity_details/host_right/hooks/use_observed_host_fields.ts create mode 100644 x-pack/plugins/security_solution/public/flyout/entity_details/host_right/index.test.tsx create mode 100644 x-pack/plugins/security_solution/public/flyout/entity_details/host_right/index.tsx create mode 100644 x-pack/plugins/security_solution/public/flyout/entity_details/mocks/index.ts create mode 100644 x-pack/plugins/security_solution/public/flyout/entity_details/shared/common.test.tsx create mode 100644 x-pack/plugins/security_solution/public/flyout/entity_details/shared/common.tsx create mode 100644 x-pack/plugins/security_solution/public/flyout/entity_details/shared/components/anomalies_field.test.tsx create mode 100644 x-pack/plugins/security_solution/public/flyout/entity_details/shared/components/anomalies_field.tsx create mode 100644 x-pack/plugins/security_solution/public/flyout/entity_details/shared/components/entity_table/columns.tsx create mode 100644 x-pack/plugins/security_solution/public/flyout/entity_details/shared/components/entity_table/index.test.tsx create mode 100644 x-pack/plugins/security_solution/public/flyout/entity_details/shared/components/entity_table/index.tsx create mode 100644 x-pack/plugins/security_solution/public/flyout/entity_details/shared/components/entity_table/types.ts rename x-pack/plugins/security_solution/public/flyout/entity_details/{user_details_left/content.tsx => shared/components/left_panel/left_panel_content.tsx} (70%) rename x-pack/plugins/security_solution/public/flyout/entity_details/{user_details_left/header.tsx => shared/components/left_panel/left_panel_header.tsx} (67%) create mode 100644 x-pack/plugins/security_solution/public/flyout/entity_details/shared/components/observed_entity/index.test.tsx rename x-pack/plugins/security_solution/public/{timelines/components/side_panel/new_user_detail/observed_user.tsx => flyout/entity_details/shared/components/observed_entity/index.tsx} (51%) create mode 100644 x-pack/plugins/security_solution/public/flyout/entity_details/shared/components/observed_entity/types.ts create mode 100644 x-pack/plugins/security_solution/public/flyout/entity_details/shared/constants.ts create mode 100644 x-pack/plugins/security_solution/public/flyout/entity_details/user_right/hooks/translations.ts rename x-pack/plugins/security_solution/public/{timelines/components/side_panel/new_user_detail => flyout/entity_details/user_right}/hooks/use_observed_user.ts (65%) rename x-pack/plugins/security_solution/public/{timelines/components/side_panel/new_user_detail => flyout/entity_details/user_right}/hooks/use_observed_user_items.test.ts (53%) create mode 100644 x-pack/plugins/security_solution/public/flyout/entity_details/user_right/hooks/use_observed_user_items.ts delete mode 100644 x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/hooks/use_observed_user_items.ts delete mode 100644 x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/observed_user.test.tsx delete mode 100644 x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/risk_score_field.test.tsx delete mode 100644 x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/risk_score_field.tsx diff --git a/x-pack/plugins/security_solution/common/experimental_features.ts b/x-pack/plugins/security_solution/common/experimental_features.ts index 2b34532e4e84..2c7910166b19 100644 --- a/x-pack/plugins/security_solution/common/experimental_features.ts +++ b/x-pack/plugins/security_solution/common/experimental_features.ts @@ -100,11 +100,17 @@ export const allowedExperimentalValues = Object.freeze({ assistantModelEvaluation: false, /* - * Enables the new user details flyout displayed on the Alerts page and timeline. + * Enables the new user details flyout displayed on the Alerts table. * **/ newUserDetailsFlyout: false, + /* + * Enables the new host details flyout displayed on the Alerts table. + * + **/ + newHostDetailsFlyout: false, + /** * Enable risk engine client and initialisation of datastream, component templates and mappings */ diff --git a/x-pack/plugins/security_solution/common/utility_types.ts b/x-pack/plugins/security_solution/common/utility_types.ts index 1a85597e84e7..aaf1dfafb657 100644 --- a/x-pack/plugins/security_solution/common/utility_types.ts +++ b/x-pack/plugins/security_solution/common/utility_types.ts @@ -71,3 +71,10 @@ export const assertUnreachable = ( ): never => { throw new Error(`${message}: ${x}`); }; + +type Without = { [P in Exclude]?: never }; +/** + * The XOR (exclusive OR) allows to ensure that a variable conforms to only one of several possible types. + * Read more: https://medium.com/@aeron169/building-a-xor-type-in-typescript-5f4f7e709a9d + */ +export type XOR = T | U extends object ? (Without & U) | (Without & T) : T | U; diff --git a/x-pack/plugins/security_solution/public/common/mock/storybook_providers.tsx b/x-pack/plugins/security_solution/public/common/mock/storybook_providers.tsx index 6fb3ca1ff0f5..40b9ce71419d 100644 --- a/x-pack/plugins/security_solution/public/common/mock/storybook_providers.tsx +++ b/x-pack/plugins/security_solution/public/common/mock/storybook_providers.tsx @@ -21,6 +21,7 @@ import { mockGlobalState } from './global_state'; import { SUB_PLUGINS_REDUCER } from './utils'; import { createSecuritySolutionStorageMock } from './mock_local_storage'; import type { StartServices } from '../../types'; +import { ReactQueryClientProvider } from '../containers/query_client/query_client_provider'; export const kibanaObservable = new BehaviorSubject({} as unknown as StartServices); @@ -106,13 +107,15 @@ export const StorybookProviders: React.FC = ({ children }) => { - Promise.resolve([])}> - - ({ eui: euiLightVars, darkMode: false })}> - {children} - - - + + Promise.resolve([])}> + + ({ eui: euiLightVars, darkMode: false })}> + {children} + + + + diff --git a/x-pack/plugins/security_solution/public/entity_analytics/components/entity_details_flyout/index.tsx b/x-pack/plugins/security_solution/public/entity_analytics/components/entity_details_flyout/index.tsx index 428f98530d55..64c79bfdb77f 100644 --- a/x-pack/plugins/security_solution/public/entity_analytics/components/entity_details_flyout/index.tsx +++ b/x-pack/plugins/security_solution/public/entity_analytics/components/entity_details_flyout/index.tsx @@ -7,14 +7,14 @@ import React from 'react'; import { FormattedMessage } from '@kbn/i18n-react'; +import { EntityDetailsLeftPanelTab } from '../../../flyout/entity_details/shared/components/left_panel/left_panel_header'; import { PREFIX } from '../../../flyout/shared/test_ids'; -import { UserDetailsLeftPanelTab } from '../../../flyout/entity_details/user_details_left/tabs'; import { RiskInputsTab } from './tabs/risk_inputs'; export const RISK_INPUTS_TAB_TEST_ID = `${PREFIX}RiskInputsTab` as const; export const getRiskInputTab = (alertIds: string[]) => ({ - id: UserDetailsLeftPanelTab.RISK_INPUTS, + id: EntityDetailsLeftPanelTab.RISK_INPUTS, 'data-test-subj': RISK_INPUTS_TAB_TEST_ID, name: ( ); + +jest.mock('../../../common/components/visualization_actions/visualization_embeddable', () => ({ + VisualizationEmbeddable: (props: VisualizationEmbeddableProps) => + mockVisualizationEmbeddable(props), +})); describe('RiskSummary', () => { + beforeEach(() => { + mockVisualizationEmbeddable.mockClear(); + }); + it('renders risk summary table', () => { const { getByTestId } = render( {}} /> @@ -34,7 +52,7 @@ describe('RiskSummary', () => { const { getByTestId } = render( {}} /> @@ -47,7 +65,7 @@ describe('RiskSummary', () => { const { getByTestId } = render( {}} /> @@ -61,7 +79,7 @@ describe('RiskSummary', () => { const { getByTestId } = render( {}} /> @@ -70,4 +88,52 @@ describe('RiskSummary', () => { expect(getByTestId('risk-summary-updatedAt')).toHaveTextContent('Updated Nov 8, 1989'); }); + + it('builds lens attributes for host risk score', () => { + render( + + {}} + /> + + ); + + const lensAttributes: LensAttributes = + mockVisualizationEmbeddable.mock.calls[0][0].lensAttributes; + const datasourceLayers = Object.values(lensAttributes.state.datasourceStates.formBased.layers); + const firstColumn = Object.values(datasourceLayers[0].columns)[0]; + + expect(lensAttributes.state.query.query).toEqual('host.name: test'); + expect(firstColumn).toEqual( + expect.objectContaining({ + sourceField: 'host.risk.calculated_score_norm', + }) + ); + }); + + it('builds lens attributes for user risk score', () => { + render( + + {}} + /> + + ); + + const lensAttributes: LensAttributes = + mockVisualizationEmbeddable.mock.calls[0][0].lensAttributes; + const datasourceLayers = Object.values(lensAttributes.state.datasourceStates.formBased.layers); + const firstColumn = Object.values(datasourceLayers[0].columns)[0]; + + expect(lensAttributes.state.query.query).toEqual('user.name: test'); + expect(firstColumn).toEqual( + expect.objectContaining({ + sourceField: 'user.risk.calculated_score_norm', + }) + ); + }); }); diff --git a/x-pack/plugins/security_solution/public/entity_analytics/components/risk_summary_flyout/risk_summary.tsx b/x-pack/plugins/security_solution/public/entity_analytics/components/risk_summary_flyout/risk_summary.tsx index 50259cd6ca13..c8d4f093fdc4 100644 --- a/x-pack/plugins/security_solution/public/entity_analytics/components/risk_summary_flyout/risk_summary.tsx +++ b/x-pack/plugins/security_solution/public/entity_analytics/components/risk_summary_flyout/risk_summary.tsx @@ -21,7 +21,11 @@ import { css } from '@emotion/react'; import { FormattedMessage } from '@kbn/i18n-react'; import { euiThemeVars } from '@kbn/ui-theme'; import { i18n } from '@kbn/i18n'; -import { UserDetailsLeftPanelTab } from '../../../flyout/entity_details/user_details_left/tabs'; +import { EntityDetailsLeftPanelTab } from '../../../flyout/entity_details/shared/components/left_panel/left_panel_header'; +import type { + HostRiskScore, + UserRiskScore, +} from '../../../../common/search_strategy/security_solution/risk_score'; import { InspectButton, InspectButtonContainer } from '../../../common/components/inspect'; import { ONE_WEEK_IN_HOURS } from '../../../timelines/components/side_panel/new_user_detail/constants'; import { FormattedRelativePreferenceDate } from '../../../common/components/formatted_date'; @@ -31,10 +35,10 @@ import { ExpandablePanel } from '../../../flyout/shared/components/expandable_pa import type { RiskScoreState } from '../../api/hooks/use_risk_score'; import { getRiskScoreSummaryAttributes } from '../../lens_attributes/risk_score_summary'; -export interface RiskSummaryProps { - riskScoreData: RiskScoreState; +export interface RiskSummaryProps { + riskScoreData: RiskScoreState; queryId: string; - openDetailsPanel: (tab: UserDetailsLeftPanelTab) => void; + openDetailsPanel: (tab: EntityDetailsLeftPanelTab) => void; } interface TableItem { @@ -44,203 +48,229 @@ interface TableItem { const LENS_VISUALIZATION_HEIGHT = 126; // Static height in pixels specified by design const LAST_30_DAYS = { from: 'now-30d', to: 'now' }; -export const RiskSummary = React.memo( - ({ riskScoreData, queryId, openDetailsPanel }: RiskSummaryProps) => { - const { data: userRisk } = riskScoreData; - const userRiskData = userRisk && userRisk.length > 0 ? userRisk[0] : undefined; - const { euiTheme } = useEuiTheme(); - - const lensAttributes = useMemo(() => { - return getRiskScoreSummaryAttributes({ - severity: userRiskData?.user?.risk?.calculated_level, - query: `user.name: ${userRiskData?.user?.name}`, - spaceId: 'default', - riskEntity: RiskScoreEntity.user, - }); - }, [userRiskData]); - - const columns: Array> = useMemo( - () => [ - { - field: 'category', - name: ( +function isUserRiskData( + riskData: UserRiskScore | HostRiskScore | undefined +): riskData is UserRiskScore { + return !!riskData && (riskData as UserRiskScore).user !== undefined; +} + +const getEntityData = (riskData: UserRiskScore | HostRiskScore | undefined) => { + if (!riskData) { + return; + } + + if (isUserRiskData(riskData)) { + return riskData.user; + } + + return riskData.host; +}; + +const RiskSummaryComponent = ({ + riskScoreData, + queryId, + openDetailsPanel, +}: RiskSummaryProps) => { + const { data } = riskScoreData; + const riskData = data && data.length > 0 ? data[0] : undefined; + const entityData = getEntityData(riskData); + const { euiTheme } = useEuiTheme(); + + const lensAttributes = useMemo(() => { + const entityName = entityData?.name ?? ''; + const fieldName = isUserRiskData(riskData) ? 'user.name' : 'host.name'; + + return getRiskScoreSummaryAttributes({ + severity: entityData?.risk?.calculated_level, + query: `${fieldName}: ${entityName}`, + spaceId: 'default', + riskEntity: isUserRiskData(riskData) ? RiskScoreEntity.user : RiskScoreEntity.host, + }); + }, [entityData?.name, entityData?.risk?.calculated_level, riskData]); + + const columns: Array> = useMemo( + () => [ + { + field: 'category', + name: ( + + ), + truncateText: false, + mobileOptions: { show: true }, + sortable: true, + }, + { + field: 'count', + name: ( + + ), + truncateText: false, + mobileOptions: { show: true }, + sortable: true, + dataType: 'number', + }, + ], + [] + ); + + const xsFontSize = useEuiFontSize('xxs').fontSize; + + const items: TableItem[] = useMemo( + () => [ + { + category: i18n.translate('xpack.securitySolution.flyout.entityDetails.alertsGroupLabel', { + defaultMessage: 'Alerts', + }), + count: entityData?.risk.inputs?.length ?? 0, + }, + ], + [entityData?.risk.inputs?.length] + ); + + return ( + +

- ), - truncateText: false, - mobileOptions: { show: true }, - sortable: true, - }, - { - field: 'count', - name: ( +

+ + } + extraAction={ + + {riskData && ( + ), + }} /> - ), - truncateText: false, - mobileOptions: { show: true }, - sortable: true, - dataType: 'number', - }, - ], - [] - ); - - const xsFontSize = useEuiFontSize('xxs').fontSize; - - const items: TableItem[] = useMemo( - () => [ - { - category: i18n.translate('xpack.securitySolution.flyout.entityDetails.alertsGroupLabel', { - defaultMessage: 'Alerts', - }), - count: userRiskData?.user.risk.inputs?.length ?? 0, - }, - ], - [userRiskData?.user.risk.inputs?.length] - ); - - return ( - -

- -

- - } - extraAction={ - - {userRiskData && ( - - ), - }} - /> - )} - - } - > - + )} +
+ } + > + - + ), + link: { + callback: () => openDetailsPanel(EntityDetailsLeftPanelTab.RISK_INPUTS), + tooltip: ( ), - link: { - callback: () => openDetailsPanel(UserDetailsLeftPanelTab.RISK_INPUTS), - tooltip: ( - + + +
+ {riskData && ( + + } /> - ), - }, - iconType: 'arrowStart', - }} - expand={{ - expandable: false, - }} - > - - + )} +
+
+ +
- {userRiskData && ( - - } - /> - )} -
-
- -
-
- - } - /> -
- + } />
-
-
-
-
- -
- ); - } -); + + + + +
+ + + + ); +}; + +export const RiskSummary = React.memo(RiskSummaryComponent); RiskSummary.displayName = 'RiskSummary'; diff --git a/x-pack/plugins/security_solution/public/explore/hosts/containers/hosts/details/index.tsx b/x-pack/plugins/security_solution/public/explore/hosts/containers/hosts/details/index.tsx index f6ea1ff14a26..490891732abd 100644 --- a/x-pack/plugins/security_solution/public/explore/hosts/containers/hosts/details/index.tsx +++ b/x-pack/plugins/security_solution/public/explore/hosts/containers/hosts/details/index.tsx @@ -42,7 +42,7 @@ export const useHostDetails = ({ id = ID, skip = false, startDate, -}: UseHostDetails): [boolean, HostDetailsArgs] => { +}: UseHostDetails): [boolean, HostDetailsArgs, inputsModel.Refetch] => { const { loading, result: response, @@ -91,5 +91,5 @@ export const useHostDetails = ({ } }, [hostDetailsRequest, search, skip]); - return [loading, hostDetailsResponse]; + return [loading, hostDetailsResponse, refetch]; }; diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/host_details_left/index.test.tsx b/x-pack/plugins/security_solution/public/flyout/entity_details/host_details_left/index.test.tsx new file mode 100644 index 000000000000..82cf0f8ff9f5 --- /dev/null +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/host_details_left/index.test.tsx @@ -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 { RISK_INPUTS_TAB_TEST_ID } from '../../../entity_analytics/components/entity_details_flyout'; +import { render } from '@testing-library/react'; +import React from 'react'; +import { HostDetailsPanel } from '.'; +import { TestProviders } from '../../../common/mock'; + +describe('HostDetailsPanel', () => { + it('render risk inputs panel', () => { + const { getByTestId } = render( + , + { wrapper: TestProviders } + ); + expect(getByTestId(RISK_INPUTS_TAB_TEST_ID)).toBeInTheDocument(); + }); + + it("doesn't render risk inputs panel when no alerts ids are provided", () => { + const { queryByTestId } = render( + , + { wrapper: TestProviders } + ); + expect(queryByTestId(RISK_INPUTS_TAB_TEST_ID)).not.toBeInTheDocument(); + }); +}); diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/host_details_left/index.tsx b/x-pack/plugins/security_solution/public/flyout/entity_details/host_details_left/index.tsx new file mode 100644 index 000000000000..3214dec23bdd --- /dev/null +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/host_details_left/index.tsx @@ -0,0 +1,52 @@ +/* + * 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, { useMemo } from 'react'; +import type { FlyoutPanelProps } from '@kbn/expandable-flyout'; +import { getRiskInputTab } from '../../../entity_analytics/components/entity_details_flyout'; +import { LeftPanelContent } from '../shared/components/left_panel/left_panel_content'; +import { + EntityDetailsLeftPanelTab, + LeftPanelHeader, +} from '../shared/components/left_panel/left_panel_header'; + +interface RiskInputsParam { + alertIds: string[]; +} + +export interface HostDetailsPanelProps extends Record { + riskInputs: RiskInputsParam; +} +export interface HostDetailsExpandableFlyoutProps extends FlyoutPanelProps { + key: 'host_details'; + params: HostDetailsPanelProps; +} +export const HostDetailsPanelKey: HostDetailsExpandableFlyoutProps['key'] = 'host_details'; + +export const HostDetailsPanel = ({ riskInputs }: HostDetailsPanelProps) => { + // Temporary implementation while Host details left panel don't have Asset tabs + const [tabs, selectedTabId, setSelectedTabId] = useMemo(() => { + return [ + riskInputs.alertIds.length > 0 ? [getRiskInputTab(riskInputs.alertIds)] : [], + EntityDetailsLeftPanelTab.RISK_INPUTS, + () => {}, + ]; + }, [riskInputs.alertIds]); + + return ( + <> + + + + ); +}; + +HostDetailsPanel.displayName = 'HostDetailsPanel'; diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/content.stories.tsx b/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/content.stories.tsx new file mode 100644 index 000000000000..9bea5cb2a4ac --- /dev/null +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/content.stories.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 from 'react'; +import { storiesOf } from '@storybook/react'; +import { EuiFlyout } from '@elastic/eui'; +import type { ExpandableFlyoutContextValue } from '@kbn/expandable-flyout/src/context'; +import { ExpandableFlyoutContext } from '@kbn/expandable-flyout/src/context'; +import { StorybookProviders } from '../../../common/mock/storybook_providers'; +import { mockRiskScoreState } from '../../../timelines/components/side_panel/new_user_detail/__mocks__'; +import { HostPanelContent } from './content'; +import { mockObservedHostData } from '../mocks'; + +const flyoutContextValue = { + openLeftPanel: () => window.alert('openLeftPanel called'), + panels: {}, +} as unknown as ExpandableFlyoutContextValue; + +const riskScoreData = { ...mockRiskScoreState, data: [] }; + +storiesOf('Components/HostPanelContent', module) + .addDecorator((storyFn) => ( + + + {}}> + {storyFn()} + + + + )) + .add('default', () => ( + {}} + /> + )) + .add('no observed data', () => ( + {}} + /> + )) + .add('loading', () => ( + {}} + /> + )); diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/content.tsx b/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/content.tsx new file mode 100644 index 000000000000..eb7d5f3fda26 --- /dev/null +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/content.tsx @@ -0,0 +1,64 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { EuiHorizontalRule } from '@elastic/eui'; + +import React from 'react'; +import { RiskSummary } from '../../../entity_analytics/components/risk_summary_flyout/risk_summary'; +import type { RiskScoreState } from '../../../entity_analytics/api/hooks/use_risk_score'; +import type { RiskScoreEntity, HostItem } from '../../../../common/search_strategy'; +import { FlyoutBody } from '../../shared/components/flyout_body'; +import { ObservedEntity } from '../shared/components/observed_entity'; +import { HOST_PANEL_OBSERVED_HOST_QUERY_ID, HOST_PANEL_RISK_SCORE_QUERY_ID } from '.'; +import type { ObservedEntityData } from '../shared/components/observed_entity/types'; +import { useObservedHostFields } from './hooks/use_observed_host_fields'; +import type { EntityDetailsLeftPanelTab } from '../shared/components/left_panel/left_panel_header'; + +interface HostPanelContentProps { + observedHost: ObservedEntityData; + riskScoreState: RiskScoreState; + contextID: string; + scopeId: string; + isDraggable: boolean; + openDetailsPanel: (tab: EntityDetailsLeftPanelTab) => void; +} + +export const HostPanelContent = ({ + observedHost, + riskScoreState, + contextID, + scopeId, + isDraggable, + openDetailsPanel, +}: HostPanelContentProps) => { + const observedFields = useObservedHostFields(observedHost); + + return ( + + {riskScoreState.isModuleEnabled && riskScoreState.data?.length !== 0 && ( + <> + { + + } + + + )} + + + ); +}; diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/fields/basic_host_fields.tsx b/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/fields/basic_host_fields.tsx new file mode 100644 index 000000000000..1229a08e7c95 --- /dev/null +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/fields/basic_host_fields.tsx @@ -0,0 +1,80 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; + +import { getEmptyTagValue } from '../../../../common/components/empty_value'; +import type { HostItem } from '../../../../../common/search_strategy'; +import { FormattedRelativePreferenceDate } from '../../../../common/components/formatted_date'; +import { NetworkDetailsLink } from '../../../../common/components/links'; +import * as i18n from './translations'; +import type { ObservedEntityData } from '../../shared/components/observed_entity/types'; +import type { EntityTableRows } from '../../shared/components/entity_table/types'; + +export const basicHostFields: EntityTableRows> = [ + { + label: i18n.HOST_ID, + getValues: (hostData: ObservedEntityData) => hostData.details.host?.id, + field: 'host.id', + }, + { + label: i18n.FIRST_SEEN, + render: (hostData: ObservedEntityData) => + hostData.firstSeen.date ? ( + + ) : ( + getEmptyTagValue() + ), + }, + { + label: i18n.LAST_SEEN, + render: (hostData: ObservedEntityData) => + hostData.lastSeen.date ? ( + + ) : ( + getEmptyTagValue() + ), + }, + { + label: i18n.IP_ADDRESSES, + field: 'host.ip', + getValues: (hostData: ObservedEntityData) => hostData.details.host?.ip, + renderField: (ip: string) => { + return ; + }, + }, + { + label: i18n.MAC_ADDRESSES, + getValues: (hostData: ObservedEntityData) => hostData.details.host?.mac, + field: 'host.mac', + }, + { + label: i18n.PLATFORM, + getValues: (hostData: ObservedEntityData) => hostData.details.host?.os?.platform, + field: 'host.os.platform', + }, + { + label: i18n.OS, + getValues: (hostData: ObservedEntityData) => hostData.details.host?.os?.name, + field: 'host.os.name', + }, + { + label: i18n.FAMILY, + getValues: (hostData: ObservedEntityData) => hostData.details.host?.os?.family, + field: 'host.os.family', + }, + { + label: i18n.VERSION, + getValues: (hostData: ObservedEntityData) => hostData.details.host?.os?.version, + field: 'host.os.version', + }, + { + label: i18n.ARCHITECTURE, + getValues: (hostData: ObservedEntityData) => hostData.details.host?.architecture, + field: 'host.architecture', + }, +]; diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/fields/cloud_fields.ts b/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/fields/cloud_fields.ts new file mode 100644 index 000000000000..c4ea144a7db0 --- /dev/null +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/fields/cloud_fields.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 type { HostItem } from '../../../../../common/search_strategy'; +import type { EntityTableRows } from '../../shared/components/entity_table/types'; +import type { ObservedEntityData } from '../../shared/components/observed_entity/types'; +import * as i18n from './translations'; + +export const cloudFields: EntityTableRows> = [ + { + label: i18n.CLOUD_PROVIDER, + getValues: (hostData: ObservedEntityData) => hostData.details.cloud?.provider, + field: 'cloud.provider', + }, + { + label: i18n.REGION, + getValues: (hostData: ObservedEntityData) => hostData.details.cloud?.region, + field: 'cloud.region', + }, + { + label: i18n.INSTANCE_ID, + getValues: (hostData: ObservedEntityData) => hostData.details.cloud?.instance?.id, + field: 'cloud.instance.id', + }, + { + label: i18n.MACHINE_TYPE, + getValues: (hostData: ObservedEntityData) => hostData.details.cloud?.machine?.type, + field: 'cloud.machine.type', + }, +]; diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/fields/endpoint_policy_fields.test.tsx b/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/fields/endpoint_policy_fields.test.tsx new file mode 100644 index 000000000000..a8ba12de451e --- /dev/null +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/fields/endpoint_policy_fields.test.tsx @@ -0,0 +1,61 @@ +/* + * 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 { TestProviders } from '../../../../common/mock'; +import { render } from '@testing-library/react'; +import React from 'react'; +import { mockObservedHostData } from '../../mocks'; +import { policyFields } from './endpoint_policy_fields'; + +const TestWrapper = ({ el }: { el: JSX.Element | undefined }) => <>{el}; + +jest.mock( + '../../../../management/hooks/response_actions/use_get_endpoint_pending_actions_summary', + () => { + const original = jest.requireActual( + '../../../../management/hooks/response_actions/use_get_endpoint_pending_actions_summary' + ); + return { + ...original, + useGetEndpointPendingActionsSummary: () => ({ + pendingActions: [], + isLoading: false, + isError: false, + isTimeout: false, + fetch: jest.fn(), + }), + }; + } +); + +describe('Endpoint Policy Fields', () => { + it('renders policy name', () => { + const policyName = policyFields[0]; + + const { container } = render(); + + expect(container).toHaveTextContent('policy-name'); + }); + + it('renders policy status', () => { + const policyStatus = policyFields[1]; + + const { container } = render(); + + expect(container).toHaveTextContent('failure'); + }); + + it('renders agent status', () => { + const agentStatus = policyFields[3]; + + const { container } = render(, { + wrapper: TestProviders, + }); + + expect(container).toHaveTextContent('Healthy'); + }); +}); diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/fields/endpoint_policy_fields.tsx b/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/fields/endpoint_policy_fields.tsx new file mode 100644 index 000000000000..fd9b8c744a7b --- /dev/null +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/fields/endpoint_policy_fields.tsx @@ -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 React from 'react'; +import { EuiHealth } from '@elastic/eui'; + +import type { EntityTableRows } from '../../shared/components/entity_table/types'; +import type { ObservedEntityData } from '../../shared/components/observed_entity/types'; +import { EndpointAgentStatus } from '../../../../common/components/endpoint/endpoint_agent_status'; +import { getEmptyTagValue } from '../../../../common/components/empty_value'; +import type { HostItem } from '../../../../../common/search_strategy'; +import { HostPolicyResponseActionStatus } from '../../../../../common/search_strategy'; +import * as i18n from './translations'; + +export const policyFields: EntityTableRows> = [ + { + label: i18n.ENDPOINT_POLICY, + render: (hostData: ObservedEntityData) => { + const appliedPolicy = hostData.details.endpoint?.hostInfo?.metadata.Endpoint.policy.applied; + return appliedPolicy?.name ? <>{appliedPolicy.name} : getEmptyTagValue(); + }, + isVisible: (hostData: ObservedEntityData) => hostData.details.endpoint != null, + }, + { + label: i18n.POLICY_STATUS, + render: (hostData: ObservedEntityData) => { + const appliedPolicy = hostData.details.endpoint?.hostInfo?.metadata.Endpoint.policy.applied; + const policyColor = + appliedPolicy?.status === HostPolicyResponseActionStatus.failure + ? 'danger' + : appliedPolicy?.status; + + return appliedPolicy?.status ? ( + + {appliedPolicy?.status} + + ) : ( + getEmptyTagValue() + ); + }, + isVisible: (hostData: ObservedEntityData) => hostData.details.endpoint != null, + }, + { + label: i18n.SENSORVERSION, + getValues: (hostData: ObservedEntityData) => + hostData.details.endpoint?.hostInfo?.metadata.agent.version + ? [hostData.details.endpoint?.hostInfo?.metadata.agent.version] + : undefined, + field: 'agent.version', + isVisible: (hostData: ObservedEntityData) => hostData.details.endpoint != null, + }, + { + label: i18n.FLEET_AGENT_STATUS, + render: (hostData: ObservedEntityData) => + hostData.details.endpoint?.hostInfo ? ( + + ) : ( + getEmptyTagValue() + ), + isVisible: (hostData: ObservedEntityData) => hostData.details.endpoint != null, + }, +]; diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/fields/translations.ts b/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/fields/translations.ts new file mode 100644 index 000000000000..dac45a3a6202 --- /dev/null +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/fields/translations.ts @@ -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 { i18n } from '@kbn/i18n'; + +export const HOST_ID = i18n.translate( + 'xpack.securitySolution.flyout.entityDetails.host.hostIdTitle', + { + defaultMessage: 'Host ID', + } +); + +export const FIRST_SEEN = i18n.translate( + 'xpack.securitySolution.flyout.entityDetails.host.firstSeenTitle', + { + defaultMessage: 'First seen', + } +); + +export const LAST_SEEN = i18n.translate( + 'xpack.securitySolution.flyout.entityDetails.host.lastSeenTitle', + { + defaultMessage: 'Last seen', + } +); + +export const IP_ADDRESSES = i18n.translate( + 'xpack.securitySolution.flyout.entityDetails.host.ipAddressesTitle', + { + defaultMessage: 'IP addresses', + } +); + +export const MAC_ADDRESSES = i18n.translate( + 'xpack.securitySolution.flyout.entityDetails.host.macAddressesTitle', + { + defaultMessage: 'MAC addresses', + } +); + +export const PLATFORM = i18n.translate( + 'xpack.securitySolution.flyout.entityDetails.host.platformTitle', + { + defaultMessage: 'Platform', + } +); + +export const OS = i18n.translate('xpack.securitySolution.flyout.entityDetails.host.osTitle', { + defaultMessage: 'Operating system', +}); + +export const FAMILY = i18n.translate( + 'xpack.securitySolution.flyout.entityDetails.host.familyTitle', + { + defaultMessage: 'Family', + } +); + +export const VERSION = i18n.translate( + 'xpack.securitySolution.flyout.entityDetails.host.versionLabel', + { + defaultMessage: 'Version', + } +); + +export const ARCHITECTURE = i18n.translate( + 'xpack.securitySolution.flyout.entityDetails.host.architectureLabel', + { + defaultMessage: 'Architecture', + } +); + +export const CLOUD_PROVIDER = i18n.translate( + 'xpack.securitySolution.flyout.entityDetails.host.cloudProviderTitle', + { + defaultMessage: 'Cloud provider', + } +); + +export const REGION = i18n.translate( + 'xpack.securitySolution.flyout.entityDetails.host.regionTitle', + { + defaultMessage: 'Region', + } +); + +export const INSTANCE_ID = i18n.translate( + 'xpack.securitySolution.flyout.entityDetails.host.instanceIdTitle', + { + defaultMessage: 'Instance ID', + } +); + +export const MACHINE_TYPE = i18n.translate( + 'xpack.securitySolution.flyout.entityDetails.host.machineTypeTitle', + { + defaultMessage: 'Machine type', + } +); + +export const ENDPOINT_POLICY = i18n.translate( + 'xpack.securitySolution.flyout.entityDetails.host.endpoint.endpointPolicy', + { + defaultMessage: 'Endpoint integration policy', + } +); + +export const POLICY_STATUS = i18n.translate( + 'xpack.securitySolution.flyout.entityDetails.host.endpoint.policyStatus', + { + defaultMessage: 'Policy Status', + } +); + +export const SENSORVERSION = i18n.translate( + 'xpack.securitySolution.flyout.entityDetails.host.endpoint.sensorversion', + { + defaultMessage: 'Endpoint version', + } +); + +export const FLEET_AGENT_STATUS = i18n.translate( + 'xpack.securitySolution.flyout.entityDetails.host.endpoint.fleetAgentStatus', + { + defaultMessage: 'Agent status', + } +); diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/header.test.tsx b/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/header.test.tsx new file mode 100644 index 000000000000..418ec64cb670 --- /dev/null +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/header.test.tsx @@ -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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { render } from '@testing-library/react'; +import React from 'react'; +import { TestProviders } from '../../../common/mock'; +import { HostPanelHeader } from './header'; +import { mockObservedHostData } from '../mocks'; + +const mockProps = { + hostName: 'test', + observedHost: mockObservedHostData, +}; + +jest.mock('../../../common/components/visualization_actions/visualization_embeddable'); + +describe('HostPanelHeader', () => { + it('renders', () => { + const { getByTestId } = render( + + + + ); + + expect(getByTestId('host-panel-header')).toBeInTheDocument(); + }); + + it('renders observed date', () => { + const futureDay = '2989-03-07T20:00:00.000Z'; + const { getByTestId } = render( + + + + ); + + expect(getByTestId('host-panel-header-lastSeen').textContent).toContain('Mar 7, 2989'); + }); + + it('renders observed badge when lastSeen is defined', () => { + const { getByTestId } = render( + + + + ); + + expect(getByTestId('host-panel-header-observed-badge')).toBeInTheDocument(); + }); + + it('does not render observed badge when lastSeen date is undefined', () => { + const { queryByTestId } = render( + + + + ); + + expect(queryByTestId('host-panel-header-observed-badge')).not.toBeInTheDocument(); + }); +}); diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/header.tsx b/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/header.tsx new file mode 100644 index 000000000000..e8785a92acb6 --- /dev/null +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/header.tsx @@ -0,0 +1,67 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { EuiSpacer, EuiBadge, EuiText, EuiFlexItem, EuiFlexGroup } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n-react'; +import React, { useMemo } from 'react'; +import { SecurityPageName } from '@kbn/security-solution-navigation'; +import type { HostItem } from '../../../../common/search_strategy'; +import { getHostDetailsUrl } from '../../../common/components/link_to'; +import { SecuritySolutionLinkAnchor } from '../../../common/components/links'; +import { PreferenceFormattedDate } from '../../../common/components/formatted_date'; +import { FlyoutHeader } from '../../shared/components/flyout_header'; +import { FlyoutTitle } from '../../shared/components/flyout_title'; +import type { ObservedEntityData } from '../shared/components/observed_entity/types'; + +interface HostPanelHeaderProps { + hostName: string; + observedHost: ObservedEntityData; +} + +export const HostPanelHeader = ({ hostName, observedHost }: HostPanelHeaderProps) => { + const lastSeenDate = useMemo( + () => observedHost.lastSeen.date && new Date(observedHost.lastSeen.date), + [observedHost.lastSeen.date] + ); + + return ( + + + + + {lastSeenDate && } + + + + + + + + + + + + {observedHost.lastSeen.date && ( + + + + )} + + + + + + ); +}; diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/hooks/use_observed_host.ts b/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/hooks/use_observed_host.ts new file mode 100644 index 000000000000..980407b03464 --- /dev/null +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/hooks/use_observed_host.ts @@ -0,0 +1,71 @@ +/* + * 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 { useHostDetails } from '../../../../explore/hosts/containers/hosts/details'; +import { useFirstLastSeen } from '../../../../common/containers/use_first_last_seen'; +import { useGlobalTime } from '../../../../common/containers/use_global_time'; +import { useSourcererDataView } from '../../../../common/containers/sourcerer'; +import type { HostItem } from '../../../../../common/search_strategy'; +import { Direction, NOT_EVENT_KIND_ASSET_FILTER } from '../../../../../common/search_strategy'; +import { HOST_PANEL_OBSERVED_HOST_QUERY_ID, HOST_PANEL_RISK_SCORE_QUERY_ID } from '..'; +import { useQueryInspector } from '../../../../common/components/page/manage_query'; +import type { ObservedEntityData } from '../../shared/components/observed_entity/types'; + +export const useObservedHost = ( + hostName: string +): Omit, 'anomalies'> => { + const { to, from, isInitializing, setQuery, deleteQuery } = useGlobalTime(); + const { selectedPatterns } = useSourcererDataView(); + + const [isLoading, { hostDetails, inspect: inspectObservedHost }, refetch] = useHostDetails({ + endDate: to, + hostName, + indexNames: selectedPatterns, + id: HOST_PANEL_RISK_SCORE_QUERY_ID, + skip: isInitializing, + startDate: from, + }); + + useQueryInspector({ + deleteQuery, + inspect: inspectObservedHost, + loading: isLoading, + queryId: HOST_PANEL_OBSERVED_HOST_QUERY_ID, + refetch, + setQuery, + }); + + const [loadingFirstSeen, { firstSeen }] = useFirstLastSeen({ + field: 'host.name', + value: hostName, + defaultIndex: selectedPatterns, + order: Direction.asc, + filterQuery: NOT_EVENT_KIND_ASSET_FILTER, + }); + + const [loadingLastSeen, { lastSeen }] = useFirstLastSeen({ + field: 'host.name', + value: hostName, + defaultIndex: selectedPatterns, + order: Direction.desc, + filterQuery: NOT_EVENT_KIND_ASSET_FILTER, + }); + + return useMemo( + () => ({ + details: hostDetails, + isLoading: isLoading || loadingLastSeen || loadingFirstSeen, + firstSeen: { + date: firstSeen, + isLoading: loadingFirstSeen, + }, + lastSeen: { date: lastSeen, isLoading: loadingLastSeen }, + }), + [firstSeen, hostDetails, isLoading, lastSeen, loadingFirstSeen, loadingLastSeen] + ); +}; diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/hooks/use_observed_host_fields.test.ts b/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/hooks/use_observed_host_fields.test.ts new file mode 100644 index 000000000000..ea37bf40bfee --- /dev/null +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/hooks/use_observed_host_fields.test.ts @@ -0,0 +1,143 @@ +/* + * 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 { renderHook } from '@testing-library/react-hooks'; +import { useObservedHostFields } from './use_observed_host_fields'; +import { TestProviders } from '@kbn/timelines-plugin/public/mock'; +import { mockObservedHostData } from '../../mocks'; + +describe('useManagedUserItems', () => { + it('returns managed user items for Entra user', () => { + const { result } = renderHook(() => useObservedHostFields(mockObservedHostData), { + wrapper: TestProviders, + }); + + expect(result.current).toMatchInlineSnapshot(` + Array [ + Object { + "field": "host.id", + "getValues": [Function], + "label": "Host ID", + }, + Object { + "label": "First seen", + "render": [Function], + }, + Object { + "label": "Last seen", + "render": [Function], + }, + Object { + "field": "host.ip", + "getValues": [Function], + "label": "IP addresses", + "renderField": [Function], + }, + Object { + "field": "host.mac", + "getValues": [Function], + "label": "MAC addresses", + }, + Object { + "field": "host.os.platform", + "getValues": [Function], + "label": "Platform", + }, + Object { + "field": "host.os.name", + "getValues": [Function], + "label": "Operating system", + }, + Object { + "field": "host.os.family", + "getValues": [Function], + "label": "Family", + }, + Object { + "field": "host.os.version", + "getValues": [Function], + "label": "Version", + }, + Object { + "field": "host.architecture", + "getValues": [Function], + "label": "Architecture", + }, + Object { + "isVisible": [Function], + "label": "Max anomaly score by job", + "render": [Function], + }, + Object { + "field": "cloud.provider", + "getValues": [Function], + "label": "Cloud provider", + }, + Object { + "field": "cloud.region", + "getValues": [Function], + "label": "Region", + }, + Object { + "field": "cloud.instance.id", + "getValues": [Function], + "label": "Instance ID", + }, + Object { + "field": "cloud.machine.type", + "getValues": [Function], + "label": "Machine type", + }, + Object { + "isVisible": [Function], + "label": "Endpoint integration policy", + "render": [Function], + }, + Object { + "isVisible": [Function], + "label": "Policy Status", + "render": [Function], + }, + Object { + "field": "agent.version", + "getValues": [Function], + "isVisible": [Function], + "label": "Endpoint version", + }, + Object { + "isVisible": [Function], + "label": "Agent status", + "render": [Function], + }, + ] + `); + + expect( + result.current.map(({ getValues }) => getValues && getValues(mockObservedHostData)) + ).toEqual([ + ['host-id'], + undefined, // First seen doesn't implement getValues + undefined, // Last seen doesn't implement getValues + ['host-ip'], + ['host-mac'], + ['host-platform'], + ['os-name'], + ['host-family'], + ['host-version'], + ['host-architecture'], + undefined, // Max anomaly score by job doesn't implement getValues + ['cloud-provider'], + ['cloud-region'], + ['cloud-instance-id'], + ['cloud-machine-type'], + undefined, // Endpoint integration policy doesn't implement getValues + undefined, // Policy Status doesn't implement getValues + ['endpoint-agent-version'], + undefined, // Agent status doesn't implement getValues + ]); + }); +}); diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/hooks/use_observed_host_fields.ts b/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/hooks/use_observed_host_fields.ts new file mode 100644 index 000000000000..255bb54c2c58 --- /dev/null +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/hooks/use_observed_host_fields.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 { useMlCapabilities } from '../../../../common/components/ml/hooks/use_ml_capabilities'; +import type { HostItem } from '../../../../../common/search_strategy'; +import { getAnomaliesFields } from '../../shared/common'; +import type { EntityTableRows } from '../../shared/components/entity_table/types'; +import type { ObservedEntityData } from '../../shared/components/observed_entity/types'; +import { policyFields } from '../fields/endpoint_policy_fields'; +import { basicHostFields } from '../fields/basic_host_fields'; +import { cloudFields } from '../fields/cloud_fields'; + +export const useObservedHostFields = ( + hostData: ObservedEntityData +): EntityTableRows> => { + const mlCapabilities = useMlCapabilities(); + + return useMemo(() => { + if (hostData == null) { + return []; + } + + return [ + ...basicHostFields, + ...getAnomaliesFields(mlCapabilities), + ...cloudFields, + ...policyFields, + ]; + }, [hostData, mlCapabilities]); +}; diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/index.test.tsx b/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/index.test.tsx new file mode 100644 index 000000000000..467a1be82a44 --- /dev/null +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/index.test.tsx @@ -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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { render } from '@testing-library/react'; +import React from 'react'; +import { TestProviders } from '../../../common/mock'; +import { mockHostRiskScoreState, mockObservedHostData } from '../mocks'; + +import type { HostPanelProps } from '.'; +import { HostPanel } from '.'; + +const mockProps: HostPanelProps = { + hostName: 'test', + contextID: 'test-host -panel', + scopeId: 'test-scope-id', + isDraggable: false, +}; + +jest.mock('../../../common/components/visualization_actions/visualization_embeddable'); + +const mockedHostRiskScore = jest.fn().mockReturnValue(mockHostRiskScoreState); +jest.mock('../../../entity_analytics/api/hooks/use_risk_score', () => ({ + useRiskScore: () => mockedHostRiskScore(), +})); + +const mockedUseObservedHost = jest.fn().mockReturnValue(mockObservedHostData); + +jest.mock('./hooks/use_observed_host', () => ({ + useObservedHost: () => mockedUseObservedHost(), +})); + +describe('HostPanel', () => { + beforeEach(() => { + mockedHostRiskScore.mockReturnValue(mockHostRiskScoreState); + mockedUseObservedHost.mockReturnValue(mockObservedHostData); + }); + + it('renders', () => { + const { getByTestId, queryByTestId } = render( + + + + ); + + expect(getByTestId('host-panel-header')).toBeInTheDocument(); + expect(queryByTestId('securitySolutionFlyoutLoading')).not.toBeInTheDocument(); + expect(getByTestId('securitySolutionFlyoutNavigationExpandDetailButton')).toBeInTheDocument(); + }); + + it('renders loading state when risk score is loading', () => { + mockedHostRiskScore.mockReturnValue({ + ...mockHostRiskScoreState, + data: undefined, + loading: true, + }); + + const { getByTestId } = render( + + + + ); + + expect(getByTestId('securitySolutionFlyoutLoading')).toBeInTheDocument(); + }); + + it('renders loading state when observed host is loading', () => { + mockedUseObservedHost.mockReturnValue({ + ...mockObservedHostData, + isLoading: true, + }); + + const { getByTestId } = render( + + + + ); + + expect(getByTestId('securitySolutionFlyoutLoading')).toBeInTheDocument(); + }); +}); diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/index.tsx b/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/index.tsx new file mode 100644 index 000000000000..783a9ce59838 --- /dev/null +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/host_right/index.tsx @@ -0,0 +1,141 @@ +/* + * 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, { useCallback, useMemo } from 'react'; +import type { FlyoutPanelProps } from '@kbn/expandable-flyout'; +import { useExpandableFlyoutContext } from '@kbn/expandable-flyout'; + +import { hostToCriteria } from '../../../common/components/ml/criteria/host_to_criteria'; +import { useRiskScore } from '../../../entity_analytics/api/hooks/use_risk_score'; +import { useQueryInspector } from '../../../common/components/page/manage_query'; +import { useGlobalTime } from '../../../common/containers/use_global_time'; +import type { HostItem } from '../../../../common/search_strategy'; +import { buildHostNamesFilter } from '../../../../common/search_strategy'; +import { RiskScoreEntity } from '../../../../common/entity_analytics/risk_engine'; +import { FlyoutLoading } from '../../shared/components/flyout_loading'; +import { FlyoutNavigation } from '../../shared/components/flyout_navigation'; +import { HostPanelContent } from './content'; +import { HostPanelHeader } from './header'; +import { AnomalyTableProvider } from '../../../common/components/ml/anomaly/anomaly_table_provider'; +import type { ObservedEntityData } from '../shared/components/observed_entity/types'; +import { useObservedHost } from './hooks/use_observed_host'; +import { HostDetailsPanelKey } from '../host_details_left'; +import type { EntityDetailsLeftPanelTab } from '../shared/components/left_panel/left_panel_header'; + +export interface HostPanelProps extends Record { + contextID: string; + scopeId: string; + hostName: string; + isDraggable?: boolean; +} + +export interface HostPanelExpandableFlyoutProps extends FlyoutPanelProps { + key: 'host-panel'; + params: HostPanelProps; +} + +export const HostPanelKey: HostPanelExpandableFlyoutProps['key'] = 'host-panel'; +export const HOST_PANEL_RISK_SCORE_QUERY_ID = 'HostPanelRiskScoreQuery'; +export const HOST_PANEL_OBSERVED_HOST_QUERY_ID = 'HostPanelObservedHostQuery'; + +const FIRST_RECORD_PAGINATION = { + cursorStart: 0, + querySize: 1, +}; + +export const HostPanel = ({ contextID, scopeId, hostName, isDraggable }: HostPanelProps) => { + const { openLeftPanel } = useExpandableFlyoutContext(); + const { to, from, isInitializing, setQuery, deleteQuery } = useGlobalTime(); + const hostNameFilterQuery = useMemo( + () => (hostName ? buildHostNamesFilter([hostName]) : undefined), + [hostName] + ); + + const riskScoreState = useRiskScore({ + riskEntity: RiskScoreEntity.host, + filterQuery: hostNameFilterQuery, + onlyLatest: false, + pagination: FIRST_RECORD_PAGINATION, + }); + + const { data: hostRisk, inspect: inspectRiskScore, refetch, loading } = riskScoreState; + const hostRiskData = hostRisk && hostRisk.length > 0 ? hostRisk[0] : undefined; + + useQueryInspector({ + deleteQuery, + inspect: inspectRiskScore, + loading, + queryId: HOST_PANEL_RISK_SCORE_QUERY_ID, + refetch, + setQuery, + }); + + const openTabPanel = useCallback( + (tab?: EntityDetailsLeftPanelTab) => { + openLeftPanel({ + id: HostDetailsPanelKey, + params: { + riskInputs: { + alertIds: hostRiskData?.host.risk.inputs?.map(({ id }) => id) ?? [], + host: { + name: hostName, + }, + }, + path: tab ? { tab } : undefined, + }, + }); + }, + [openLeftPanel, hostRiskData?.host.risk.inputs, hostName] + ); + + const openDefaultPanel = useCallback(() => openTabPanel(), [openTabPanel]); + const observedHost = useObservedHost(hostName); + + if (riskScoreState.loading || observedHost.isLoading) { + return ; + } + + return ( + + {({ isLoadingAnomaliesData, anomaliesData, jobNameById }) => { + const observedHostWithAnomalies: ObservedEntityData = { + ...observedHost, + anomalies: { + isLoading: isLoadingAnomaliesData, + anomalies: anomaliesData, + jobNameById, + }, + }; + + return ( + <> + + + + + ); + }} + + ); +}; + +HostPanel.displayName = 'HostPanel'; diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/mocks/index.ts b/x-pack/plugins/security_solution/public/flyout/entity_details/mocks/index.ts new file mode 100644 index 000000000000..01dafb9d6b47 --- /dev/null +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/mocks/index.ts @@ -0,0 +1,168 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { HostMetadataInterface } from '../../../../common/endpoint/types'; +import { EndpointStatus, HostStatus } from '../../../../common/endpoint/types'; +import type { RiskScoreState } from '../../../entity_analytics/api/hooks/use_risk_score'; +import type { + HostItem, + HostRiskScore, + RiskScoreEntity, + UserRiskScore, +} from '../../../../common/search_strategy'; +import { HostPolicyResponseActionStatus, RiskSeverity } from '../../../../common/search_strategy'; +import { RiskCategories } from '../../../../common/entity_analytics/risk_engine'; +import type { ObservedEntityData } from '../shared/components/observed_entity/types'; + +const userRiskScore: UserRiskScore = { + '@timestamp': '1989-11-08T23:00:00.000Z', + user: { + name: 'test', + risk: { + rule_risks: [], + calculated_score_norm: 70, + multipliers: [], + calculated_level: RiskSeverity.high, + inputs: [ + { + id: '_id', + index: '_index', + category: RiskCategories.category_1, + description: 'Alert from Rule: My rule', + risk_score: 30, + timestamp: '2021-08-19T18:55:59.000Z', + }, + ], + }, + }, + alertsCount: 0, + oldestAlertTimestamp: '1989-11-08T23:00:00.000Z', +}; + +const hostRiskScore: HostRiskScore = { + '@timestamp': '1989-11-08T23:00:00.000Z', + host: { + name: 'test', + risk: { + rule_risks: [], + calculated_score_norm: 70, + multipliers: [], + calculated_level: RiskSeverity.high, + inputs: [ + { + id: '_id', + index: '_index', + category: RiskCategories.category_1, + description: 'Alert from Rule: My rule', + risk_score: 30, + timestamp: '2021-08-19T18:55:59.000Z', + }, + ], + }, + }, + alertsCount: 0, + oldestAlertTimestamp: '1989-11-08T23:00:00.000Z', +}; + +export const mockUserRiskScoreState: RiskScoreState = { + data: [userRiskScore], + inspect: { + dsl: [], + response: [], + }, + isInspected: false, + refetch: () => {}, + totalCount: 0, + isModuleEnabled: true, + isAuthorized: true, + isDeprecated: false, + loading: false, +}; + +export const mockHostRiskScoreState: RiskScoreState = { + data: [hostRiskScore], + inspect: { + dsl: [], + response: [], + }, + isInspected: false, + refetch: () => {}, + totalCount: 0, + isModuleEnabled: true, + isAuthorized: true, + isDeprecated: false, + loading: false, +}; + +const hostMetadata: HostMetadataInterface = { + '@timestamp': 1036358673463478, + + agent: { + id: 'endpoint-agent-id', + version: 'endpoint-agent-version', + type: 'endpoint-agent-type', + }, + Endpoint: { + status: EndpointStatus.enrolled, + policy: { + applied: { + name: 'policy-name', + id: 'C2A9093E-E289-4C0A-AA44-8C32A414FA7A', + endpoint_policy_version: 3, + version: 5, + status: HostPolicyResponseActionStatus.failure, + }, + }, + }, +} as HostMetadataInterface; + +export const mockObservedHost: HostItem = { + host: { + id: ['host-id'], + mac: ['host-mac'], + architecture: ['host-architecture'], + os: { + platform: ['host-platform'], + name: ['os-name'], + version: ['host-version'], + family: ['host-family'], + }, + ip: ['host-ip'], + name: ['host-name'], + }, + cloud: { + instance: { + id: ['cloud-instance-id'], + }, + provider: ['cloud-provider'], + region: ['cloud-region'], + machine: { + type: ['cloud-machine-type'], + }, + }, + endpoint: { + hostInfo: { + metadata: hostMetadata, + host_status: HostStatus.HEALTHY, + last_checkin: 'host-last-checkin', + }, + }, +}; + +export const mockObservedHostData: ObservedEntityData = { + details: mockObservedHost, + isLoading: false, + firstSeen: { + isLoading: false, + date: '2023-02-23T20:03:17.489Z', + }, + lastSeen: { + isLoading: false, + date: '2023-02-23T20:03:17.489Z', + }, + anomalies: { isLoading: false, anomalies: null, jobNameById: {} }, +}; diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/shared/common.test.tsx b/x-pack/plugins/security_solution/public/flyout/entity_details/shared/common.test.tsx new file mode 100644 index 000000000000..70b37fd8ba72 --- /dev/null +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/shared/common.test.tsx @@ -0,0 +1,45 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { getAnomaliesFields } from './common'; +import { emptyMlCapabilities } from '../../../../common/machine_learning/empty_ml_capabilities'; + +const emptyMlCapabilitiesProvider = { + ...emptyMlCapabilities, + capabilitiesFetched: false, +}; + +describe('getAnomaliesFields', () => { + it('returns max anomaly score', () => { + const field = getAnomaliesFields(emptyMlCapabilitiesProvider); + + expect(field[0].label).toBe('Max anomaly score by job'); + }); + + it('hides anomalies field when user has no permissions', () => { + const field = getAnomaliesFields(emptyMlCapabilitiesProvider); + + expect(field[0].isVisible()).toBeFalsy(); + }); + + it('shows anomalies field when user has permissions', () => { + const mlCapabilitiesProvider = { + ...emptyMlCapabilities, + capabilitiesFetched: false, + capabilities: { + ...emptyMlCapabilities.capabilities, + canGetJobs: true, + canGetDatafeeds: true, + canGetCalendars: true, + }, + }; + + const field = getAnomaliesFields(mlCapabilitiesProvider); + + expect(field[0].isVisible()).toBeTruthy(); + }); +}); diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/shared/common.tsx b/x-pack/plugins/security_solution/public/flyout/entity_details/shared/common.tsx new file mode 100644 index 000000000000..95d4758c2c44 --- /dev/null +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/shared/common.tsx @@ -0,0 +1,26 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 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 type { ObservedEntityData } from './components/observed_entity/types'; +import type { MlCapabilitiesProvider } from '../../../common/components/ml/permissions/ml_capabilities_provider'; +import { hasMlUserPermissions } from '../../../../common/machine_learning/has_ml_user_permissions'; +import { getEmptyTagValue } from '../../../common/components/empty_value'; +import type { HostItem } from '../../../../common/search_strategy'; +import { AnomaliesField } from './components/anomalies_field'; + +export const getAnomaliesFields = (mlCapabilities: MlCapabilitiesProvider) => [ + { + label: i18n.translate('xpack.securitySolution.timeline.sidePanel.maxAnomalyScoreByJobTitle', { + defaultMessage: 'Max anomaly score by job', + }), + render: (hostData: ObservedEntityData) => + hostData.anomalies ? : getEmptyTagValue(), + isVisible: () => hasMlUserPermissions(mlCapabilities), + }, +]; diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/shared/components/anomalies_field.test.tsx b/x-pack/plugins/security_solution/public/flyout/entity_details/shared/components/anomalies_field.test.tsx new file mode 100644 index 000000000000..c8a2cdbb71da --- /dev/null +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/shared/components/anomalies_field.test.tsx @@ -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 { mockAnomalies } from '../../../../common/components/ml/mock'; +import { render } from '@testing-library/react'; +import React from 'react'; +import { AnomaliesField } from './anomalies_field'; +import { TestProviders } from '../../../../common/mock'; + +jest.mock('../../../../common/components/cell_actions', () => { + const actual = jest.requireActual('../../../../common/components/cell_actions'); + return { + ...actual, + SecurityCellActions: () => <>, + }; +}); + +describe('getAnomaliesFields', () => { + it('returns max anomaly score', () => { + const { getByTestId } = render( + , + { + wrapper: TestProviders, + } + ); + + expect(getByTestId('anomaly-scores')).toBeInTheDocument(); + }); +}); diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/shared/components/anomalies_field.tsx b/x-pack/plugins/security_solution/public/flyout/entity_details/shared/components/anomalies_field.tsx new file mode 100644 index 000000000000..ea5e7b17202f --- /dev/null +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/shared/components/anomalies_field.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, { useCallback } from 'react'; +import { useDispatch } from 'react-redux'; +import type { EntityAnomalies } from './observed_entity/types'; +import { AnomalyScores } from '../../../../common/components/ml/score/anomaly_scores'; +import { useGlobalTime } from '../../../../common/containers/use_global_time'; +import { scoreIntervalToDateTime } from '../../../../common/components/ml/score/score_interval_to_datetime'; +import { InputsModelId } from '../../../../common/store/inputs/constants'; +import { setAbsoluteRangeDatePicker } from '../../../../common/store/inputs/actions'; + +export const AnomaliesField = ({ anomalies }: { anomalies: EntityAnomalies }) => { + const { to, from } = useGlobalTime(); + const dispatch = useDispatch(); + + const narrowDateRange = useCallback( + (score, interval) => { + const fromTo = scoreIntervalToDateTime(score, interval); + dispatch( + setAbsoluteRangeDatePicker({ + id: InputsModelId.global, + from: fromTo.from, + to: fromTo.to, + }) + ); + }, + [dispatch] + ); + + return ( + + ); +}; diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/shared/components/entity_table/columns.tsx b/x-pack/plugins/security_solution/public/flyout/entity_details/shared/components/entity_table/columns.tsx new file mode 100644 index 000000000000..e97ab9b4acca --- /dev/null +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/shared/components/entity_table/columns.tsx @@ -0,0 +1,75 @@ +/* + * 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 { css } from '@emotion/react'; +import React from 'react'; +import { euiLightVars } from '@kbn/ui-theme'; +import { FormattedMessage } from '@kbn/i18n-react'; +import { DefaultFieldRenderer } from '../../../../../timelines/components/field_renderers/field_renderers'; +import { getEmptyTagValue } from '../../../../../common/components/empty_value'; +import { getSourcererScopeId } from '../../../../../helpers'; +import type { BasicEntityData, EntityTableColumns } from './types'; + +export const getEntityTableColumns = ( + contextID: string, + scopeId: string, + isDraggable: boolean, + data: T +): EntityTableColumns => [ + { + name: ( + + ), + field: 'label', + render: (label: string, { field }) => ( + + {label ?? field} + + ), + }, + { + name: ( + + ), + field: 'field', + render: (field: string | undefined, { getValues, render, renderField }) => { + const values = getValues && getValues(data); + + if (field) { + return ( + + ); + } + + if (render) { + return render(data); + } + + return getEmptyTagValue(); + }, + }, +]; diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/shared/components/entity_table/index.test.tsx b/x-pack/plugins/security_solution/public/flyout/entity_details/shared/components/entity_table/index.test.tsx new file mode 100644 index 000000000000..d6243abb39e9 --- /dev/null +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/shared/components/entity_table/index.test.tsx @@ -0,0 +1,94 @@ +/* + * 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 { render } from '@testing-library/react'; +import React from 'react'; +import { EntityTable } from '.'; +import { TestProviders } from '../../../../../common/mock'; +import type { BasicEntityData, EntityTableRow } from './types'; + +const renderedFieldValue = 'testValue1'; + +const testField: EntityTableRow = { + label: 'testLabel', + field: 'testField', + getValues: (data: unknown) => [renderedFieldValue], + renderField: (field: string) => <>{field}, +}; + +const mockProps = { + contextID: 'testContextID', + scopeId: 'testScopeId', + isDraggable: false, + data: { isLoading: false }, + entityFields: [testField], +}; + +describe('EntityTable', () => { + it('renders correctly', () => { + const { queryByTestId, queryAllByTestId } = render(, { + wrapper: TestProviders, + }); + + expect(queryByTestId('entity-table')).toBeInTheDocument(); + expect(queryAllByTestId('entity-table-label')).toHaveLength(1); + }); + + it("it doesn't render fields when isVisible returns false", () => { + const props = { + ...mockProps, + entityFields: [ + { + ...testField, + isVisible: () => false, + }, + ], + }; + + const { queryAllByTestId } = render(, { + wrapper: TestProviders, + }); + + expect(queryAllByTestId('entity-table-label')).toHaveLength(0); + }); + + it('it renders the field label', () => { + const { queryByTestId } = render(, { + wrapper: TestProviders, + }); + + expect(queryByTestId('entity-table-label')).toHaveTextContent('testLabel'); + }); + + it('it renders the field value', () => { + const { queryByTestId } = render(, { + wrapper: TestProviders, + }); + + expect(queryByTestId('DefaultFieldRendererComponent')).toHaveTextContent(renderedFieldValue); + }); + + it('it call render function when field is undefined', () => { + const props = { + ...mockProps, + entityFields: [ + { + label: 'testLabel', + render: (data: unknown) => ( + {'test-custom-render'} + ), + }, + ], + }; + + const { queryByTestId } = render(, { + wrapper: TestProviders, + }); + + expect(queryByTestId('test-custom-render')).toBeInTheDocument(); + }); +}); diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/shared/components/entity_table/index.tsx b/x-pack/plugins/security_solution/public/flyout/entity_details/shared/components/entity_table/index.tsx new file mode 100644 index 000000000000..84075071e7a9 --- /dev/null +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/shared/components/entity_table/index.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, { useMemo } from 'react'; +import { BasicTable } from '../../../../../common/components/ml/tables/basic_table'; +import { getEntityTableColumns } from './columns'; +import type { BasicEntityData, EntityTableRows } from './types'; + +interface EntityTableProps { + contextID: string; + scopeId: string; + isDraggable: boolean; + data: T; + entityFields: EntityTableRows; +} + +export const EntityTable = ({ + contextID, + scopeId, + isDraggable, + data, + entityFields, +}: EntityTableProps) => { + const items = useMemo( + () => entityFields.filter(({ isVisible }) => (isVisible ? isVisible(data) : true)), + [data, entityFields] + ); + + const entityTableColumns = useMemo( + () => getEntityTableColumns(contextID, scopeId, isDraggable, data), + [contextID, scopeId, isDraggable, data] + ); + return ( + + ); +}; diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/shared/components/entity_table/types.ts b/x-pack/plugins/security_solution/public/flyout/entity_details/shared/components/entity_table/types.ts new file mode 100644 index 000000000000..690a99ec92ce --- /dev/null +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/shared/components/entity_table/types.ts @@ -0,0 +1,54 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { EuiBasicTableColumn } from '@elastic/eui'; +import type { XOR } from '../../../../../../common/utility_types'; + +export type EntityTableRow = XOR< + { + label: string; + /** + * The field name. It is used for displaying CellActions. + */ + field: string; + /** + * It extracts an array of strings from the data. Each element is a valid field value. + * It is used for displaying MoreContainer. + */ + getValues: (data: T) => string[] | null | undefined; + /** + * It allows the customization of the rendered field. + * The element is still rendered inside `DefaultFieldRenderer` getting `CellActions` and `MoreContainer` capabilities. + */ + renderField?: (value: string) => JSX.Element; + /** + * It hides the row when `isVisible` returns false. + */ + isVisible?: (data: T) => boolean; + }, + { + label: string; + /** + * It takes complete control over the rendering. + * `getValues` and `renderField` are not called when this property is used. + */ + render: (data: T) => JSX.Element; + /** + * It hides the row when `isVisible` returns false. + */ + isVisible?: (data: T) => boolean; + } +>; + +export type EntityTableColumns = Array< + EuiBasicTableColumn> +>; +export type EntityTableRows = Array>; + +export interface BasicEntityData { + isLoading: boolean; +} diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/user_details_left/content.tsx b/x-pack/plugins/security_solution/public/flyout/entity_details/shared/components/left_panel/left_panel_content.tsx similarity index 70% rename from x-pack/plugins/security_solution/public/flyout/entity_details/user_details_left/content.tsx rename to x-pack/plugins/security_solution/public/flyout/entity_details/shared/components/left_panel/left_panel_content.tsx index 991592bd1ea0..5a66a5b30561 100644 --- a/x-pack/plugins/security_solution/public/flyout/entity_details/user_details_left/content.tsx +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/shared/components/left_panel/left_panel_content.tsx @@ -9,19 +9,19 @@ import { useEuiBackgroundColor } from '@elastic/eui'; import type { VFC } from 'react'; import React, { useMemo } from 'react'; import { css } from '@emotion/react'; -import type { LeftPanelTabsType, UserDetailsLeftPanelTab } from './tabs'; -import { FlyoutBody } from '../../shared/components/flyout_body'; +import { FlyoutBody } from '../../../../shared/components/flyout_body'; +import type { EntityDetailsLeftPanelTab, LeftPanelTabsType } from './left_panel_header'; export interface PanelContentProps { - selectedTabId: UserDetailsLeftPanelTab; + selectedTabId: EntityDetailsLeftPanelTab; tabs: LeftPanelTabsType; } /** - * User details expandable flyout left section. + * Content for a entity left panel. * Appears after the user clicks on the expand details button in the right section. */ -export const PanelContent: VFC = ({ selectedTabId, tabs }) => { +export const LeftPanelContent: VFC = ({ selectedTabId, tabs }) => { const selectedTabContent = useMemo(() => { return tabs.find((tab) => tab.id === selectedTabId)?.content; }, [selectedTabId, tabs]); @@ -37,4 +37,4 @@ export const PanelContent: VFC = ({ selectedTabId, tabs }) => ); }; -PanelContent.displayName = 'PanelContent'; +LeftPanelContent.displayName = 'LeftPanelContent'; diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/user_details_left/header.tsx b/x-pack/plugins/security_solution/public/flyout/entity_details/shared/components/left_panel/left_panel_header.tsx similarity index 67% rename from x-pack/plugins/security_solution/public/flyout/entity_details/user_details_left/header.tsx rename to x-pack/plugins/security_solution/public/flyout/entity_details/shared/components/left_panel/left_panel_header.tsx index 2f807ca1d0a7..ea62ce25f3ca 100644 --- a/x-pack/plugins/security_solution/public/flyout/entity_details/user_details_left/header.tsx +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/shared/components/left_panel/left_panel_header.tsx @@ -6,21 +6,33 @@ */ import { EuiTab, EuiTabs, useEuiBackgroundColor } from '@elastic/eui'; -import type { VFC } from 'react'; +import type { ReactElement, VFC } from 'react'; import React, { memo } from 'react'; import { css } from '@emotion/react'; -import type { LeftPanelTabsType, UserDetailsLeftPanelTab } from './tabs'; -import { FlyoutHeader } from '../../shared/components/flyout_header'; +import { FlyoutHeader } from '../../../../shared/components/flyout_header'; + +export type LeftPanelTabsType = Array<{ + id: EntityDetailsLeftPanelTab; + 'data-test-subj': string; + name: ReactElement; + content: React.ReactElement; +}>; + +export enum EntityDetailsLeftPanelTab { + RISK_INPUTS = 'risk_inputs', + OKTA = 'okta_document', + ENTRA = 'entra_document', +} export interface PanelHeaderProps { /** * Id of the tab selected in the parent component to display its content */ - selectedTabId: UserDetailsLeftPanelTab; + selectedTabId: EntityDetailsLeftPanelTab; /** * Callback to set the selected tab id in the parent component */ - setSelectedTabId: (selected: UserDetailsLeftPanelTab) => void; + setSelectedTabId: (selected: EntityDetailsLeftPanelTab) => void; /** * List of tabs to display in the header */ @@ -31,9 +43,9 @@ export interface PanelHeaderProps { * Header at the top of the left section. * Displays the investigation and insights tabs (visualize is hidden for 8.9). */ -export const PanelHeader: VFC = memo( +export const LeftPanelHeader: VFC = memo( ({ selectedTabId, setSelectedTabId, tabs }) => { - const onSelectedTabChanged = (id: UserDetailsLeftPanelTab) => setSelectedTabId(id); + const onSelectedTabChanged = (id: EntityDetailsLeftPanelTab) => setSelectedTabId(id); const renderTabs = tabs.map((tab, index) => ( onSelectedTabChanged(tab.id)} @@ -61,4 +73,4 @@ export const PanelHeader: VFC = memo( } ); -PanelHeader.displayName = 'PanelHeader'; +LeftPanelHeader.displayName = 'LeftPanelHeader'; diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/shared/components/observed_entity/index.test.tsx b/x-pack/plugins/security_solution/public/flyout/entity_details/shared/components/observed_entity/index.test.tsx new file mode 100644 index 000000000000..f3cdfefa6c74 --- /dev/null +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/shared/components/observed_entity/index.test.tsx @@ -0,0 +1,43 @@ +/* + * 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 { render } from '@testing-library/react'; +import React from 'react'; +import { ObservedEntity } from '.'; +import { TestProviders } from '../../../../../common/mock'; +import { mockObservedHostData } from '../../../mocks'; + +describe('ObservedHost', () => { + const mockProps = { + observedData: mockObservedHostData, + contextID: '', + scopeId: '', + isDraggable: false, + queryId: 'TEST_QUERY_ID', + observedFields: [], + }; + + it('renders', () => { + const { getByTestId } = render( + + + + ); + + expect(getByTestId('observedEntity-accordion')).toBeInTheDocument(); + }); + + it('renders the formatted date', () => { + const { getByTestId } = render( + + + + ); + + expect(getByTestId('observedEntity-accordion')).toHaveTextContent('Updated Feb 23, 2023'); + }); +}); diff --git a/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/observed_user.tsx b/x-pack/plugins/security_solution/public/flyout/entity_details/shared/components/observed_entity/index.tsx similarity index 51% rename from x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/observed_user.tsx rename to x-pack/plugins/security_solution/public/flyout/entity_details/shared/components/observed_entity/index.tsx index 411e516b570f..792ad322e631 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/observed_user.tsx +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/shared/components/observed_entity/index.tsx @@ -5,39 +5,34 @@ * 2.0. */ -import { EuiAccordion, EuiSpacer, EuiTitle, useEuiTheme, useEuiFontSize } from '@elastic/eui'; +import { EuiAccordion, EuiSpacer, EuiTitle, useEuiFontSize, useEuiTheme } from '@elastic/eui'; -import React, { useMemo } from 'react'; +import React from 'react'; import { css } from '@emotion/react'; import { FormattedMessage } from '@kbn/i18n-react'; -import * as i18n from './translations'; -import type { ObservedUserData } from './types'; -import { BasicTable } from '../../../../common/components/ml/tables/basic_table'; -import { FormattedRelativePreferenceDate } from '../../../../common/components/formatted_date'; -import { getObservedUserTableColumns } from './columns'; -import { ONE_WEEK_IN_HOURS } from './constants'; -import { InspectButton, InspectButtonContainer } from '../../../../common/components/inspect'; -import { OBSERVED_USER_QUERY_ID } from '../../../../explore/users/containers/users/observed_details'; -import { useObservedUserItems } from './hooks/use_observed_user_items'; +import { EntityTable } from '../entity_table'; +import { FormattedRelativePreferenceDate } from '../../../../../common/components/formatted_date'; +import { InspectButton, InspectButtonContainer } from '../../../../../common/components/inspect'; +import type { EntityTableRows } from '../entity_table/types'; +import { ONE_WEEK_IN_HOURS } from '../../constants'; +import type { ObservedEntityData } from './types'; -export const ObservedUser = ({ - observedUser, +export const ObservedEntity = ({ + observedData, contextID, scopeId, isDraggable, + observedFields, + queryId, }: { - observedUser: ObservedUserData; + observedData: ObservedEntityData; contextID: string; scopeId: string; isDraggable: boolean; + observedFields: EntityTableRows>; + queryId: string; }) => { const { euiTheme } = useEuiTheme(); - const observedItems = useObservedUserItems(observedUser); - - const observedUserTableColumns = useMemo( - () => getObservedUserTableColumns(contextID, scopeId, isDraggable), - [contextID, scopeId, isDraggable] - ); const xsFontSize = useEuiFontSize('xxs').fontSize; return ( @@ -45,18 +40,23 @@ export const ObservedUser = ({ -

{i18n.OBSERVED_DATA_TITLE}

+

+ +

} extraAction={ @@ -67,23 +67,28 @@ export const ObservedUser = ({ `} > + } /> - {observedUser.lastSeen.date && ( + {observedData.lastSeen.date && ( @@ -101,17 +106,12 @@ export const ObservedUser = ({ `} > - -
diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/shared/components/observed_entity/types.ts b/x-pack/plugins/security_solution/public/flyout/entity_details/shared/components/observed_entity/types.ts new file mode 100644 index 000000000000..f9d9db179d3f --- /dev/null +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/shared/components/observed_entity/types.ts @@ -0,0 +1,27 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { BasicEntityData } from '../entity_table/types'; +import type { AnomalyTableProviderChildrenProps } from '../../../../../common/components/ml/anomaly/anomaly_table_provider'; + +export interface FirstLastSeenData { + date: string | null | undefined; + isLoading: boolean; +} + +export interface EntityAnomalies { + isLoading: AnomalyTableProviderChildrenProps['isLoadingAnomaliesData']; + anomalies: AnomalyTableProviderChildrenProps['anomaliesData']; + jobNameById: AnomalyTableProviderChildrenProps['jobNameById']; +} + +export interface ObservedEntityData extends BasicEntityData { + firstSeen: FirstLastSeenData; + lastSeen: FirstLastSeenData; + anomalies: EntityAnomalies; + details: T; +} diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/shared/constants.ts b/x-pack/plugins/security_solution/public/flyout/entity_details/shared/constants.ts new file mode 100644 index 000000000000..bad35d365789 --- /dev/null +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/shared/constants.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 const ONE_WEEK_IN_HOURS = 24 * 7; diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/user_details_left/index.tsx b/x-pack/plugins/security_solution/public/flyout/entity_details/user_details_left/index.tsx index ae96a76c68d4..c2591eab2c91 100644 --- a/x-pack/plugins/security_solution/public/flyout/entity_details/user_details_left/index.tsx +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/user_details_left/index.tsx @@ -9,11 +9,14 @@ import React, { useMemo } from 'react'; import type { FlyoutPanelProps, PanelPath } from '@kbn/expandable-flyout'; import { useExpandableFlyoutContext } from '@kbn/expandable-flyout'; import { useManagedUser } from '../../../timelines/components/side_panel/new_user_detail/hooks/use_managed_user'; -import { PanelHeader } from './header'; -import { PanelContent } from './content'; -import type { LeftPanelTabsType, UserDetailsLeftPanelTab } from './tabs'; import { useTabs } from './tabs'; import { FlyoutLoading } from '../../shared/components/flyout_loading'; +import type { + EntityDetailsLeftPanelTab, + LeftPanelTabsType, +} from '../shared/components/left_panel/left_panel_header'; +import { LeftPanelHeader } from '../shared/components/left_panel/left_panel_header'; +import { LeftPanelContent } from '../shared/components/left_panel/left_panel_content'; interface RiskInputsParam { alertIds: string[]; @@ -44,8 +47,12 @@ export const UserDetailsPanel = ({ riskInputs, user, path }: UserDetailsPanelPro return ( <> - - + + ); }; @@ -65,7 +72,7 @@ const useSelectedTab = ( return tabs.find((tab) => tab.id === path.tab)?.id ?? defaultTab; }, [path, tabs]); - const setSelectedTabId = (tabId: UserDetailsLeftPanelTab) => { + const setSelectedTabId = (tabId: EntityDetailsLeftPanelTab) => { openLeftPanel({ id: UserDetailsPanelKey, path: { diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/user_details_left/tabs.tsx b/x-pack/plugins/security_solution/public/flyout/entity_details/user_details_left/tabs.tsx index 61f408a5c0ad..3867afb4470e 100644 --- a/x-pack/plugins/security_solution/public/flyout/entity_details/user_details_left/tabs.tsx +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/user_details_left/tabs.tsx @@ -5,7 +5,6 @@ * 2.0. */ -import type { ReactElement } from 'react'; import React, { useMemo } from 'react'; import { FormattedMessage } from '@kbn/i18n-react'; @@ -19,19 +18,8 @@ import type { import { ENTRA_TAB_TEST_ID, OKTA_TAB_TEST_ID } from './test_ids'; import { AssetDocumentTab } from './tabs/asset_document'; import { RightPanelProvider } from '../../document_details/right/context'; - -export type LeftPanelTabsType = Array<{ - id: UserDetailsLeftPanelTab; - 'data-test-subj': string; - name: ReactElement; - content: React.ReactElement; -}>; - -export enum UserDetailsLeftPanelTab { - RISK_INPUTS = 'risk_inputs', - OKTA = 'okta_document', - ENTRA = 'entra_document', -} +import type { LeftPanelTabsType } from '../shared/components/left_panel/left_panel_header'; +import { EntityDetailsLeftPanelTab } from '../shared/components/left_panel/left_panel_header'; export const useTabs = (managedUser: ManagedUserHits, alertIds: string[]): LeftPanelTabsType => useMemo(() => { @@ -55,7 +43,7 @@ export const useTabs = (managedUser: ManagedUserHits, alertIds: string[]): LeftP }, [alertIds, managedUser]); const getOktaTab = (oktaManagedUser: ManagedUserHit) => ({ - id: UserDetailsLeftPanelTab.OKTA, + id: EntityDetailsLeftPanelTab.OKTA, 'data-test-subj': OKTA_TAB_TEST_ID, name: ( ({ const getEntraTab = (entraManagedUser: ManagedUserHit) => { return { - id: UserDetailsLeftPanelTab.ENTRA, + id: EntityDetailsLeftPanelTab.ENTRA, 'data-test-subj': ENTRA_TAB_TEST_ID, name: ( window.alert('openLeftPanel called'), diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/user_right/content.tsx b/x-pack/plugins/security_solution/public/flyout/entity_details/user_right/content.tsx index 9b99c42aeac7..f1f7916d3907 100644 --- a/x-pack/plugins/security_solution/public/flyout/entity_details/user_right/content.tsx +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/user_right/content.tsx @@ -8,27 +8,27 @@ import { EuiHorizontalRule } from '@elastic/eui'; import React from 'react'; +import { OBSERVED_USER_QUERY_ID } from '../../../explore/users/containers/users/observed_details'; import { RiskSummary } from '../../../entity_analytics/components/risk_summary_flyout/risk_summary'; import type { RiskScoreState } from '../../../entity_analytics/api/hooks/use_risk_score'; import { ManagedUser } from '../../../timelines/components/side_panel/new_user_detail/managed_user'; -import type { - ManagedUserData, - ObservedUserData, -} from '../../../timelines/components/side_panel/new_user_detail/types'; -import { ObservedUser } from '../../../timelines/components/side_panel/new_user_detail/observed_user'; -import type { RiskScoreEntity } from '../../../../common/search_strategy'; +import type { ManagedUserData } from '../../../timelines/components/side_panel/new_user_detail/types'; +import type { RiskScoreEntity, UserItem } from '../../../../common/search_strategy'; import { USER_PANEL_RISK_SCORE_QUERY_ID } from '.'; import { FlyoutBody } from '../../shared/components/flyout_body'; -import type { UserDetailsLeftPanelTab } from '../user_details_left/tabs'; +import { ObservedEntity } from '../shared/components/observed_entity'; +import type { ObservedEntityData } from '../shared/components/observed_entity/types'; +import { useObservedUserItems } from './hooks/use_observed_user_items'; +import type { EntityDetailsLeftPanelTab } from '../shared/components/left_panel/left_panel_header'; interface UserPanelContentProps { - observedUser: ObservedUserData; + observedUser: ObservedEntityData; managedUser: ManagedUserData; riskScoreState: RiskScoreState; contextID: string; scopeId: string; isDraggable: boolean; - openDetailsPanel: (tab: UserDetailsLeftPanelTab) => void; + openDetailsPanel: (tab: EntityDetailsLeftPanelTab) => void; } export const UserPanelContent = ({ @@ -40,6 +40,8 @@ export const UserPanelContent = ({ isDraggable, openDetailsPanel, }: UserPanelContentProps) => { + const observedFields = useObservedUserItems(observedUser); + return ( {riskScoreState.isModuleEnabled && riskScoreState.data?.length !== 0 && ( @@ -52,11 +54,13 @@ export const UserPanelContent = ({ )} - ; managedUser: ManagedUserData; } diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/user_right/hooks/translations.ts b/x-pack/plugins/security_solution/public/flyout/entity_details/user_right/hooks/translations.ts new file mode 100644 index 000000000000..9c7637d75f54 --- /dev/null +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/user_right/hooks/translations.ts @@ -0,0 +1,54 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { i18n } from '@kbn/i18n'; + +export const USER_ID = i18n.translate('xpack.securitySolution.flyout.entityDetails.user.idLabel', { + defaultMessage: 'User ID', +}); + +export const MAX_ANOMALY_SCORE_BY_JOB = i18n.translate( + 'xpack.securitySolution.flyout.entityDetails.user.maxAnomalyScoreByJobLabel', + { + defaultMessage: 'Max anomaly score by job', + } +); + +export const FIRST_SEEN = i18n.translate( + 'xpack.securitySolution.flyout.entityDetails.user.firstSeenLabel', + { + defaultMessage: 'First seen', + } +); + +export const LAST_SEEN = i18n.translate( + 'xpack.securitySolution.flyout.entityDetails.user.lastSeenLabel', + { + defaultMessage: 'Last seen', + } +); + +export const OPERATING_SYSTEM_TITLE = i18n.translate( + 'xpack.securitySolution.flyout.entityDetails.user.hostOsNameLabel', + { + defaultMessage: 'Operating system', + } +); + +export const FAMILY = i18n.translate( + 'xpack.securitySolution.flyout.entityDetails.user.familyLabel', + { + defaultMessage: 'Family', + } +); + +export const IP_ADDRESSES = i18n.translate( + 'xpack.securitySolution.flyout.entityDetails.user.ipAddressesLabel', + { + defaultMessage: 'IP addresses', + } +); diff --git a/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/hooks/use_observed_user.ts b/x-pack/plugins/security_solution/public/flyout/entity_details/user_right/hooks/use_observed_user.ts similarity index 65% rename from x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/hooks/use_observed_user.ts rename to x-pack/plugins/security_solution/public/flyout/entity_details/user_right/hooks/use_observed_user.ts index d3d2c4fde90a..6d1ae0ab11e0 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/hooks/use_observed_user.ts +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/user_right/hooks/use_observed_user.ts @@ -6,28 +6,18 @@ */ import { useMemo } from 'react'; -import { useObservedUserDetails } from '../../../../../explore/users/containers/users/observed_details'; -import type { UserItem } from '../../../../../../common/search_strategy'; -import { Direction, NOT_EVENT_KIND_ASSET_FILTER } from '../../../../../../common/search_strategy'; -import { useSourcererDataView } from '../../../../../common/containers/sourcerer'; -import { useGlobalTime } from '../../../../../common/containers/use_global_time'; -import { useFirstLastSeen } from '../../../../../common/containers/use_first_last_seen'; -import { useQueryInspector } from '../../../../../common/components/page/manage_query'; +import { useQueryInspector } from '../../../../common/components/page/manage_query'; +import type { ObservedEntityData } from '../../shared/components/observed_entity/types'; +import { useObservedUserDetails } from '../../../../explore/users/containers/users/observed_details'; +import type { UserItem } from '../../../../../common/search_strategy'; +import { Direction, NOT_EVENT_KIND_ASSET_FILTER } from '../../../../../common/search_strategy'; +import { useSourcererDataView } from '../../../../common/containers/sourcerer'; +import { useGlobalTime } from '../../../../common/containers/use_global_time'; +import { useFirstLastSeen } from '../../../../common/containers/use_first_last_seen'; -export interface ObserverUser { - details: UserItem; - isLoading: boolean; - firstSeen: { - date: string | null | undefined; - isLoading: boolean; - }; - lastSeen: { - date: string | null | undefined; - isLoading: boolean; - }; -} - -export const useObservedUser = (userName: string): ObserverUser => { +export const useObservedUser = ( + userName: string +): Omit, 'anomalies'> => { const { selectedPatterns } = useSourcererDataView(); const { to, from, isInitializing, deleteQuery, setQuery } = useGlobalTime(); @@ -68,7 +58,7 @@ export const useObservedUser = (userName: string): ObserverUser => { return useMemo( () => ({ details: observedUserDetails, - isLoading: loadingObservedUser, + isLoading: loadingObservedUser || loadingLastSeen || loadingFirstSeen, firstSeen: { date: firstSeen, isLoading: loadingFirstSeen, diff --git a/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/hooks/use_observed_user_items.test.ts b/x-pack/plugins/security_solution/public/flyout/entity_details/user_right/hooks/use_observed_user_items.test.ts similarity index 53% rename from x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/hooks/use_observed_user_items.test.ts rename to x-pack/plugins/security_solution/public/flyout/entity_details/user_right/hooks/use_observed_user_items.test.ts index 40fd3c608903..1c7b5557dd90 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/hooks/use_observed_user_items.test.ts +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/user_right/hooks/use_observed_user_items.test.ts @@ -5,13 +5,13 @@ * 2.0. */ +import { TestProviders } from '@kbn/timelines-plugin/public/mock'; import { renderHook } from '@testing-library/react-hooks'; -import { TestProviders } from '../../../../../common/mock'; -import { mockObservedUser } from '../__mocks__'; +import { mockObservedUser } from '../mocks'; import { useObservedUserItems } from './use_observed_user_items'; describe('useManagedUserItems', () => { - it('returns managed user items for Entra user', () => { + it('returns observed user fields', () => { const { result } = renderHook(() => useObservedUserItems(mockObservedUser), { wrapper: TestProviders, }); @@ -20,43 +20,58 @@ describe('useManagedUserItems', () => { { field: 'user.id', label: 'User ID', - values: ['1234', '321'], + getValues: expect.any(Function), }, { field: 'user.domain', label: 'Domain', - values: ['test domain', 'another test domain'], - }, - { - field: 'anomalies', - label: 'Max anomaly score by job', - values: mockObservedUser.anomalies, + getValues: expect.any(Function), }, { field: '@timestamp', label: 'First seen', - values: ['2023-02-23T20:03:17.489Z'], + getValues: expect.any(Function), }, { field: '@timestamp', label: 'Last seen', - values: ['2023-02-23T20:03:17.489Z'], + getValues: expect.any(Function), }, { field: 'host.os.name', label: 'Operating system', - values: ['testOs'], + getValues: expect.any(Function), }, { field: 'host.os.family', label: 'Family', - values: ['testFamily'], + + getValues: expect.any(Function), }, { field: 'host.ip', label: 'IP addresses', - values: ['10.0.0.1', '127.0.0.1'], + + getValues: expect.any(Function), + }, + { + label: 'Max anomaly score by job', + isVisible: expect.any(Function), + render: expect.any(Function), }, ]); + + expect(result.current.map(({ getValues }) => getValues && getValues(mockObservedUser))).toEqual( + [ + ['1234', '321'], // id + ['test domain', 'another test domain'], // domain + ['2023-02-23T20:03:17.489Z'], // First seen + ['2023-02-23T20:03:17.489Z'], // Last seen + ['testOs'], // OS name + ['testFamily'], // os family + ['10.0.0.1', '127.0.0.1'], // IP addresses + undefined, // Max anomaly score by job doesn't implement getValues + ] + ); }); }); diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/user_right/hooks/use_observed_user_items.ts b/x-pack/plugins/security_solution/public/flyout/entity_details/user_right/hooks/use_observed_user_items.ts new file mode 100644 index 000000000000..7275b2ca5557 --- /dev/null +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/user_right/hooks/use_observed_user_items.ts @@ -0,0 +1,71 @@ +/* + * 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 type { UserItem } from '../../../../../common/search_strategy'; +import { useMlCapabilities } from '../../../../common/components/ml/hooks/use_ml_capabilities'; +import { getAnomaliesFields } from '../../shared/common'; +import * as i18n from './translations'; +import type { ObservedEntityData } from '../../shared/components/observed_entity/types'; +import type { EntityTableRows } from '../../shared/components/entity_table/types'; + +const basicUserFields: EntityTableRows> = [ + { + label: i18n.USER_ID, + getValues: (userData: ObservedEntityData) => userData.details.user?.id, + field: 'user.id', + }, + { + label: 'Domain', + getValues: (userData: ObservedEntityData) => userData.details.user?.domain, + field: 'user.domain', + }, + { + label: i18n.FIRST_SEEN, + getValues: (userData: ObservedEntityData) => + userData.firstSeen.date ? [userData.firstSeen.date] : undefined, + field: '@timestamp', + }, + { + label: i18n.LAST_SEEN, + getValues: (userData: ObservedEntityData) => + userData.lastSeen.date ? [userData.lastSeen.date] : undefined, + field: '@timestamp', + }, + { + label: i18n.OPERATING_SYSTEM_TITLE, + getValues: (userData: ObservedEntityData) => userData.details.host?.os?.name, + field: 'host.os.name', + }, + { + label: i18n.FAMILY, + getValues: (userData: ObservedEntityData) => userData.details.host?.os?.family, + field: 'host.os.family', + }, + { + label: i18n.IP_ADDRESSES, + getValues: (userData: ObservedEntityData) => userData.details.host?.ip, + field: 'host.ip', + }, +]; + +export const useObservedUserItems = ( + userData: ObservedEntityData +): EntityTableRows> => { + const mlCapabilities = useMlCapabilities(); + + const fields: EntityTableRows> = useMemo( + () => [...basicUserFields, ...getAnomaliesFields(mlCapabilities)], + [mlCapabilities] + ); + + if (!userData.details) { + return []; + } + + return fields; +}; diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/user_right/index.test.tsx b/x-pack/plugins/security_solution/public/flyout/entity_details/user_right/index.test.tsx index 1c74e4ed23ea..9961b3ea086e 100644 --- a/x-pack/plugins/security_solution/public/flyout/entity_details/user_right/index.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/user_right/index.test.tsx @@ -10,12 +10,12 @@ import React from 'react'; import { TestProviders } from '../../../common/mock'; import type { UserPanelProps } from '.'; import { UserPanel } from '.'; -import { mockRiskScoreState } from './mocks'; import { mockManagedUserData, - mockObservedUser, + mockRiskScoreState, } from '../../../timelines/components/side_panel/new_user_detail/__mocks__'; +import { mockObservedUser } from './mocks'; const mockProps: UserPanelProps = { userName: 'test', @@ -41,12 +41,9 @@ jest.mock( }) ); -jest.mock( - '../../../timelines/components/side_panel/new_user_detail/hooks/use_observed_user', - () => ({ - useObservedUser: () => mockedUseObservedUser(), - }) -); +jest.mock('./hooks/use_observed_user', () => ({ + useObservedUser: () => mockedUseObservedUser(), +})); describe('UserPanel', () => { beforeEach(() => { diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/user_right/index.tsx b/x-pack/plugins/security_solution/public/flyout/entity_details/user_right/index.tsx index 76168bc01c84..abe3ee479301 100644 --- a/x-pack/plugins/security_solution/public/flyout/entity_details/user_right/index.tsx +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/user_right/index.tsx @@ -11,7 +11,6 @@ import { useExpandableFlyoutContext } from '@kbn/expandable-flyout'; import { useRiskScore } from '../../../entity_analytics/api/hooks/use_risk_score'; import { ManagedUserDatasetKey } from '../../../../common/search_strategy/security_solution/users/managed_details'; import { useManagedUser } from '../../../timelines/components/side_panel/new_user_detail/hooks/use_managed_user'; -import { useObservedUser } from '../../../timelines/components/side_panel/new_user_detail/hooks/use_observed_user'; import { useQueryInspector } from '../../../common/components/page/manage_query'; import { UsersType } from '../../../explore/users/store/model'; import { getCriteriaFromUsersType } from '../../../common/components/ml/criteria/get_criteria_from_users_type'; @@ -24,7 +23,8 @@ import { FlyoutNavigation } from '../../shared/components/flyout_navigation'; import { UserPanelContent } from './content'; import { UserPanelHeader } from './header'; import { UserDetailsPanelKey } from '../user_details_left'; -import type { UserDetailsLeftPanelTab } from '../user_details_left/tabs'; +import { useObservedUser } from './hooks/use_observed_user'; +import type { EntityDetailsLeftPanelTab } from '../shared/components/left_panel/left_panel_header'; export interface UserPanelProps extends Record { contextID: string; @@ -79,7 +79,7 @@ export const UserPanel = ({ contextID, scopeId, userName, isDraggable }: UserPan const { openLeftPanel } = useExpandableFlyoutContext(); const openPanelTab = useCallback( - (tab?: UserDetailsLeftPanelTab) => { + (tab?: EntityDetailsLeftPanelTab) => { openLeftPanel({ id: UserDetailsPanelKey, params: { diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/user_right/mocks/index.ts b/x-pack/plugins/security_solution/public/flyout/entity_details/user_right/mocks/index.ts index 88ab3c10241c..b58c94c5772f 100644 --- a/x-pack/plugins/security_solution/public/flyout/entity_details/user_right/mocks/index.ts +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/user_right/mocks/index.ts @@ -5,47 +5,43 @@ * 2.0. */ -import type { RiskScoreState } from '../../../../entity_analytics/api/hooks/use_risk_score'; -import type { RiskScoreEntity, UserRiskScore } from '../../../../../common/search_strategy'; -import { RiskSeverity } from '../../../../../common/search_strategy'; -import { RiskCategories } from '../../../../../common/entity_analytics/risk_engine'; +import { mockAnomalies } from '../../../../common/components/ml/mock'; +import type { UserItem } from '../../../../../common/search_strategy'; +import type { ObservedEntityData } from '../../shared/components/observed_entity/types'; -const userRiskScore: UserRiskScore = { - '@timestamp': '626569200000', +const anomaly = mockAnomalies.anomalies[0]; + +const observedUserDetails = { user: { - name: 'test', - risk: { - rule_risks: [], - calculated_score_norm: 70, - multipliers: [], - calculated_level: RiskSeverity.high, - inputs: [ - { - id: '_id', - index: '_index', - category: RiskCategories.category_1, - description: 'Alert from Rule: My rule', - risk_score: 30, - timestamp: '2021-08-19T18:55:59.000Z', - }, - ], + id: ['1234', '321'], + domain: ['test domain', 'another test domain'], + }, + host: { + ip: ['10.0.0.1', '127.0.0.1'], + os: { + name: ['testOs'], + family: ['testFamily'], }, }, - alertsCount: 0, - oldestAlertTimestamp: '626569200000', }; -export const mockRiskScoreState: RiskScoreState = { - data: [userRiskScore], - inspect: { - dsl: [], - response: [], +export const mockObservedUser: ObservedEntityData = { + details: observedUserDetails, + isLoading: false, + firstSeen: { + isLoading: false, + date: '2023-02-23T20:03:17.489Z', + }, + lastSeen: { + isLoading: false, + date: '2023-02-23T20:03:17.489Z', + }, + anomalies: { + isLoading: false, + anomalies: { + anomalies: [anomaly], + interval: '', + }, + jobNameById: { [anomaly.jobId]: 'job_name' }, }, - isInspected: false, - refetch: () => {}, - totalCount: 0, - isModuleEnabled: true, - isAuthorized: true, - isDeprecated: false, - loading: false, }; diff --git a/x-pack/plugins/security_solution/public/flyout/index.tsx b/x-pack/plugins/security_solution/public/flyout/index.tsx index ef7e182324c6..c72417bd2004 100644 --- a/x-pack/plugins/security_solution/public/flyout/index.tsx +++ b/x-pack/plugins/security_solution/public/flyout/index.tsx @@ -26,6 +26,11 @@ import type { UserPanelExpandableFlyoutProps } from './entity_details/user_right import { UserPanel, UserPanelKey } from './entity_details/user_right'; import type { UserDetailsPanelProps } from './entity_details/user_details_left'; import { UserDetailsPanel, UserDetailsPanelKey } from './entity_details/user_details_left'; +import type { HostPanelExpandableFlyoutProps } from './entity_details/host_right'; +import { HostPanel, HostPanelKey } from './entity_details/host_right'; +import type { HostDetailsExpandableFlyoutProps } from './entity_details/host_details_left'; +import { HostDetailsPanel, HostDetailsPanelKey } from './entity_details/host_details_left'; + /** * List of all panels that will be used within the document details expandable flyout. * This needs to be passed to the expandable flyout registeredPanels property. @@ -73,6 +78,16 @@ const expandableFlyoutDocumentsPanels: ExpandableFlyoutProps['registeredPanels'] ), }, + { + key: HostPanelKey, + component: (props) => , + }, + { + key: HostDetailsPanelKey, + component: (props) => ( + + ), + }, ]; export const SecuritySolutionFlyout = memo(() => ( diff --git a/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/__mocks__/index.ts b/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/__mocks__/index.ts index 65c6bd974b83..43abce110446 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/__mocks__/index.ts +++ b/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/__mocks__/index.ts @@ -11,8 +11,7 @@ import type { } from '../../../../../../common/search_strategy/security_solution/users/managed_details'; import { ManagedUserDatasetKey } from '../../../../../../common/search_strategy/security_solution/users/managed_details'; import { RiskSeverity } from '../../../../../../common/search_strategy'; -import { mockAnomalies } from '../../../../../common/components/ml/mock'; -import type { ManagedUserData, ObservedUserData } from '../types'; +import type { ManagedUserData } from '../types'; const userRiskScore = { '@timestamp': '123456', @@ -44,43 +43,6 @@ export const mockRiskScoreState = { loading: false, }; -const anomaly = mockAnomalies.anomalies[0]; - -export const observedUserDetails = { - user: { - id: ['1234', '321'], - domain: ['test domain', 'another test domain'], - }, - host: { - ip: ['10.0.0.1', '127.0.0.1'], - os: { - name: ['testOs'], - family: ['testFamily'], - }, - }, -}; - -export const mockObservedUser: ObservedUserData = { - details: observedUserDetails, - isLoading: false, - firstSeen: { - isLoading: false, - date: '2023-02-23T20:03:17.489Z', - }, - lastSeen: { - isLoading: false, - date: '2023-02-23T20:03:17.489Z', - }, - anomalies: { - isLoading: false, - anomalies: { - anomalies: [anomaly], - interval: '', - }, - jobNameById: { [anomaly.jobId]: 'job_name' }, - }, -}; - export const mockOktaUserFields: ManagedUserFields = { '@timestamp': ['2023-11-16T13:42:23.074Z'], 'event.dataset': [ManagedUserDatasetKey.OKTA], diff --git a/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/columns.tsx b/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/columns.tsx index 8c4f31ea1214..da4e82976d51 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/columns.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/columns.tsx @@ -6,31 +6,16 @@ */ import { css } from '@emotion/react'; -import React, { useCallback } from 'react'; -import { head } from 'lodash/fp'; +import React from 'react'; import { euiLightVars } from '@kbn/ui-theme'; import type { EuiBasicTableColumn } from '@elastic/eui'; -import { useDispatch } from 'react-redux'; import { SourcererScopeName } from '../../../../common/store/sourcerer/model'; import { DefaultFieldRenderer } from '../../field_renderers/field_renderers'; -import type { - ManagedUsersTableColumns, - ManagedUserTable, - ObservedUsersTableColumns, - ObservedUserTable, - UserAnomalies, -} from './types'; +import type { ManagedUsersTableColumns, ManagedUserTable } from './types'; import * as i18n from './translations'; import { defaultToEmptyTag } from '../../../../common/components/empty_value'; -import { FormattedRelativePreferenceDate } from '../../../../common/components/formatted_date'; -import { AnomalyScores } from '../../../../common/components/ml/score/anomaly_scores'; -import { useGlobalTime } from '../../../../common/containers/use_global_time'; -import { scoreIntervalToDateTime } from '../../../../common/components/ml/score/score_interval_to_datetime'; -import { InputsModelId } from '../../../../common/store/inputs/constants'; -import { setAbsoluteRangeDatePicker } from '../../../../common/store/inputs/actions'; -import { getSourcererScopeId } from '../../../../helpers'; -const fieldColumn: EuiBasicTableColumn = { +const fieldColumn: EuiBasicTableColumn = { name: i18n.FIELD_COLUMN_TITLE, field: 'label', render: (label: string, { field }) => ( @@ -68,71 +53,3 @@ export const getManagedUserTableColumns = ( }, }, ]; - -function isAnomalies( - field: string | undefined, - values: UserAnomalies | unknown -): values is UserAnomalies { - return field === 'anomalies'; -} - -export const getObservedUserTableColumns = ( - contextID: string, - scopeId: string, - isDraggable: boolean -): ObservedUsersTableColumns => [ - fieldColumn, - { - name: i18n.VALUES_COLUMN_TITLE, - field: 'values', - render: (values: ObservedUserTable['values'], { field }) => { - if (isAnomalies(field, values) && values) { - return ; - } - - if (field === '@timestamp') { - return ; - } - - return ( - - ); - }, - }, -]; - -const AnomaliesField = ({ anomalies }: { anomalies: UserAnomalies }) => { - const { to, from } = useGlobalTime(); - const dispatch = useDispatch(); - - const narrowDateRange = useCallback( - (score, interval) => { - const fromTo = scoreIntervalToDateTime(score, interval); - dispatch( - setAbsoluteRangeDatePicker({ - id: InputsModelId.global, - from: fromTo.from, - to: fromTo.to, - }) - ); - }, - [dispatch] - ); - - return ( - - ); -}; diff --git a/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/hooks/use_observed_user_items.ts b/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/hooks/use_observed_user_items.ts deleted file mode 100644 index d6390b210d58..000000000000 --- a/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/hooks/use_observed_user_items.ts +++ /dev/null @@ -1,48 +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 { useMemo } from 'react'; -import * as i18n from '../translations'; -import type { ObservedUserData, ObservedUserTable } from '../types'; - -export const useObservedUserItems = (userData: ObservedUserData): ObservedUserTable[] => - useMemo( - () => - !userData.details - ? [] - : [ - { label: i18n.USER_ID, values: userData.details.user?.id, field: 'user.id' }, - { label: 'Domain', values: userData.details.user?.domain, field: 'user.domain' }, - { - label: i18n.MAX_ANOMALY_SCORE_BY_JOB, - field: 'anomalies', - values: userData.anomalies, - }, - { - label: i18n.FIRST_SEEN, - values: userData.firstSeen.date ? [userData.firstSeen.date] : undefined, - field: '@timestamp', - }, - { - label: i18n.LAST_SEEN, - values: userData.lastSeen.date ? [userData.lastSeen.date] : undefined, - field: '@timestamp', - }, - { - label: i18n.OPERATING_SYSTEM_TITLE, - values: userData.details.host?.os?.name, - field: 'host.os.name', - }, - { - label: i18n.FAMILY, - values: userData.details.host?.os?.family, - field: 'host.os.family', - }, - { label: i18n.IP_ADDRESSES, values: userData.details.host?.ip, field: 'host.ip' }, - ], - [userData.details, userData.anomalies, userData.firstSeen, userData.lastSeen] - ); diff --git a/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/managed_user.tsx b/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/managed_user.tsx index 590f120b1968..635cf6a2868f 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/managed_user.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/managed_user.tsx @@ -18,7 +18,7 @@ import { import React, { useMemo } from 'react'; import { FormattedMessage } from '@kbn/i18n-react'; import { css } from '@emotion/css'; -import type { UserDetailsLeftPanelTab } from '../../../../flyout/entity_details/user_details_left/tabs'; +import type { EntityDetailsLeftPanelTab } from '../../../../flyout/entity_details/shared/components/left_panel/left_panel_header'; import { UserAssetTableType } from '../../../../explore/users/store/model'; import type { ManagedUserFields } from '../../../../../common/search_strategy/security_solution/users/managed_details'; import { ManagedUserDatasetKey } from '../../../../../common/search_strategy/security_solution/users/managed_details'; @@ -47,7 +47,7 @@ export const ManagedUser = ({ managedUser: ManagedUserData; contextID: string; isDraggable: boolean; - openDetailsPanel: (tab: UserDetailsLeftPanelTab) => void; + openDetailsPanel: (tab: EntityDetailsLeftPanelTab) => void; }) => { const entraManagedUser = managedUser.data?.[ManagedUserDatasetKey.ENTRA]; const oktaManagedUser = managedUser.data?.[ManagedUserDatasetKey.OKTA]; diff --git a/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/managed_user_accordion.tsx b/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/managed_user_accordion.tsx index a03775f61cf2..ad8b089adc16 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/managed_user_accordion.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/managed_user_accordion.tsx @@ -11,7 +11,7 @@ import React from 'react'; import { css } from '@emotion/react'; import { FormattedMessage } from '@kbn/i18n-react'; import { get } from 'lodash/fp'; -import { UserDetailsLeftPanelTab } from '../../../../flyout/entity_details/user_details_left/tabs'; +import { EntityDetailsLeftPanelTab } from '../../../../flyout/entity_details/shared/components/left_panel/left_panel_header'; import { ExpandablePanel } from '../../../../flyout/shared/components/expandable_panel'; import type { ManagedUserFields } from '../../../../../common/search_strategy/security_solution/users/managed_details'; @@ -23,7 +23,7 @@ interface ManagedUserAccordionProps { title: string; managedUser: ManagedUserFields; tableType: UserAssetTableType; - openDetailsPanel: (tab: UserDetailsLeftPanelTab) => void; + openDetailsPanel: (tab: EntityDetailsLeftPanelTab) => void; } export const ManagedUserAccordion: React.FC = ({ @@ -66,8 +66,8 @@ export const ManagedUserAccordion: React.FC = ({ callback: () => openDetailsPanel( tableType === UserAssetTableType.assetOkta - ? UserDetailsLeftPanelTab.OKTA - : UserDetailsLeftPanelTab.ENTRA + ? EntityDetailsLeftPanelTab.OKTA + : EntityDetailsLeftPanelTab.ENTRA ), tooltip: ( { - const mockProps = { - observedUser: mockObservedUser, - contextID: '', - scopeId: '', - isDraggable: false, - }; - - it('renders', () => { - const { getByTestId } = render( - - - - ); - - expect(getByTestId('observedUser-data')).toBeInTheDocument(); - }); - - it('renders the formatted date', () => { - const { getByTestId } = render( - - - - ); - - expect(getByTestId('observedUser-data')).toHaveTextContent('Updated Feb 23, 2023'); - }); - - it('renders anomaly score', () => { - const { getByTestId } = render( - - - - ); - - expect(getByTestId('anomaly-score')).toHaveTextContent('17'); - }); -}); diff --git a/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/risk_score_field.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/risk_score_field.test.tsx deleted file mode 100644 index 48d927c97030..000000000000 --- a/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/risk_score_field.test.tsx +++ /dev/null @@ -1,46 +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 { render } from '@testing-library/react'; -import React from 'react'; -import { TestProviders } from '../../../../common/mock'; -import { RiskScoreField } from './risk_score_field'; -import { mockRiskScoreState } from './__mocks__'; -import { getEmptyValue } from '../../../../common/components/empty_value'; - -describe('RiskScoreField', () => { - it('renders', () => { - const { getByTestId } = render( - - - - ); - - expect(getByTestId('user-details-risk-score')).toBeInTheDocument(); - expect(getByTestId('user-details-risk-score')).toHaveTextContent('70'); - }); - - it('does not render content when the license is invalid', () => { - const { queryByTestId } = render( - - - - ); - - expect(queryByTestId('user-details-risk-score')).not.toBeInTheDocument(); - }); - - it('renders empty tag when risk score is undefined', () => { - const { getByTestId } = render( - - - - ); - - expect(getByTestId('user-details-risk-score')).toHaveTextContent(getEmptyValue()); - }); -}); diff --git a/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/risk_score_field.tsx b/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/risk_score_field.tsx deleted file mode 100644 index fab77b92582f..000000000000 --- a/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/risk_score_field.tsx +++ /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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { EuiFlexItem, EuiFlexGroup, useEuiFontSize, useEuiTheme } from '@elastic/eui'; - -import React from 'react'; -import { css } from '@emotion/react'; - -import styled from 'styled-components'; -import * as i18n from './translations'; - -import { RiskScoreEntity } from '../../../../../common/search_strategy'; -import { getEmptyTagValue } from '../../../../common/components/empty_value'; -import { RiskScoreLevel } from '../../../../entity_analytics/components/severity/common'; -import type { RiskScoreState } from '../../../../entity_analytics/api/hooks/use_risk_score'; -import { RiskScoreDocTooltip } from '../../../../overview/components/common'; - -export const TooltipContainer = styled.div` - padding: ${({ theme }) => theme.eui.euiSizeS}; -`; - -export const RiskScoreField = ({ - riskScoreState, -}: { - riskScoreState: RiskScoreState; -}) => { - const { euiTheme } = useEuiTheme(); - const { fontSize: xsFontSize } = useEuiFontSize('xs'); - const { data: userRisk, isAuthorized: isRiskScoreAuthorized } = riskScoreState; - const userRiskData = userRisk && userRisk.length > 0 ? userRisk[0] : undefined; - - if (!isRiskScoreAuthorized) { - return null; - } - - return ( - - - - {i18n.RISK_SCORE} - {': '} - - - {userRiskData ? ( - - - {Math.round(userRiskData.user.risk.calculated_score_norm)} - - - - - - - - - ) : ( - getEmptyTagValue() - )} - - ); -}; diff --git a/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/translations.ts b/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/translations.ts index ce5e34ce3249..ebeb5d26cf36 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/translations.ts +++ b/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/translations.ts @@ -81,49 +81,6 @@ export const FIELD_COLUMN_TITLE = i18n.translate( } ); -export const USER_ID = i18n.translate('xpack.securitySolution.timeline.userDetails.userIdLabel', { - defaultMessage: 'User ID', -}); - -export const MAX_ANOMALY_SCORE_BY_JOB = i18n.translate( - 'xpack.securitySolution.timeline.userDetails.maxAnomalyScoreByJobLabel', - { - defaultMessage: 'Max anomaly score by job', - } -); - -export const FIRST_SEEN = i18n.translate( - 'xpack.securitySolution.timeline.userDetails.firstSeenLabel', - { - defaultMessage: 'First seen', - } -); - -export const LAST_SEEN = i18n.translate( - 'xpack.securitySolution.timeline.userDetails.lastSeenLabel', - { - defaultMessage: 'Last seen', - } -); - -export const OPERATING_SYSTEM_TITLE = i18n.translate( - 'xpack.securitySolution.timeline.userDetails.hostOsNameLabel', - { - defaultMessage: 'Operating system', - } -); - -export const FAMILY = i18n.translate('xpack.securitySolution.timeline.userDetails.familyLabel', { - defaultMessage: 'Family', -}); - -export const IP_ADDRESSES = i18n.translate( - 'xpack.securitySolution.timeline.userDetails.ipAddressesLabel', - { - defaultMessage: 'IP addresses', - } -); - export const NO_ACTIVE_INTEGRATION_TITLE = i18n.translate( 'xpack.securitySolution.timeline.userDetails.noActiveIntegrationTitle', { @@ -168,13 +125,6 @@ export const CLOSE_BUTTON = i18n.translate( } ); -export const OBSERVED_USER_INSPECT_TITLE = i18n.translate( - 'xpack.securitySolution.timeline.userDetails.observedUserInspectTitle', - { - defaultMessage: 'Observed user', - } -); - export const MANAGED_USER_INSPECT_TITLE = i18n.translate( 'xpack.securitySolution.timeline.userDetails.managedUserInspectTitle', { diff --git a/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/types.ts b/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/types.ts index edefb6ac7510..721ba1737070 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/types.ts +++ b/x-pack/plugins/security_solution/public/timelines/components/side_panel/new_user_detail/types.ts @@ -7,44 +7,17 @@ import type { EuiBasicTableColumn } from '@elastic/eui'; import type { SearchTypes } from '../../../../../common/detection_engine/types'; -import type { UserItem } from '../../../../../common/search_strategy'; import type { ManagedUserHits } from '../../../../../common/search_strategy/security_solution/users/managed_details'; -import type { AnomalyTableProviderChildrenProps } from '../../../../common/components/ml/anomaly/anomaly_table_provider'; - -export interface ObservedUserTable { - values: string[] | null | undefined | UserAnomalies; - field: string; -} export interface ManagedUserTable { value: SearchTypes[]; field?: string; } -export type ObservedUsersTableColumns = Array>; export type ManagedUsersTableColumns = Array>; -export interface ObservedUserData { - isLoading: boolean; - details: UserItem; - firstSeen: FirstLastSeenData; - lastSeen: FirstLastSeenData; - anomalies: UserAnomalies; -} - export interface ManagedUserData { isLoading: boolean; data: ManagedUserHits | undefined; isIntegrationEnabled: boolean; } - -export interface FirstLastSeenData { - date: string | null | undefined; - isLoading: boolean; -} - -export interface UserAnomalies { - isLoading: AnomalyTableProviderChildrenProps['isLoadingAnomaliesData']; - anomalies: AnomalyTableProviderChildrenProps['anomaliesData']; - jobNameById: AnomalyTableProviderChildrenProps['jobNameById']; -} diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/host_name.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/host_name.test.tsx index 1535b05a97a4..437f8be9de10 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/host_name.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/host_name.test.tsx @@ -17,6 +17,23 @@ import { StatefulEventContext } from '../../../../../common/components/events_vi import { createTelemetryServiceMock } from '../../../../../common/lib/telemetry/telemetry_service.mock'; const mockedTelemetry = createTelemetryServiceMock(); +const mockUseIsExperimentalFeatureEnabled = jest.fn(); +const mockOpenRightPanel = jest.fn(); + +jest.mock('../../../../../common/hooks/use_experimental_features', () => ({ + useIsExperimentalFeatureEnabled: () => mockUseIsExperimentalFeatureEnabled, +})); + +jest.mock('@kbn/expandable-flyout/src/context', () => { + const original = jest.requireActual('@kbn/expandable-flyout/src/context'); + + return { + ...original, + useExpandableFlyoutContext: () => ({ + openRightPanel: mockOpenRightPanel, + }), + }; +}); jest.mock('react-redux', () => { const origin = jest.requireActual('react-redux'); @@ -197,4 +214,27 @@ describe('HostName', () => { expect(toggleExpandedDetail).not.toHaveBeenCalled(); }); }); + + test('it should open expandable flyout if timeline is not in context and experimental flag is enabled', async () => { + mockUseIsExperimentalFeatureEnabled.mockReturnValue(true); + const context = { + enableHostDetailsFlyout: true, + enableIpDetailsFlyout: true, + timelineID: 'fake-timeline', + tabType: TimelineTabs.query, + }; + const wrapper = mount( + + + + + + ); + + wrapper.find('[data-test-subj="host-details-button"]').last().simulate('click'); + await waitFor(() => { + expect(mockOpenRightPanel).toHaveBeenCalled(); + expect(toggleExpandedDetail).not.toHaveBeenCalled(); + }); + }); }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/host_name.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/host_name.tsx index 37503f7b905e..c6b8d4f2d4cd 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/host_name.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/host_name.tsx @@ -9,9 +9,13 @@ import React, { useCallback, useContext, useMemo } from 'react'; import type { EuiButtonEmpty, EuiButtonIcon } from '@elastic/eui'; import { useDispatch } from 'react-redux'; import { isString } from 'lodash/fp'; +import { useExpandableFlyoutContext } from '@kbn/expandable-flyout'; +import { TableId } from '@kbn/securitysolution-data-table'; +import { useIsExperimentalFeatureEnabled } from '../../../../../common/hooks/use_experimental_features'; +import { HostPanelKey } from '../../../../../flyout/entity_details/host_right'; import type { ExpandedDetailType } from '../../../../../../common/types'; import { StatefulEventContext } from '../../../../../common/components/events_viewer/stateful_event_context'; -import { getScopedActions } from '../../../../../helpers'; +import { getScopedActions, isTimelineScope } from '../../../../../helpers'; import { HostDetailsLink } from '../../../../../common/components/links'; import { TimelineId, TimelineTabs } from '../../../../../../common/types/timeline'; import { DefaultDraggable } from '../../../../../common/components/draggables'; @@ -46,6 +50,9 @@ const HostNameComponent: React.FC = ({ title, value, }) => { + const isNewHostDetailsFlyoutEnabled = useIsExperimentalFeatureEnabled('newHostDetailsFlyout'); + const { openRightPanel } = useExpandableFlyoutContext(); + const dispatch = useDispatch(); const eventContext = useContext(StatefulEventContext); const hostName = `${value}`; @@ -58,31 +65,55 @@ const HostNameComponent: React.FC = ({ if (onClick) { onClick(); } + if (eventContext && isInTimelineContext) { const { timelineID, tabType } = eventContext; - const updatedExpandedDetail: ExpandedDetailType = { - panelView: 'hostDetail', - params: { - hostName, - }, - }; - const scopedActions = getScopedActions(timelineID); - if (scopedActions) { - dispatch( - scopedActions.toggleDetailPanel({ - ...updatedExpandedDetail, - id: timelineID, - tabType: tabType as TimelineTabs, - }) - ); - } - if (timelineID === TimelineId.active && tabType === TimelineTabs.query) { - activeTimeline.toggleExpandedDetail({ ...updatedExpandedDetail }); + if (isNewHostDetailsFlyoutEnabled && !isTimelineScope(timelineID)) { + openRightPanel({ + id: HostPanelKey, + params: { + hostName, + contextID: contextId, + scopeId: TableId.alertsOnAlertsPage, + isDraggable, + }, + }); + } else { + const updatedExpandedDetail: ExpandedDetailType = { + panelView: 'hostDetail', + params: { + hostName, + }, + }; + const scopedActions = getScopedActions(timelineID); + if (scopedActions) { + dispatch( + scopedActions.toggleDetailPanel({ + ...updatedExpandedDetail, + id: timelineID, + tabType: tabType as TimelineTabs, + }) + ); + } + + if (timelineID === TimelineId.active && tabType === TimelineTabs.query) { + activeTimeline.toggleExpandedDetail({ ...updatedExpandedDetail }); + } } } }, - [onClick, eventContext, isInTimelineContext, hostName, dispatch] + [ + onClick, + eventContext, + isInTimelineContext, + isNewHostDetailsFlyoutEnabled, + openRightPanel, + hostName, + contextId, + isDraggable, + dispatch, + ] ); // The below is explicitly defined this way as the onClick takes precedence when it and the href are both defined diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index 9942bbf4508e..cbbd515a86e1 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -32020,7 +32020,6 @@ "xpack.securitySolution.timeline.properties.timelineToggleButtonAriaLabel": "{isOpen, select, false {Ouvrir} true {Fermer} other {Bascule}} la chronologie {title}", "xpack.securitySolution.timeline.saveTimeline.modal.warning.title": "Vous avez une {timeline} non enregistrée. Voulez-vous l'enregistrer ?", "xpack.securitySolution.timeline.searchBoxPlaceholder": "par ex. nom ou description de {timeline}", - "xpack.securitySolution.timeline.userDetails.observedUserUpdatedTime": "Mis à jour {time}", "xpack.securitySolution.timeline.userDetails.updatedTime": "Mis à jour {time}", "xpack.securitySolution.timeline.youAreInAnEventRendererScreenReaderOnly": "Vous êtes dans un outil de rendu d'événement pour la ligne : {row}. Appuyez sur la touche fléchée vers le haut pour quitter et revenir à la ligne en cours, ou sur la touche fléchée vers le bas pour quitter et passer à la ligne suivante.", "xpack.securitySolution.timeline.youAreInATableCellScreenReaderOnly": "Vous êtes dans une cellule de tableau. Ligne : {row}, colonne : {column}", @@ -36361,25 +36360,17 @@ "xpack.securitySolution.timeline.userDetails.addExternalIntegrationButton": "Ajouter des intégrations externes", "xpack.securitySolution.timeline.userDetails.closeButton": "fermer", "xpack.securitySolution.timeline.userDetails.failManagedUserDescription": "Impossible de lancer la recherche sur des données gérées par l'utilisateur", - "xpack.securitySolution.timeline.userDetails.familyLabel": "Famille", "xpack.securitySolution.timeline.userDetails.fieldColumnTitle": "Champ", - "xpack.securitySolution.timeline.userDetails.firstSeenLabel": "Vu en premier", - "xpack.securitySolution.timeline.userDetails.hostOsNameLabel": "Système d'exploitation", - "xpack.securitySolution.timeline.userDetails.ipAddressesLabel": "Adresses IP", - "xpack.securitySolution.timeline.userDetails.lastSeenLabel": "Vu en dernier", "xpack.securitySolution.timeline.userDetails.managedBadge": "GÉRÉ", "xpack.securitySolution.timeline.userDetails.managedDataTitle": "Données gérées", "xpack.securitySolution.timeline.userDetails.managedUserInspectTitle": "Géré par l'utilisateur", - "xpack.securitySolution.timeline.userDetails.maxAnomalyScoreByJobLabel": "Score maximal d'anomalie par tâche", "xpack.securitySolution.timeline.userDetails.noActiveIntegrationText": "Les intégrations externes peuvent fournir des métadonnées supplémentaires et vous aider à gérer les utilisateurs.", "xpack.securitySolution.timeline.userDetails.noActiveIntegrationTitle": "Vous n'avez aucune intégration active.", "xpack.securitySolution.timeline.userDetails.noAzureDataText": "Si vous vous attendiez à voir des métadonnées pour cet utilisateur, assurez-vous d'avoir correctement configuré vos intégrations.", "xpack.securitySolution.timeline.userDetails.noAzureDataTitle": "Métadonnées introuvables pour cet utilisateur", "xpack.securitySolution.timeline.userDetails.observedBadge": "OBSERVÉ", "xpack.securitySolution.timeline.userDetails.observedDataTitle": "Données observées", - "xpack.securitySolution.timeline.userDetails.observedUserInspectTitle": "Utilisateur observé", "xpack.securitySolution.timeline.userDetails.riskScoreLabel": "Score de risque", - "xpack.securitySolution.timeline.userDetails.userIdLabel": "ID utilisateur", "xpack.securitySolution.timeline.userDetails.userLabel": "Utilisateur", "xpack.securitySolution.timeline.userDetails.valuesColumnTitle": "Valeurs", "xpack.securitySolution.timelineEvents.errorSearchDescription": "Une erreur s'est produite lors de la recherche d'événements de la chronologie", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index d569cab16ee9..f0575cc0496f 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -32019,7 +32019,6 @@ "xpack.securitySolution.timeline.properties.timelineToggleButtonAriaLabel": "タイムライン\"{title}\"を{isOpen, select, false {開く} true {閉じる} other {切り替え}}", "xpack.securitySolution.timeline.saveTimeline.modal.warning.title": "保存されていない{timeline}があります。保存しますか?", "xpack.securitySolution.timeline.searchBoxPlaceholder": "例:{timeline}名または説明", - "xpack.securitySolution.timeline.userDetails.observedUserUpdatedTime": "{time}を更新しました", "xpack.securitySolution.timeline.userDetails.updatedTime": "{time}を更新しました", "xpack.securitySolution.timeline.youAreInAnEventRendererScreenReaderOnly": "行{row}のイベントレンダラーを表示しています。上矢印キーを押すと、終了して現在の行に戻ります。下矢印キーを押すと、終了して次の行に進みます。", "xpack.securitySolution.timeline.youAreInATableCellScreenReaderOnly": "表セルの行{row}、列{column}にいます", @@ -36360,25 +36359,17 @@ "xpack.securitySolution.timeline.userDetails.addExternalIntegrationButton": "外部統合を追加", "xpack.securitySolution.timeline.userDetails.closeButton": "閉じる", "xpack.securitySolution.timeline.userDetails.failManagedUserDescription": "ユーザーが管理するデータで検索を実行できませんでした", - "xpack.securitySolution.timeline.userDetails.familyLabel": "ファミリー", "xpack.securitySolution.timeline.userDetails.fieldColumnTitle": "フィールド", - "xpack.securitySolution.timeline.userDetails.firstSeenLabel": "初回の認識", - "xpack.securitySolution.timeline.userDetails.hostOsNameLabel": "オペレーティングシステム", - "xpack.securitySolution.timeline.userDetails.ipAddressesLabel": "IP アドレス", - "xpack.securitySolution.timeline.userDetails.lastSeenLabel": "前回の認識", "xpack.securitySolution.timeline.userDetails.managedBadge": "管理対象", "xpack.securitySolution.timeline.userDetails.managedDataTitle": "管理対象のデータ", "xpack.securitySolution.timeline.userDetails.managedUserInspectTitle": "管理対象のユーザー", - "xpack.securitySolution.timeline.userDetails.maxAnomalyScoreByJobLabel": "ジョブ別の最高異常スコア", "xpack.securitySolution.timeline.userDetails.noActiveIntegrationText": "外部統合は追加のメタデータを提供し、ユーザーの管理を支援できます。", "xpack.securitySolution.timeline.userDetails.noActiveIntegrationTitle": "アクティブな統合がありません", "xpack.securitySolution.timeline.userDetails.noAzureDataText": "このユーザーのメタデータが表示されることが想定される場合は、統合を正しく構成したことを確認してください。", "xpack.securitySolution.timeline.userDetails.noAzureDataTitle": "このユーザーのメタデータが見つかりません", "xpack.securitySolution.timeline.userDetails.observedBadge": "観測済み", "xpack.securitySolution.timeline.userDetails.observedDataTitle": "観測されたデータ", - "xpack.securitySolution.timeline.userDetails.observedUserInspectTitle": "観測されたユーザー", "xpack.securitySolution.timeline.userDetails.riskScoreLabel": "リスクスコア", - "xpack.securitySolution.timeline.userDetails.userIdLabel": "ユーザーID", "xpack.securitySolution.timeline.userDetails.userLabel": "ユーザー", "xpack.securitySolution.timeline.userDetails.valuesColumnTitle": "値", "xpack.securitySolution.timelineEvents.errorSearchDescription": "タイムラインイベント検索でエラーが発生しました", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 06fe50fdae46..2a5c081a8d01 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -32001,7 +32001,6 @@ "xpack.securitySolution.timeline.properties.timelineToggleButtonAriaLabel": "{isOpen, select, false {打开} true {关闭} other {切换}}时间线 {title}", "xpack.securitySolution.timeline.saveTimeline.modal.warning.title": "您的 {timeline} 未保存。是否保存?", "xpack.securitySolution.timeline.searchBoxPlaceholder": "例如 {timeline} 名称或描述", - "xpack.securitySolution.timeline.userDetails.observedUserUpdatedTime": "已更新 {time}", "xpack.securitySolution.timeline.userDetails.updatedTime": "已更新 {time}", "xpack.securitySolution.timeline.youAreInAnEventRendererScreenReaderOnly": "您正处于第 {row} 行的事件呈现器中。按向上箭头键退出并返回当前行,或按向下箭头键退出并前进到下一行。", "xpack.securitySolution.timeline.youAreInATableCellScreenReaderOnly": "您处在表单元格中。行:{row},列:{column}", @@ -36342,25 +36341,17 @@ "xpack.securitySolution.timeline.userDetails.addExternalIntegrationButton": "添加外部集成", "xpack.securitySolution.timeline.userDetails.closeButton": "关闭", "xpack.securitySolution.timeline.userDetails.failManagedUserDescription": "无法对用户托管数据执行搜索", - "xpack.securitySolution.timeline.userDetails.familyLabel": "系列", "xpack.securitySolution.timeline.userDetails.fieldColumnTitle": "字段", - "xpack.securitySolution.timeline.userDetails.firstSeenLabel": "首次看到时间", - "xpack.securitySolution.timeline.userDetails.hostOsNameLabel": "操作系统", - "xpack.securitySolution.timeline.userDetails.ipAddressesLabel": "IP 地址", - "xpack.securitySolution.timeline.userDetails.lastSeenLabel": "最后看到时间", "xpack.securitySolution.timeline.userDetails.managedBadge": "托管", "xpack.securitySolution.timeline.userDetails.managedDataTitle": "托管数据", "xpack.securitySolution.timeline.userDetails.managedUserInspectTitle": "托管用户", - "xpack.securitySolution.timeline.userDetails.maxAnomalyScoreByJobLabel": "最大异常分数(按作业)", "xpack.securitySolution.timeline.userDetails.noActiveIntegrationText": "外部集成可提供其他元数据并帮助您管理用户。", "xpack.securitySolution.timeline.userDetails.noActiveIntegrationTitle": "您没有任何活动集成", "xpack.securitySolution.timeline.userDetails.noAzureDataText": "如果计划查看此用户的元数据,请确保已正确配置集成。", "xpack.securitySolution.timeline.userDetails.noAzureDataTitle": "找不到此用户的元数据", "xpack.securitySolution.timeline.userDetails.observedBadge": "已观察", "xpack.securitySolution.timeline.userDetails.observedDataTitle": "观察数据", - "xpack.securitySolution.timeline.userDetails.observedUserInspectTitle": "已观察用户", "xpack.securitySolution.timeline.userDetails.riskScoreLabel": "风险分数", - "xpack.securitySolution.timeline.userDetails.userIdLabel": "用户 ID", "xpack.securitySolution.timeline.userDetails.userLabel": "用户", "xpack.securitySolution.timeline.userDetails.valuesColumnTitle": "值", "xpack.securitySolution.timelineEvents.errorSearchDescription": "搜索时间线事件时发生错误", From e4cac3725f50ab16d1c8df543a4fd0e3fde1e843 Mon Sep 17 00:00:00 2001 From: Alexi Doak <109488926+doakalexi@users.noreply.github.com> Date: Thu, 4 Jan 2024 07:03:52 -0800 Subject: [PATCH 05/57] [ResponseOps][Alerting] Update the size of the input labels for the ES query and index threshold rule (#174137) Resolves https://github.com/elastic/kibana/issues/173857 ## Summary Updates the size of the input labels for the ES query and index threshold rules. It is helpful to hide whitespace when reviewing the code changes. **KQL** Screen Shot 2024-01-03 at 10 03 36 AM **Query DSL** Screen Shot 2024-01-03 at 10 04 06 AM **ES|QL** Screen Shot 2024-01-03 at 10 04 35 AM **Index Threshold** Screen Shot 2024-01-03 at 10 02 29 AM --- .../components/source_fields_select.tsx | 69 +++++++------- .../expression/es_query_expression.tsx | 95 +++++++++---------- .../expression/esql_query_expression.tsx | 46 ++++----- .../search_source_expression_form.tsx | 27 +++--- .../rule_common_expressions.tsx | 86 ++++++++--------- .../rule_types/threshold/expression.tsx | 95 ++++++++++--------- 6 files changed, 196 insertions(+), 222 deletions(-) diff --git a/x-pack/plugins/stack_alerts/public/rule_types/components/source_fields_select.tsx b/x-pack/plugins/stack_alerts/public/rule_types/components/source_fields_select.tsx index 3cd34a3cd001..79b2e6ca4ed1 100644 --- a/x-pack/plugins/stack_alerts/public/rule_types/components/source_fields_select.tsx +++ b/x-pack/plugins/stack_alerts/public/rule_types/components/source_fields_select.tsx @@ -7,7 +7,7 @@ import React, { useEffect, useState } from 'react'; import { uniqBy } from 'lodash'; -import { EuiComboBox, EuiFormRow, EuiSpacer, EuiTitle } from '@elastic/eui'; +import { EuiComboBox, EuiFormRow } from '@elastic/eui'; import { FieldOption } from '@kbn/triggers-actions-ui-plugin/public/common'; import { IErrorObject } from '@kbn/triggers-actions-ui-plugin/public'; import { FormattedMessage } from '@kbn/i18n-react'; @@ -77,44 +77,39 @@ export const SourceFields: React.FC = ({ fullWidth isInvalid={errors.length > 0 && sourceFields !== undefined} error={errors} + label={ + + } > - <> - -
- -
-
- - 0 && sourceFields !== undefined} + selectedOptions={(sourceFields || []).map((f) => ({ + label: f.label, + value: f.searchPath, + 'data-test-subj': `option-${f.label}`, + }))} + onChange={(options) => { + const fields: SourceField[] = []; + options.forEach((f) => { + if (f.value) { + fields.push({ label: f.label, searchPath: f.value }); } - )} - data-test-subj="sourceFields" - isInvalid={errors.length > 0 && sourceFields !== undefined} - selectedOptions={(sourceFields || []).map((f) => ({ - label: f.label, - value: f.searchPath, - 'data-test-subj': `option-${f.label}`, - }))} - onChange={(options) => { - const fields: SourceField[] = []; - options.forEach((f) => { - if (f.value) { - fields.push({ label: f.label, searchPath: f.value }); - } - }); - onChangeSourceFields(fields); - }} - options={sourceFieldsOptions} - /> - + }); + onChangeSourceFields(fields); + }} + options={sourceFieldsOptions} + /> ) : null; }; diff --git a/x-pack/plugins/stack_alerts/public/rule_types/es_query/expression/es_query_expression.tsx b/x-pack/plugins/stack_alerts/public/rule_types/es_query/expression/es_query_expression.tsx index 1cf901ecae8f..66a1ca82feff 100644 --- a/x-pack/plugins/stack_alerts/public/rule_types/es_query/expression/es_query_expression.tsx +++ b/x-pack/plugins/stack_alerts/public/rule_types/es_query/expression/es_query_expression.tsx @@ -11,7 +11,7 @@ import { lastValueFrom } from 'rxjs'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; -import { EuiFormRow, EuiLink, EuiSpacer, EuiTitle } from '@elastic/eui'; +import { EuiFormRow, EuiLink, EuiSpacer } from '@elastic/eui'; import { XJson } from '@kbn/es-ui-shared-plugin/public'; import { CodeEditor } from '@kbn/kibana-react-plugin/public'; @@ -195,60 +195,49 @@ export const EsQueryExpression: React.FC< return ( - -
+ -
-
- - - - { - setParam('index', indices); - - // reset expression fields if indices are deleted - if (indices.length === 0) { - setRuleProperty('params', { - timeField: ruleParams.timeField, - index: indices, - esQuery: DEFAULT_VALUES.QUERY, - size: DEFAULT_VALUES.SIZE, - thresholdComparator: DEFAULT_VALUES.THRESHOLD_COMPARATOR, - timeWindowSize: DEFAULT_VALUES.TIME_WINDOW_SIZE, - timeWindowUnit: DEFAULT_VALUES.TIME_WINDOW_UNIT, - threshold: DEFAULT_VALUES.THRESHOLD, - aggType: DEFAULT_VALUES.AGGREGATION_TYPE, - groupBy: DEFAULT_VALUES.GROUP_BY, - termSize: DEFAULT_VALUES.TERM_SIZE, - searchType: SearchType.esQuery, - excludeHitsFromPreviousRun: DEFAULT_VALUES.EXCLUDE_PREVIOUS_HITS, - sourceFields: undefined, - }); - } else { - await refreshEsFields(indices); - } - }} - onTimeFieldChange={(updatedTimeField: string) => setParam('timeField', updatedTimeField)} - /> - + } + > + { + setParam('index', indices); - -
- -
-
+ // reset expression fields if indices are deleted + if (indices.length === 0) { + setRuleProperty('params', { + timeField: ruleParams.timeField, + index: indices, + esQuery: DEFAULT_VALUES.QUERY, + size: DEFAULT_VALUES.SIZE, + thresholdComparator: DEFAULT_VALUES.THRESHOLD_COMPARATOR, + timeWindowSize: DEFAULT_VALUES.TIME_WINDOW_SIZE, + timeWindowUnit: DEFAULT_VALUES.TIME_WINDOW_UNIT, + threshold: DEFAULT_VALUES.THRESHOLD, + aggType: DEFAULT_VALUES.AGGREGATION_TYPE, + groupBy: DEFAULT_VALUES.GROUP_BY, + termSize: DEFAULT_VALUES.TERM_SIZE, + searchType: SearchType.esQuery, + excludeHitsFromPreviousRun: DEFAULT_VALUES.EXCLUDE_PREVIOUS_HITS, + sourceFields: undefined, + }); + } else { + await refreshEsFields(indices); + } + }} + onTimeFieldChange={(updatedTimeField: string) => setParam('timeField', updatedTimeField)} + /> + } + label={ + + } > - -
+ -
-
- - + } + > { @@ -215,20 +215,17 @@ export const EsqlQueryExpression: React.FC< errors={errors.sourceFields} /> - -
- -
-
- 0 && timeField !== undefined} error={errors.timeField} + label={ + + } > - -
- -
-
- - + 0} error={errors.timeWindowSize} + label={ + + } > - -
+ -
-
- - + } + > + +
{Boolean(dataView?.id) && ( <> diff --git a/x-pack/plugins/stack_alerts/public/rule_types/es_query/rule_common_expressions/rule_common_expressions.tsx b/x-pack/plugins/stack_alerts/public/rule_types/es_query/rule_common_expressions/rule_common_expressions.tsx index 313d3f586c73..c356104ed831 100644 --- a/x-pack/plugins/stack_alerts/public/rule_types/es_query/rule_common_expressions/rule_common_expressions.tsx +++ b/x-pack/plugins/stack_alerts/public/rule_types/es_query/rule_common_expressions/rule_common_expressions.tsx @@ -7,15 +7,7 @@ import React, { useEffect, useState } from 'react'; import { FormattedMessage } from '@kbn/i18n-react'; -import { - EuiCheckbox, - EuiFlexGroup, - EuiFlexItem, - EuiFormRow, - EuiIconTip, - EuiSpacer, - EuiTitle, -} from '@elastic/eui'; +import { EuiCheckbox, EuiFormRow, EuiIconTip, EuiSpacer } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { builtInAggregationTypes, @@ -98,22 +90,23 @@ export const RuleCommonExpressions: React.FC = ({ }, [groupBy]); return ( <> - -

+ {' '} - -

-
- - + />, + , + ]} + > + +
{aggType && builtInAggregationTypes[aggType].fieldRequired ? ( = ({ onChangeWindowUnit={onChangeWindowUnit} /> - - - -
- -
-
-
- + , = ({ defaultMessage: 'Specify the number of documents to pass to the configured actions when the threshold condition is met.', })} - /> - -
- - + />, + ]} + > + +
) : null} - -
+ -
-
- - { - setRuleParams('index', indices); + } + > + { + setRuleParams('index', indices); - // reset expression fields if indices are deleted - if (indices.length === 0) { - setRuleProperty('params', { - ...ruleParams, - index: indices, - aggType: DEFAULT_VALUES.AGGREGATION_TYPE, - termSize: DEFAULT_VALUES.TERM_SIZE, - thresholdComparator: DEFAULT_VALUES.THRESHOLD_COMPARATOR, - timeWindowSize: DEFAULT_VALUES.TIME_WINDOW_SIZE, - timeWindowUnit: DEFAULT_VALUES.TIME_WINDOW_UNIT, - groupBy: DEFAULT_VALUES.GROUP_BY, - threshold: DEFAULT_VALUES.THRESHOLD, - timeField: '', - }); - } else { - await refreshEsFields(indices); + // reset expression fields if indices are deleted + if (indices.length === 0) { + setRuleProperty('params', { + ...ruleParams, + index: indices, + aggType: DEFAULT_VALUES.AGGREGATION_TYPE, + termSize: DEFAULT_VALUES.TERM_SIZE, + thresholdComparator: DEFAULT_VALUES.THRESHOLD_COMPARATOR, + timeWindowSize: DEFAULT_VALUES.TIME_WINDOW_SIZE, + timeWindowUnit: DEFAULT_VALUES.TIME_WINDOW_UNIT, + groupBy: DEFAULT_VALUES.GROUP_BY, + threshold: DEFAULT_VALUES.THRESHOLD, + timeField: '', + }); + } else { + await refreshEsFields(indices); + } + }} + onTimeFieldChange={(updatedTimeField: string) => + setRuleParams('timeField', updatedTimeField) } - }} - onTimeFieldChange={(updatedTimeField: string) => - setRuleParams('timeField', updatedTimeField) - } - /> + /> + - -
+ -
-
- - - setRuleParams('aggType', selectedAggType) } - /> + > + + setRuleParams('aggType', selectedAggType) + } + /> + {aggType && builtInAggregationTypes[aggType].fieldRequired ? ( Date: Thu, 4 Jan 2024 08:17:41 -0700 Subject: [PATCH 06/57] [Dashboard] Update embed mode test screenshot (#174193) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes https://github.com/elastic/kibana/issues/163207 ## Summary This PR updates the embed mode baseline screenshot so that the failing test can be unskipped. This test is, unfortunately, very fragile because the font rendering is prone to changing between Chrome updates - however, there isn't really a better way of checking for rendering issues, so we'll have to continue just updating the baseline whenever a failure happens 🙈 ### Checklist - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [x] [Flaky Test Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was used on any tests changed: - Flaky test runner: https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/4749 ![image](https://github.com/elastic/kibana/assets/8698078/eeb87dca-4542-4333-af8b-58d07a8c911e) ### For maintainers - [ ] This was checked for breaking API changes and was [labeled appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) --- .../apps/dashboard/group5/embed_mode.ts | 3 +-- .../baseline/dashboard_embed_mode.png | Bin 129613 -> 72266 bytes 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/test/functional/apps/dashboard/group5/embed_mode.ts b/test/functional/apps/dashboard/group5/embed_mode.ts index fc7b92ab5fb8..25eabca77f71 100644 --- a/test/functional/apps/dashboard/group5/embed_mode.ts +++ b/test/functional/apps/dashboard/group5/embed_mode.ts @@ -56,8 +56,7 @@ export default function ({ await browser.setWindowSize(1300, 900); }); - // FLAKY: https://github.com/elastic/kibana/issues/163207 - describe.skip('default URL params', () => { + describe('default URL params', () => { it('hides the chrome', async () => { const globalNavShown = await globalNav.exists(); expect(globalNavShown).to.be(true); diff --git a/test/functional/screenshots/baseline/dashboard_embed_mode.png b/test/functional/screenshots/baseline/dashboard_embed_mode.png index 592cd6c4ff4036976b571165fcda8938f93f9d6d..c96c621a8c45b7ca60504c4165adc5cd600d74f8 100644 GIT binary patch literal 72266 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%0DG6TTpPN@Z-E87z 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
    #)ye8M^&|7sV2JkE< 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 z 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 From 5fa14686e5c6b3edffb338c3029a46a4316fdfca Mon Sep 17 00:00:00 2001 From: Paul Tavares <56442535+paul-tavares@users.noreply.github.com> Date: Thu, 4 Jan 2024 10:22:41 -0500 Subject: [PATCH 07/57] [Security solution][Endpoint] Additional changes to response action APIs in support of SentinelOne (#173882) ## Summary PR makes additional changes to Endpoint (kibana) response action APIs in support of 3rd party EDR systems and support for SentinelOne. Changes include: - `release` response action support for SentinelOne - Action responses for SentinelOne `isolate` and `release` are now written to the responses index (thanks to [this PR](https://github.com/elastic/elasticsearch/pull/103555)) - Action Details and List APIs now return `agentType` and support 3rd party EDR response actions - SentinelOne response actions are now returned and in the expected state (completed) - Added feature usage reporting to response actions client base class (sent when action request is written to ES index) - Added method to SentinelOne actions client to retrieve agent details - Host name for SentinelOne is now stored along with the Action Request document - Refactored action details and action list services to use common methods for: - fetching the action responses from ES - building the `ActionDetails` record for each action - Made several types (mostly around response action responses) to be generic to provided the ability to narrow the `output` type --- .../endpoint_action_generator.ts | 70 ++++-- .../service/response_actions/type_guards.ts | 40 +++ .../common/endpoint/types/actions.ts | 56 ++++- .../common/endpoint/types/index.ts | 1 + .../common/endpoint/types/utility_types.ts | 21 ++ .../endpoint_action_failure_message.tsx | 2 +- .../execute_action_host_response.test.tsx | 18 +- .../execute_action_host_response.tsx | 5 +- .../execute_action.tsx | 20 +- .../components/action_success.tsx | 2 +- .../hooks/use_console_action_submitter.tsx | 30 +-- .../components/endpoint_responder/types.ts | 5 +- .../components/action_log_expanded_tray.tsx | 19 +- .../use_get_action_details.ts | 14 +- .../use_get_automated_action_list.ts | 1 + .../endpoint/common/response_actions.ts | 49 ++-- .../server/endpoint/mocks.ts | 3 +- .../routes/actions/response_actions.test.ts | 3 +- .../routes/actions/response_actions.ts | 4 +- .../endpoint/routes/actions/status.test.ts | 3 + .../actions/action_details_by_id.test.ts | 2 + .../services/actions/action_details_by_id.ts | 70 +----- .../services/actions/action_list.test.ts | 45 ++-- .../endpoint/services/actions/action_list.ts | 55 +---- .../clients/endpoint_actions_client.ts | 11 +- .../services/actions/clients/errors.ts | 4 +- .../get_response_actions_client.test.ts | 3 +- .../lib/base_response_actions_client.test.ts | 36 ++- .../lib/base_response_actions_client.ts | 48 +++- .../services/actions/clients/mocks.ts | 37 +-- .../actions/clients/sentinelone/mock.ts | 177 +++++++++++++ .../sentinel_one_actions_client.test.ts | 143 +++++++++-- .../sentinel_one_actions_client.ts | 120 +++++++-- .../actions/clients/sentinelone/types.ts | 26 ++ .../endpoint/services/actions/create/index.ts | 20 +- .../endpoint/services/actions/create/types.ts | 3 +- .../actions/create/write_action_to_indices.ts | 6 +- .../actions/fetch_action_responses.test.ts | 232 ++++++++++++++++++ .../actions/fetch_action_responses.ts | 89 +++++++ .../server/endpoint/services/actions/mocks.ts | 14 +- .../endpoint/services/actions/utils.test.ts | 150 ++++++++++- .../server/endpoint/services/actions/utils.ts | 90 ++++++- .../services/feature_usage/feature_keys.ts | 48 ++++ .../endpoint/services/feature_usage/index.ts | 2 +- .../endpoint/services/feature_usage/mocks.ts | 2 + .../services/feature_usage/service.ts | 36 +-- .../utils/action_list_helpers.test.ts | 130 +--------- .../endpoint/utils/action_list_helpers.ts | 65 +---- .../endpoint/utils/{dump.ts => stringify.ts} | 2 +- .../endpoint/validators/base_validator.ts | 2 +- 50 files changed, 1448 insertions(+), 586 deletions(-) create mode 100644 x-pack/plugins/security_solution/common/endpoint/service/response_actions/type_guards.ts create mode 100644 x-pack/plugins/security_solution/server/endpoint/services/actions/clients/sentinelone/mock.ts create mode 100644 x-pack/plugins/security_solution/server/endpoint/services/actions/clients/sentinelone/types.ts create mode 100644 x-pack/plugins/security_solution/server/endpoint/services/actions/fetch_action_responses.test.ts create mode 100644 x-pack/plugins/security_solution/server/endpoint/services/actions/fetch_action_responses.ts create mode 100644 x-pack/plugins/security_solution/server/endpoint/services/feature_usage/feature_keys.ts rename x-pack/plugins/security_solution/server/endpoint/utils/{dump.ts => stringify.ts} (88%) 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 03f769e34c5d..f3f9bde438d6 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 @@ -26,6 +26,8 @@ import type { ResponseActionExecuteOutputContent, ResponseActionUploadOutputContent, ResponseActionUploadParameters, + EndpointActionResponseDataOutput, + WithAllKeys, } from '../types'; import { ActivityLogItemTypes } from '../types'; import { @@ -75,9 +77,11 @@ export class EndpointActionGenerator extends BaseDataGenerator { } /** Generates an endpoint action response */ - generateResponse( - overrides: DeepPartial = {} - ): LogsEndpointActionResponse { + generateResponse< + TOutputContent extends EndpointActionResponseDataOutput = EndpointActionResponseDataOutput + >( + overrides: DeepPartial> = {} + ): LogsEndpointActionResponse { const timeStamp = overrides['@timestamp'] ? new Date(overrides['@timestamp']) : new Date(); const startedAtTimes: number[] = []; @@ -91,7 +95,7 @@ export class EndpointActionGenerator extends BaseDataGenerator { const command = overrides?.EndpointActions?.data?.command ?? this.randomResponseActionCommand(); let output: ActionResponseOutput< ResponseActionGetFileOutputContent | ResponseActionExecuteOutputContent - > = overrides?.EndpointActions?.data?.output as ActionResponseOutput< + > = overrides?.EndpointActions?.data?.output as unknown as ActionResponseOutput< ResponseActionGetFileOutputContent | ResponseActionExecuteOutputContent >; @@ -168,7 +172,7 @@ export class EndpointActionGenerator extends BaseDataGenerator { error: undefined, }, overrides - ); + ) as LogsEndpointActionResponse; } generateResponseEsHit( @@ -180,13 +184,15 @@ export class EndpointActionGenerator extends BaseDataGenerator { } generateActionDetails< - TOutputType extends object = object, + TOutputContent extends EndpointActionResponseDataOutput = EndpointActionResponseDataOutput, TParameters extends EndpointActionDataParameterTypes = EndpointActionDataParameterTypes >( - overrides: DeepPartial> = {} - ): ActionDetails { - const details: ActionDetails = { + overrides: DeepPartial> = {} + ): ActionDetails { + const details: WithAllKeys = { + action: '123', agents: ['agent-a'], + agentType: 'endpoint', command: 'isolate', completedAt: '2022-04-30T16:08:47.449Z', hosts: { 'agent-a': { name: 'Host-agent-a' } }, @@ -209,6 +215,9 @@ export class EndpointActionGenerator extends BaseDataGenerator { wasSuccessful: true, }, }, + alertIds: undefined, + ruleId: undefined, + ruleName: undefined, }; const command = overrides.command ?? details.command; @@ -216,7 +225,7 @@ export class EndpointActionGenerator extends BaseDataGenerator { if (command === 'get-file') { if (!details.parameters) { ( - details as ActionDetails< + details as unknown as ActionDetails< ResponseActionGetFileOutputContent, ResponseActionGetFileParameters > @@ -226,14 +235,26 @@ export class EndpointActionGenerator extends BaseDataGenerator { } if (!details.outputs || Object.keys(details.outputs).length === 0) { - details.outputs = { + ( + details as unknown as ActionDetails< + ResponseActionGetFileOutputContent, + ResponseActionGetFileParameters + > + ).outputs = { [details.agents[0]]: { type: 'json', content: { code: 'ra_get-file_success', - path: '/some/file/txt', - size: 1234, zip_size: 123, + contents: [ + { + path: '/some/file/txt', + sha256: '1254', + size: 1234, + file_name: 'some-file.txt', + type: 'file', + }, + ], }, }, }; @@ -243,7 +264,7 @@ export class EndpointActionGenerator extends BaseDataGenerator { if (command === 'execute') { if (!details.parameters) { ( - details as ActionDetails< + details as unknown as ActionDetails< ResponseActionExecuteOutputContent, ResponseActionsExecuteParameters > @@ -256,7 +277,12 @@ export class EndpointActionGenerator extends BaseDataGenerator { } if (!details.outputs || Object.keys(details.outputs).length === 0) { - details.outputs = { + ( + details as unknown as ActionDetails< + ResponseActionExecuteOutputContent, + ResponseActionsExecuteParameters + > + ).outputs = { [details.agents[0]]: this.generateExecuteActionResponseOutput({ content: { output_file_id: getFileDownloadId(details, details.agents[0]), @@ -268,7 +294,7 @@ export class EndpointActionGenerator extends BaseDataGenerator { } if (command === 'upload') { - const uploadActionDetails = details as ActionDetails< + const uploadActionDetails = details as unknown as ActionDetails< ResponseActionUploadOutputContent, ResponseActionUploadParameters >; @@ -293,7 +319,7 @@ export class EndpointActionGenerator extends BaseDataGenerator { } return merge(details, overrides as ActionDetails) as unknown as ActionDetails< - TOutputType, + TOutputContent, TParameters >; } @@ -328,9 +354,11 @@ export class EndpointActionGenerator extends BaseDataGenerator { ); } - generateActivityLogActionResponse( - overrides: DeepPartial - ): EndpointActivityLogActionResponse { + generateActivityLogActionResponse< + TOutputContent extends EndpointActionResponseDataOutput = EndpointActionResponseDataOutput + >( + overrides: DeepPartial> + ): EndpointActivityLogActionResponse { return merge( { type: ActivityLogItemTypes.RESPONSE, @@ -359,7 +387,7 @@ export class EndpointActionGenerator extends BaseDataGenerator { } generateExecuteActionResponseOutput( - overrides?: Partial>> + overrides?: DeepPartial> ): ActionResponseOutput { return merge( { diff --git a/x-pack/plugins/security_solution/common/endpoint/service/response_actions/type_guards.ts b/x-pack/plugins/security_solution/common/endpoint/service/response_actions/type_guards.ts new file mode 100644 index 000000000000..7786c9ebb1f5 --- /dev/null +++ b/x-pack/plugins/security_solution/common/endpoint/service/response_actions/type_guards.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 type { + ActionDetails, + MaybeImmutable, + ResponseActionExecuteOutputContent, + ResponseActionsExecuteParameters, + ResponseActionUploadOutputContent, + ResponseActionUploadParameters, + ResponseActionGetFileOutputContent, + ResponseActionGetFileParameters, +} from '../../types'; + +type SomeObjectWithCommand = Pick; + +export const isUploadAction = ( + action: MaybeImmutable +): action is ActionDetails => { + return action.command === 'upload'; +}; + +export const isExecuteAction = ( + action: MaybeImmutable +): action is ActionDetails< + ResponseActionExecuteOutputContent, + ResponseActionsExecuteParameters +> => { + return action.command === 'execute'; +}; + +export const isGetFileAction = ( + action: MaybeImmutable +): action is ActionDetails => { + return action.command === 'get-file'; +}; 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 f2393c02c3b4..9b89954ee697 100644 --- a/x-pack/plugins/security_solution/common/endpoint/types/actions.ts +++ b/x-pack/plugins/security_solution/common/endpoint/types/actions.ts @@ -23,7 +23,9 @@ import type { export type ISOLATION_ACTIONS = 'isolate' | 'unisolate'; /** The output provided by some of the Endpoint responses */ -export interface ActionResponseOutput { +export interface ActionResponseOutput< + TOutputContent extends EndpointActionResponseDataOutput = EndpointActionResponseDataOutput +> { type: 'json' | 'text'; content: TOutputContent; } @@ -36,6 +38,7 @@ export interface ProcessesEntry { } export interface GetProcessesActionOutputContent { + code: string; entries: ProcessesEntry[]; } @@ -96,7 +99,7 @@ export const ActivityLogItemTypes = { interface EndpointActionFields< TParameters extends EndpointActionDataParameterTypes = EndpointActionDataParameterTypes, - TOutputContent extends object = object + TOutputContent extends EndpointActionResponseDataOutput = EndpointActionResponseDataOutput > { action_id: string; data: EndpointActionData; @@ -146,7 +149,9 @@ export interface LogsEndpointActionWithHosts extends LogsEndpointAction { * An Action response written by the endpoint to the Endpoint `.logs-endpoint.action.responses` datastream * @since v7.16 */ -export interface LogsEndpointActionResponse { +export interface LogsEndpointActionResponse< + TOutputContent extends EndpointActionResponseDataOutput = EndpointActionResponseDataOutput +> { '@timestamp': string; agent: { id: string | string[]; @@ -155,6 +160,7 @@ export interface LogsEndpointActionResponse, 'comment' | 'command' | 'output'>; + input_type: ResponseActionAgentType; }; error?: EcsError; } @@ -189,9 +195,19 @@ export type EndpointActionDataParameterTypes = | ResponseActionGetFileParameters | ResponseActionUploadParameters; +/** Output content of the different response actions */ +export type EndpointActionResponseDataOutput = + | Record // Empty object + | ResponseActionExecuteOutputContent + | ResponseActionGetFileOutputContent + | ResponseActionUploadOutputContent + | GetProcessesActionOutputContent + | SuspendProcessActionOutputContent + | KillProcessActionOutputContent; + export interface EndpointActionData< TParameters extends EndpointActionDataParameterTypes = EndpointActionDataParameterTypes, - TOutputContent extends object = object + TOutputContent extends EndpointActionResponseDataOutput = EndpointActionResponseDataOutput > { command: ResponseActionsApiCommandNames; comment?: string; @@ -226,6 +242,10 @@ export interface EndpointAction extends ActionRequestFields { }; } +/** + * The action response created in Fleet's index after the action has been successfully delivered to + * the endpoint + */ export interface EndpointActionResponse { '@timestamp': string; /** The id of the action for which this response is associated with */ @@ -250,11 +270,13 @@ export interface EndpointActivityLogAction { }; } -export interface EndpointActivityLogActionResponse { +export interface EndpointActivityLogActionResponse< + TOutputContent extends EndpointActionResponseDataOutput = EndpointActionResponseDataOutput +> { type: typeof ActivityLogItemTypes.RESPONSE; item: { id: string; - data: LogsEndpointActionResponse; + data: LogsEndpointActionResponse; }; } @@ -306,9 +328,11 @@ export interface HostIsolationResponse { } export type ProcessesRequestBody = TypeOf; -export interface ResponseActionApiResponse { +export interface ResponseActionApiResponse< + TOutputContent extends EndpointActionResponseDataOutput = EndpointActionResponseDataOutput +> { action?: string; - data: ActionDetails; + data: ActionDetails; } export interface EndpointPendingActions { @@ -334,11 +358,17 @@ export interface ActionDetailsAgentState { } export interface ActionDetails< - TOutputContent extends object = object, + TOutputContent extends EndpointActionResponseDataOutput = EndpointActionResponseDataOutput, TParameters extends EndpointActionDataParameterTypes = EndpointActionDataParameterTypes > { - /** The action id passed only if returnActionIdCommands contains the command */ + /** + * The action ID. This is a legacy property action and should no longer be used. Only here for + * backwards compatibility + * + * @deprecated + */ action?: string; + /** The action id */ id: string; /** @@ -389,13 +419,15 @@ export interface ActionDetails< alertIds?: string[]; ruleId?: string; ruleName?: string; + /** The agent type to where the response action was sent */ + agentType: ResponseActionAgentType; } export interface ActionDetailsApiResponse< - TOutputType extends object = object, + TOutputContent extends EndpointActionResponseDataOutput = EndpointActionResponseDataOutput, TParameters extends EndpointActionDataParameterTypes = EndpointActionDataParameterTypes > { - data: ActionDetails; + data: ActionDetails; } /** Action Details normally returned by Action List API response */ diff --git a/x-pack/plugins/security_solution/common/endpoint/types/index.ts b/x-pack/plugins/security_solution/common/endpoint/types/index.ts index 8f195b926e1f..4887d83493f5 100644 --- a/x-pack/plugins/security_solution/common/endpoint/types/index.ts +++ b/x-pack/plugins/security_solution/common/endpoint/types/index.ts @@ -12,6 +12,7 @@ import type { ManifestSchema } from '../schema/manifest'; export * from './actions'; export * from './os'; export * from './trusted_apps'; +export * from './utility_types'; export type { ConditionEntriesMap, ConditionEntry } from './exception_list_items'; /** diff --git a/x-pack/plugins/security_solution/common/endpoint/types/utility_types.ts b/x-pack/plugins/security_solution/common/endpoint/types/utility_types.ts index a70c8e124eb8..2fd25a2cc37d 100644 --- a/x-pack/plugins/security_solution/common/endpoint/types/utility_types.ts +++ b/x-pack/plugins/security_solution/common/endpoint/types/utility_types.ts @@ -17,3 +17,24 @@ export type PromiseResolvedValue> = T extends Promise = T extends Record ? { -readonly [K in keyof T]: DeepMutable } : T; + +/** + * Ensure that a given type includes all of its key, even if they are optional (value can still be `undefined`) + * + * @example + * interface Foo { + * one?: number; + * two: number; + * } + * const missingKeys: Foo = { two: 2 }; // ok + * + * const shouldHaveAllKeys: WithAllKeys = { two: 2 }; // TS Error + * + * const withAllKeys: WithAllKeys = { + * one: undefined, // All good now + * two: 2 + * } + */ +export type WithAllKeys = { + [k in keyof Required]: T[k]; +}; diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_action_failure_message/endpoint_action_failure_message.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_action_failure_message/endpoint_action_failure_message.tsx index 7e85a0d081ed..f9f982188ffa 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_action_failure_message/endpoint_action_failure_message.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_action_failure_message/endpoint_action_failure_message.tsx @@ -13,7 +13,7 @@ import { endpointActionResponseCodes } from '../endpoint_responder/lib/endpoint_ import type { ActionDetails, MaybeImmutable } from '../../../../common/endpoint/types'; interface EndpointActionFailureMessageProps { - action: MaybeImmutable>; + action: MaybeImmutable; 'data-test-subj'?: string; } diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_execute_action/execute_action_host_response.test.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_execute_action/execute_action_host_response.test.tsx index 04958e60b4de..a16f1f2007f5 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_execute_action/execute_action_host_response.test.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_execute_action/execute_action_host_response.test.tsx @@ -10,6 +10,7 @@ import type { ResponseActionExecuteOutputContent, ResponseActionsExecuteParameters, ActionDetails, + DeepMutable, } from '../../../../common/endpoint/types'; import React from 'react'; import { EndpointActionGenerator } from '../../../../common/endpoint/data_generators/endpoint_action_generator'; @@ -23,8 +24,8 @@ import { EXECUTE_OUTPUT_FILE_TRUNCATED_MESSAGE } from './execute_action_host_res describe('When using the `ExecuteActionHostResponse` component', () => { let render: () => ReturnType; let renderResult: ReturnType; - let renderProps: ExecuteActionHostResponseProps; - let action: ActionDetails; + let renderProps: DeepMutable; + let action: DeepMutable['action']; beforeEach(() => { const appTestContext = createAppRootMockRenderer(); @@ -32,7 +33,10 @@ describe('When using the `ExecuteActionHostResponse` component', () => { action = new EndpointActionGenerator('seed').generateActionDetails< ResponseActionExecuteOutputContent, ResponseActionsExecuteParameters - >({ command: 'execute', agents: ['agent-a'] }); + >({ + command: 'execute', + agents: ['agent-a'], + }); renderProps = { action, @@ -92,11 +96,11 @@ describe('When using the `ExecuteActionHostResponse` component', () => { }); it('should show `-` in output accordion when no output content', async () => { - (renderProps.action as ActionDetails).outputs = { + renderProps.action.outputs = { 'agent-a': { type: 'json', content: { - ...(renderProps.action as ActionDetails).outputs?.[action.agents[0]].content, + ...renderProps.action.outputs![action.agents[0]].content, stdout: '', }, }, @@ -109,11 +113,11 @@ describe('When using the `ExecuteActionHostResponse` component', () => { }); it('should NOT show the error accordion when no error content', async () => { - (renderProps.action as ActionDetails).outputs = { + renderProps.action.outputs = { 'agent-a': { type: 'json', content: { - ...(renderProps.action as ActionDetails).outputs?.[action.agents[0]].content, + ...renderProps.action.outputs![action.agents[0]].content, stderr: '', }, }, diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_execute_action/execute_action_host_response.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_execute_action/execute_action_host_response.tsx index 3c7b5818907a..43ff3ffca5a6 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_execute_action/execute_action_host_response.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_execute_action/execute_action_host_response.tsx @@ -10,13 +10,16 @@ import type { ActionDetails, MaybeImmutable, ResponseActionExecuteOutputContent, + ResponseActionsExecuteParameters, } from '../../../../common/endpoint/types'; import { EXECUTE_FILE_LINK_TITLE } from '../endpoint_response_actions_list/translations'; import { ResponseActionFileDownloadLink } from '../response_action_file_download_link'; import { ExecuteActionHostResponseOutput } from './execute_action_host_response_output'; export interface ExecuteActionHostResponseProps { - action: MaybeImmutable; + action: MaybeImmutable< + ActionDetails + >; agentId?: string; canAccessFileDownloadLink: boolean; 'data-test-subj'?: string; diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_responder/command_render_components/execute_action.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_responder/command_render_components/execute_action.tsx index 8192b6a08b07..7e19a0386001 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_responder/command_render_components/execute_action.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_responder/command_render_components/execute_action.tsx @@ -11,17 +11,24 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import type { ExecuteActionRequestBody } from '../../../../../common/api/endpoint'; import { useConsoleActionSubmitter } from '../hooks/use_console_action_submitter'; -import type { ResponseActionExecuteOutputContent } from '../../../../../common/endpoint/types'; +import type { + ResponseActionExecuteOutputContent, + ResponseActionsExecuteParameters, +} from '../../../../../common/endpoint/types'; import { useSendExecuteEndpoint } from '../../../hooks/response_actions/use_send_execute_endpoint_request'; import type { ActionRequestComponentProps } from '../types'; import { parsedExecuteTimeout } from '../lib/utils'; import { ExecuteActionHostResponse } from '../../endpoint_execute_action'; export const ExecuteActionResult = memo< - ActionRequestComponentProps<{ - command: string; - timeout?: string; - }> + ActionRequestComponentProps< + { + command: string; + timeout?: string; + }, + ResponseActionExecuteOutputContent, + ResponseActionsExecuteParameters + > >(({ command, setStore, store, status, setStatus, ResultComponent }) => { const actionCreator = useSendExecuteEndpoint(); const actionRequestBody = useMemo(() => { @@ -47,7 +54,8 @@ export const ExecuteActionResult = memo< const { result, actionDetails: completedActionDetails } = useConsoleActionSubmitter< ExecuteActionRequestBody, - ResponseActionExecuteOutputContent + ResponseActionExecuteOutputContent, + ResponseActionsExecuteParameters >({ ResultComponent, setStore, diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_responder/components/action_success.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_responder/components/action_success.tsx index 9f7a22ece872..ff495096dcbf 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_responder/components/action_success.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_responder/components/action_success.tsx @@ -11,7 +11,7 @@ import type { ActionDetails, MaybeImmutable } from '../../../../../common/endpoi import type { CommandExecutionResultComponent, CommandExecutionResultProps } from '../../console'; export interface ActionSuccessProps extends CommandExecutionResultProps { - action: MaybeImmutable>; + action: MaybeImmutable; ResultComponent: CommandExecutionResultComponent; } diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_responder/hooks/use_console_action_submitter.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_responder/hooks/use_console_action_submitter.tsx index 519072b0fd25..08c2907dde0e 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_responder/hooks/use_console_action_submitter.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_responder/hooks/use_console_action_submitter.tsx @@ -22,11 +22,12 @@ import type { Immutable, ResponseActionApiResponse, EndpointActionDataParameterTypes, + EndpointActionResponseDataOutput, } from '../../../../../common/endpoint/types'; import type { CommandExecutionComponentProps } from '../../console'; export interface ConsoleActionSubmitter< - TActionOutputContent extends object = object, + TOutputContent extends EndpointActionResponseDataOutput = EndpointActionResponseDataOutput, TParameters extends EndpointActionDataParameterTypes = EndpointActionDataParameterTypes > { /** @@ -34,14 +35,14 @@ export interface ConsoleActionSubmitter< * including pending, error conditions and generic success messages. */ result: JSX.Element; - actionDetails: Immutable> | undefined; + actionDetails: Immutable> | undefined; } /** * Command store state for response action api state. */ export interface CommandResponseActionApiState< - TActionOutputContent extends object = object, + TOutputContent extends EndpointActionResponseDataOutput = EndpointActionResponseDataOutput, TParameters extends EndpointActionDataParameterTypes = EndpointActionDataParameterTypes > { actionApiState?: { @@ -50,20 +51,20 @@ export interface CommandResponseActionApiState< actionId: string | undefined; error: IHttpFetchError | undefined; }; - actionDetails: ActionDetails | undefined; + actionDetails: ActionDetails | undefined; actionDetailsError: IHttpFetchError | undefined; }; } export interface UseConsoleActionSubmitterOptions< TReqBody extends BaseActionRequestBody = BaseActionRequestBody, - TActionOutputContent extends object = object, + TOutputContent extends EndpointActionResponseDataOutput = EndpointActionResponseDataOutput, TParameters extends EndpointActionDataParameterTypes = EndpointActionDataParameterTypes > extends Pick< CommandExecutionComponentProps< // eslint-disable-next-line @typescript-eslint/no-explicit-any any, - CommandResponseActionApiState + CommandResponseActionApiState >, 'ResultComponent' | 'setStore' | 'store' | 'status' | 'setStatus' > { @@ -99,7 +100,7 @@ export interface UseConsoleActionSubmitterOptions< */ export const useConsoleActionSubmitter = < TReqBody extends BaseActionRequestBody = BaseActionRequestBody, - TActionOutputContent extends object = object, + TOutputContent extends EndpointActionResponseDataOutput = EndpointActionResponseDataOutput, TParameters extends EndpointActionDataParameterTypes = EndpointActionDataParameterTypes >({ actionCreator, @@ -112,18 +113,17 @@ export const useConsoleActionSubmitter = < dataTestSubj, pendingMessage, successMessage, -}: UseConsoleActionSubmitterOptions< - TReqBody, - TActionOutputContent, +}: UseConsoleActionSubmitterOptions): ConsoleActionSubmitter< + TOutputContent, TParameters ->): ConsoleActionSubmitter => { +> => { const isMounted = useIsMounted(); const getTestId = useTestIdGenerator(dataTestSubj); const isPending = status === 'pending'; const currentActionState = useMemo< Immutable< - Required>['actionApiState'] + Required>['actionApiState'] > >( () => @@ -147,7 +147,7 @@ export const useConsoleActionSubmitter = < } = currentActionState.request; const { data: apiActionDetailsResponse, error: apiActionDetailsError } = useGetActionDetails< - TActionOutputContent, + TOutputContent, TParameters >(actionId ?? '-', { enabled: Boolean(actionId) && isPending, @@ -158,11 +158,11 @@ export const useConsoleActionSubmitter = < useEffect(() => { if (!actionRequestSent && actionRequestBody && isMounted()) { const updatedRequestState: Required< - CommandResponseActionApiState + CommandResponseActionApiState >['actionApiState']['request'] = { ...( currentActionState as Required< - CommandResponseActionApiState + CommandResponseActionApiState >['actionApiState'] ).request, sent: true, diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_responder/types.ts b/x-pack/plugins/security_solution/public/management/components/endpoint_responder/types.ts index d74cd7948d81..c2277576ff63 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_responder/types.ts +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_responder/types.ts @@ -10,6 +10,7 @@ import type { ManagedConsoleExtensionComponentProps } from '../console'; import type { HostMetadata, EndpointActionDataParameterTypes, + EndpointActionResponseDataOutput, } from '../../../../common/endpoint/types'; import type { CommandExecutionComponentProps } from '../console/types'; @@ -23,10 +24,10 @@ export type EndpointResponderExtensionComponentProps = ManagedConsoleExtensionCo export type ActionRequestComponentProps< TArgs extends object = object, - TActionOutputContent extends object = object, + TOutputContent extends EndpointActionResponseDataOutput = EndpointActionResponseDataOutput, TParameters extends EndpointActionDataParameterTypes = EndpointActionDataParameterTypes > = CommandExecutionComponentProps< { comment?: string } & TArgs, - CommandResponseActionApiState, + CommandResponseActionApiState, EndpointCommandDefinitionMeta >; diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/action_log_expanded_tray.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/action_log_expanded_tray.tsx index b70a74d839bc..aef96add0881 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/action_log_expanded_tray.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/action_log_expanded_tray.tsx @@ -9,6 +9,11 @@ import React, { memo, useMemo } from 'react'; import { EuiCodeBlock, EuiDescriptionList, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { css, euiStyled } from '@kbn/kibana-react-plugin/common'; import { map } from 'lodash'; +import { + isExecuteAction, + isGetFileAction, + isUploadAction, +} from '../../../../../common/endpoint/service/response_actions/type_guards'; import { EndpointUploadActionResult } from '../../endpoint_upload_action_result'; import { useUserPrivileges } from '../../../../common/components/user_privileges'; import { OUTPUT_MESSAGES } from '../translations'; @@ -18,10 +23,6 @@ import { ResponseActionFileDownloadLink } from '../../response_action_file_downl import { ExecuteActionHostResponse } from '../../endpoint_execute_action'; import { getEmptyValue } from '../../../../common/components/empty_value'; -import type { - ResponseActionUploadOutputContent, - ResponseActionUploadParameters, -} from '../../../../../common/endpoint/types'; import { type ActionDetails, type MaybeImmutable } from '../../../../../common/endpoint/types'; const emptyValue = getEmptyValue(); @@ -80,12 +81,6 @@ const StyledEuiFlexGroup = euiStyled(EuiFlexGroup).attrs({ overflow-y: auto; `; -const isUploadAction = ( - action: MaybeImmutable -): action is ActionDetails => { - return action.command === 'upload'; -}; - const OutputContent = memo<{ action: MaybeImmutable; 'data-test-subj'?: string }>( ({ action, 'data-test-subj': dataTestSubj }) => { const getTestId = useTestIdGenerator(dataTestSubj); @@ -122,7 +117,7 @@ const OutputContent = memo<{ action: MaybeImmutable; 'data-test-s return <>{OUTPUT_MESSAGES.hasFailed(command)}; } - if (command === 'get-file') { + if (isGetFileAction(action)) { return ( <> {OUTPUT_MESSAGES.wasSuccessful(command)} @@ -136,7 +131,7 @@ const OutputContent = memo<{ action: MaybeImmutable; 'data-test-s ); } - if (command === 'execute') { + if (isExecuteAction(action)) { return ( {action.agents.map((agentId) => ( diff --git a/x-pack/plugins/security_solution/public/management/hooks/response_actions/use_get_action_details.ts b/x-pack/plugins/security_solution/public/management/hooks/response_actions/use_get_action_details.ts index cf017536762d..01c09da5d9be 100644 --- a/x-pack/plugins/security_solution/public/management/hooks/response_actions/use_get_action_details.ts +++ b/x-pack/plugins/security_solution/public/management/hooks/response_actions/use_get_action_details.ts @@ -14,22 +14,26 @@ import { ACTION_DETAILS_ROUTE } from '../../../../common/endpoint/constants'; import type { ActionDetailsApiResponse, EndpointActionDataParameterTypes, + EndpointActionResponseDataOutput, } from '../../../../common/endpoint/types'; export const useGetActionDetails = < - TOutputType extends object = object, + TOutputContent extends EndpointActionResponseDataOutput = EndpointActionResponseDataOutput, TParameters extends EndpointActionDataParameterTypes = EndpointActionDataParameterTypes >( actionId: string, - options: UseQueryOptions, IHttpFetchError> = {} -): UseQueryResult, IHttpFetchError> => { + options: UseQueryOptions< + ActionDetailsApiResponse, + IHttpFetchError + > = {} +): UseQueryResult, IHttpFetchError> => { const http = useHttp(); - return useQuery, IHttpFetchError>({ + return useQuery, IHttpFetchError>({ queryKey: ['get-action-details', actionId], ...options, queryFn: () => { - return http.get>( + return http.get>( resolvePathVariables(ACTION_DETAILS_ROUTE, { action_id: actionId.trim() || 'undefined' }), { version: '2023-10-31', diff --git a/x-pack/plugins/security_solution/public/management/hooks/response_actions/use_get_automated_action_list.ts b/x-pack/plugins/security_solution/public/management/hooks/response_actions/use_get_automated_action_list.ts index dc6832ce04f4..03828cba319c 100644 --- a/x-pack/plugins/security_solution/public/management/hooks/response_actions/use_get_automated_action_list.ts +++ b/x-pack/plugins/security_solution/public/management/hooks/response_actions/use_get_automated_action_list.ts @@ -152,6 +152,7 @@ const combineResponse = ( return { id: action.EndpointActions.action_id, agents: action.agent.id as string[], + agentType: 'endpoint', parameters, ...(alertId?.length ? { alertIds: alertId } : {}), ...(rule diff --git a/x-pack/plugins/security_solution/scripts/endpoint/common/response_actions.ts b/x-pack/plugins/security_solution/scripts/endpoint/common/response_actions.ts index 8a5c77c2a61b..c909b6323ad2 100644 --- a/x-pack/plugins/security_solution/scripts/endpoint/common/response_actions.ts +++ b/x-pack/plugins/security_solution/scripts/endpoint/common/response_actions.ts @@ -23,6 +23,7 @@ import type { ResponseActionExecuteOutputContent, ResponseActionGetFileOutputContent, ResponseActionGetFileParameters, + EndpointActionResponseDataOutput, } from '../../../common/endpoint/types'; import { getFileDownloadId } from '../../../common/endpoint/service/response_actions/get_file_download_id'; import { @@ -79,18 +80,19 @@ export const sendEndpointActionResponse = async ( action: ActionDetails, { state }: { state?: 'success' | 'failure' } = {} ): Promise => { - const endpointResponse = endpointActionGenerator.generateResponse({ - agent: { id: action.agents[0] }, - EndpointActions: { - action_id: action.id, - data: { - command: action.command as EndpointActionData['command'], - comment: '', - ...getOutputDataIfNeeded(action), + const endpointResponse = + endpointActionGenerator.generateResponse({ + agent: { id: action.agents[0] }, + EndpointActions: { + action_id: action.id, + data: { + command: action.command as EndpointActionData['command'], + comment: '', + ...getOutputDataIfNeeded(action), + }, + started_at: action.startedAt, }, - started_at: action.startedAt, - }, - }); + }); // 20% of the time we generate an error if (state === 'failure' || (state !== 'success' && endpointActionGenerator.randomFloat() < 0.2)) { @@ -103,7 +105,8 @@ export const sendEndpointActionResponse = async ( endpointResponse.EndpointActions.data.output ) { ( - endpointResponse.EndpointActions.data.output.content as ResponseActionGetFileOutputContent + endpointResponse.EndpointActions.data.output + .content as unknown as ResponseActionGetFileOutputContent ).code = endpointActionGenerator.randomGetFileFailureCode(); } @@ -112,7 +115,8 @@ export const sendEndpointActionResponse = async ( endpointResponse.EndpointActions.data.output ) { ( - endpointResponse.EndpointActions.data.output.content as ResponseActionExecuteOutputContent + endpointResponse.EndpointActions.data.output + .content as unknown as ResponseActionExecuteOutputContent ).stderr = 'execute command timed out'; } } @@ -168,7 +172,7 @@ export const sendEndpointActionResponse = async ( ? '/execute/file/path' : // eslint-disable-next-line @typescript-eslint/no-non-null-assertion ( - action as ActionDetails< + action as unknown as ActionDetails< ResponseActionGetFileOutputContent, ResponseActionGetFileParameters > @@ -244,12 +248,11 @@ export const sendEndpointActionResponse = async ( .then(() => sleep(2000)); } - return endpointResponse; + return endpointResponse as unknown as LogsEndpointActionResponse; }; -type ResponseOutput = Pick< - LogsEndpointActionResponse['EndpointActions']['data'], - 'output' ->; +type ResponseOutput< + TOutputContent extends EndpointActionResponseDataOutput = EndpointActionResponseDataOutput +> = Pick['EndpointActions']['data'], 'output'>; const getOutputDataIfNeeded = (action: ActionDetails): ResponseOutput => { const commentUppercase = (action?.comment ?? '').toUpperCase(); @@ -262,7 +265,7 @@ const getOutputDataIfNeeded = (action: ActionDetails): ResponseOutput => { entries: endpointActionGenerator.randomResponseActionProcesses(100), }, }, - } as ResponseOutput; + } as unknown as ResponseOutput; case 'get-file': return { @@ -275,7 +278,7 @@ const getOutputDataIfNeeded = (action: ActionDetails): ResponseOutput => { { type: 'file', path: ( - action as ActionDetails< + action as unknown as ActionDetails< ResponseActionGetFileOutputContent, ResponseActionGetFileParameters > @@ -287,7 +290,7 @@ const getOutputDataIfNeeded = (action: ActionDetails): ResponseOutput => { ], }, }, - } as ResponseOutput; + } as unknown as ResponseOutput; case 'execute': const executeOutput: Partial = { @@ -309,7 +312,7 @@ const getOutputDataIfNeeded = (action: ActionDetails): ResponseOutput => { output: endpointActionGenerator.generateExecuteActionResponseOutput({ content: executeOutput, }), - } as ResponseOutput; + } as unknown as ResponseOutput; default: return { output: undefined }; diff --git a/x-pack/plugins/security_solution/server/endpoint/mocks.ts b/x-pack/plugins/security_solution/server/endpoint/mocks.ts index 477d1e70be96..55e13b46c716 100644 --- a/x-pack/plugins/security_solution/server/endpoint/mocks.ts +++ b/x-pack/plugins/security_solution/server/endpoint/mocks.ts @@ -102,6 +102,7 @@ export const createMockEndpointAppContextService = ( const fleetToHostFilesClientMock = createFleetToHostFilesClientMock(); const fleetActionsClientMock = createFleetActionsClientMock(); const loggerFactory = loggingSystemMock.create(); + const featureUsageMock = createFeatureUsageServiceMock(); return { start: jest.fn(), @@ -120,7 +121,7 @@ export const createMockEndpointAppContextService = ( getFleetToHostFilesClient: jest.fn(async () => fleetToHostFilesClientMock), setup: jest.fn(), getLicenseService: jest.fn(), - getFeatureUsageService: jest.fn(), + getFeatureUsageService: jest.fn().mockReturnValue(featureUsageMock), getExceptionListsClient: jest.fn(), getMessageSigningService: jest.fn(), getFleetActionsClient: jest.fn(async (_) => fleetActionsClientMock), 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 055ef330cb08..74f222b64d2b 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 @@ -73,6 +73,7 @@ import { omit, set } from 'lodash'; import type { ResponseActionAgentType } from '../../../../common/endpoint/service/response_actions/constants'; import { responseActionsClientMock } from '../../services/actions/clients/mocks'; import type { ActionsApiRequestHandlerContext } from '@kbn/actions-plugin/server'; +import { sentinelOneMock } from '../../services/actions/clients/sentinelone/mock'; jest.mock('../../services', () => { const realModule = jest.requireActual('../../services'); @@ -1184,7 +1185,7 @@ describe('Response actions', () => { }; httpHandlerContextMock.actions = Promise.resolve({ - getActionsClient: () => responseActionsClientMock.createConnectorActionsClient(), + getActionsClient: () => sentinelOneMock.createConnectorActionsClient(), } as unknown as jest.Mocked); // Set the esClient to be used in the handler context 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 4e8fdc997572..0c573b561479 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 @@ -7,7 +7,7 @@ import type { RequestHandler } from '@kbn/core/server'; import type { TypeOf } from '@kbn/config-schema'; -import { dump } from '../../utils/dump'; +import { stringify } from '../../utils/stringify'; import { getResponseActionsClient } from '../../services'; import type { ResponseActionsClient } from '../../services/actions/clients/lib/types'; import { CustomHttpRequestError } from '../../../utils/custom_http_request_error'; @@ -292,7 +292,7 @@ function responseActionRequestHandler { - logger.debug(`response action [${command}]:\n${dump(req.body)}`); + logger.debug(`response action [${command}]:\n${stringify(req.body)}`); // Note: because our API schemas are defined as module static variables (as opposed to a // `getter` function), we need to include this additional validation here, since diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/actions/status.test.ts b/x-pack/plugins/security_solution/server/endpoint/routes/actions/status.test.ts index 455ef9ec3194..d7b8824745cd 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/actions/status.test.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/actions/status.test.ts @@ -36,6 +36,7 @@ import type { } from '../../../../common/endpoint/types'; import { EndpointActionGenerator } from '../../../../common/endpoint/data_generators/endpoint_action_generator'; import { ActionStatusRequestSchema } from '../../../../common/api/endpoint'; +import { AGENT_ACTIONS_RESULTS_INDEX } from '@kbn/fleet-plugin/common'; describe('Endpoint Pending Action Summary API', () => { let endpointAppContextService: EndpointAppContextService; @@ -109,6 +110,8 @@ describe('Endpoint Pending Action Summary API', () => { break; case ACTION_RESPONSE_INDICES.join(): + case AGENT_ACTIONS_RESULTS_INDEX: + case ENDPOINT_ACTION_RESPONSES_INDEX_PATTERN: items.push(...endpointResponses.splice(0, size)); index = ENDPOINT_ACTION_RESPONSES_INDEX_PATTERN; break; diff --git a/x-pack/plugins/security_solution/server/endpoint/services/actions/action_details_by_id.test.ts b/x-pack/plugins/security_solution/server/endpoint/services/actions/action_details_by_id.test.ts index 54d536e314ed..861a8c8870fa 100644 --- a/x-pack/plugins/security_solution/server/endpoint/services/actions/action_details_by_id.test.ts +++ b/x-pack/plugins/security_solution/server/endpoint/services/actions/action_details_by_id.test.ts @@ -66,7 +66,9 @@ describe('When using `getActionDetailsById()', () => { await expect( getActionDetailsById(esClient, endpointAppContextService.getEndpointMetadataService(), '123') ).resolves.toEqual({ + action: '123', agents: ['agent-a'], + agentType: 'endpoint', hosts: { 'agent-a': { name: 'Host-agent-a' } }, command: 'kill-process', completedAt: '2022-04-30T16:08:47.449Z', diff --git a/x-pack/plugins/security_solution/server/endpoint/services/actions/action_details_by_id.ts b/x-pack/plugins/security_solution/server/endpoint/services/actions/action_details_by_id.ts index 8e3d6ddad12b..7863eb4507e6 100644 --- a/x-pack/plugins/security_solution/server/endpoint/services/actions/action_details_by_id.ts +++ b/x-pack/plugins/security_solution/server/endpoint/services/actions/action_details_by_id.ts @@ -7,30 +7,33 @@ import type { ElasticsearchClient } from '@kbn/core/server'; +import { fetchActionResponses } from './fetch_action_responses'; import { ENDPOINT_ACTIONS_INDEX } from '../../../../common/endpoint/constants'; import { formatEndpointActionResults, categorizeResponseResults, - getActionCompletionInfo, mapToNormalizedActionRequest, getAgentHostNamesWithIds, - getActionStatus, + createActionDetailsRecord, } from './utils'; import type { ActionDetails, ActivityLogActionResponse, - EndpointActionResponse, EndpointActivityLogAction, EndpointActivityLogActionResponse, LogsEndpointAction, - LogsEndpointActionResponse, } from '../../../../common/endpoint/types'; import { catchAndWrapError } from '../../utils'; import { EndpointError } from '../../../../common/endpoint/errors'; import { NotFoundError } from '../../errors'; -import { ACTION_RESPONSE_INDICES, ACTIONS_SEARCH_PAGE_SIZE } from './constants'; import type { EndpointMetadataService } from '../metadata'; +/** + * Get Action Details for a single action id + * @param esClient + * @param metadataService + * @param actionId + */ export const getActionDetailsById = async ( esClient: ElasticsearchClient, metadataService: EndpointMetadataService, @@ -43,7 +46,7 @@ export const getActionDetailsById = async ( @@ -63,23 +66,7 @@ export const getActionDetailsById = async ( - { - index: ACTION_RESPONSE_INDICES, - size: ACTIONS_SEARCH_PAGE_SIZE, - body: { - query: { - bool: { - filter: [{ term: { action_id: actionId } }], - }, - }, - }, - }, - { ignore: [404] } - ) - .catch(catchAndWrapError), + fetchActionResponses({ esClient, actionIds: [actionId] }).then((response) => response.data), ]); actionRequestsLogEntries = formatEndpointActionResults( @@ -95,8 +82,8 @@ export const getActionDetailsById = async ; + results: allResponseEsHits, + }); } catch (error) { throw new EndpointError(error.message, error); } @@ -113,36 +100,5 @@ export const getActionDetailsById = async ((acc, id) => { - acc[id] = { name: agentsHostInfo[id] ?? '' }; - return acc; - }, {}), - command: normalizedActionRequest.command, - startedAt: normalizedActionRequest.createdAt, - isCompleted, - completedAt, - wasSuccessful, - errors, - isExpired, - status, - outputs, - agentState, - createdBy: normalizedActionRequest.createdBy, - comment: normalizedActionRequest.comment, - parameters: normalizedActionRequest.parameters, - }; - - return actionDetails as T; + return createActionDetailsRecord(normalizedActionRequest, actionResponses, agentsHostInfo); }; diff --git a/x-pack/plugins/security_solution/server/endpoint/services/actions/action_list.test.ts b/x-pack/plugins/security_solution/server/endpoint/services/actions/action_list.test.ts index ebf88e6effd2..70ccd7af8ecb 100644 --- a/x-pack/plugins/security_solution/server/endpoint/services/actions/action_list.test.ts +++ b/x-pack/plugins/security_solution/server/endpoint/services/actions/action_list.test.ts @@ -89,7 +89,9 @@ describe('When using `getActionList()', () => { endDate: undefined, data: [ { + action: '123', agents: ['agent-a'], + agentType: 'endpoint', hosts: { 'agent-a': { name: 'Host-agent-a' } }, command: 'kill-process', completedAt: '2022-04-30T16:08:47.449Z', @@ -110,6 +112,24 @@ describe('When using `getActionList()', () => { wasSuccessful: true, }, }, + outputs: { + 'agent-a': { + content: { + code: 'ra_get-file_success_done', + contents: [ + { + file_name: 'bad_file.txt', + path: '/some/path/bad_file.txt', + sha256: '9558c5cb39622e9b3653203e772b129d6c634e7dbd7af1b244352fc1d704601f', + size: 1234, + type: 'file', + }, + ], + zip_size: 123, + }, + type: 'json', + }, + }, }, ], total: 1, @@ -152,7 +172,9 @@ describe('When using `getActionList()', () => { endDate: undefined, data: [ { + action: '123', agents: ['agent-a'], + agentType: 'endpoint', hosts: { 'agent-a': { name: 'Host-agent-a' } }, command: 'kill-process', completedAt: '2022-04-30T16:08:47.449Z', @@ -246,7 +268,9 @@ describe('When using `getActionList()', () => { statuses: undefined, data: [ { + action: '123', agents: ['agent-a', 'agent-b', 'agent-x'], + agentType: 'endpoint', hosts: { 'agent-a': { name: 'Host-agent-a' }, 'agent-b': { name: 'Host-agent-b' }, @@ -284,6 +308,7 @@ describe('When using `getActionList()', () => { errors: undefined, }, }, + outputs: {}, }, ], total: 1, @@ -319,16 +344,6 @@ describe('When using `getActionList()', () => { { bool: { filter: [ - { - term: { - input_type: 'endpoint', - }, - }, - { - term: { - type: 'INPUT_ACTION', - }, - }, { range: { '@timestamp': { @@ -415,16 +430,6 @@ describe('When using `getActionList()', () => { { bool: { filter: [ - { - term: { - input_type: 'endpoint', - }, - }, - { - term: { - type: 'INPUT_ACTION', - }, - }, { range: { '@timestamp': { diff --git a/x-pack/plugins/security_solution/server/endpoint/services/actions/action_list.ts b/x-pack/plugins/security_solution/server/endpoint/services/actions/action_list.ts index f932eb7df23f..f33c716da243 100644 --- a/x-pack/plugins/security_solution/server/endpoint/services/actions/action_list.ts +++ b/x-pack/plugins/security_solution/server/endpoint/services/actions/action_list.ts @@ -7,20 +7,20 @@ import type { ElasticsearchClient, Logger } from '@kbn/core/server'; import type { SearchTotalHits } from '@elastic/elasticsearch/lib/api/types'; +import { fetchActionResponses } from './fetch_action_responses'; import { ENDPOINT_DEFAULT_PAGE_SIZE } from '../../../../common/endpoint/constants'; import { CustomHttpRequestError } from '../../../utils/custom_http_request_error'; -import type { ActionDetails, ActionListApiResponse } from '../../../../common/endpoint/types'; +import type { ActionListApiResponse } from '../../../../common/endpoint/types'; import type { ResponseActionStatus } from '../../../../common/endpoint/service/response_actions/constants'; -import { getActions, getActionResponses } from '../../utils/action_list_helpers'; +import { getActions } from '../../utils/action_list_helpers'; import { formatEndpointActionResults, categorizeResponseResults, - getActionCompletionInfo, mapToNormalizedActionRequest, getAgentHostNamesWithIds, - getActionStatus, + createActionDetailsRecord, } from './utils'; import type { EndpointMetadataService } from '../metadata'; import { ACTIONS_SEARCH_PAGE_SIZE } from './constants'; @@ -237,11 +237,8 @@ const getActionDetailsList = async ({ // get all responses for given action Ids and agent Ids // and get host metadata info with queried agents [actionResponses, agentsHostInfo] = await Promise.all([ - getActionResponses({ - actionIds: actionReqIds, - elasticAgentIds, - esClient, - }), + fetchActionResponses({ esClient, agentIds: elasticAgentIds, actionIds: actionReqIds }), + await getAgentHostNamesWithIds({ esClient, metadataService, @@ -262,7 +259,7 @@ const getActionDetailsList = async ({ // categorize responses as fleet and endpoint responses const categorizedResponses = categorizeResponseResults({ - results: actionResponses?.body?.hits?.hits, + results: actionResponses.data, }); // compute action details list for each action id @@ -274,41 +271,11 @@ const getActionDetailsList = async ({ : categorizedResponse.item.data.action_id === action.id ); - // find the specific response's details using that set of matching responses - const { isCompleted, completedAt, wasSuccessful, errors, agentState, outputs } = - getActionCompletionInfo(action, matchedResponses); - - const { isExpired, status } = getActionStatus({ - expirationDate: action.expiration, - isCompleted, - wasSuccessful, - }); + const actionRecord = createActionDetailsRecord(action, matchedResponses, agentsHostInfo); - const actionRecord: ActionListApiResponse['data'][number] = { - id: action.id, - agents: action.agents, - hosts: action.agents.reduce((acc, id) => { - acc[id] = { name: agentsHostInfo[id] ?? '' }; - return acc; - }, {}), - command: action.command, - startedAt: action.createdAt, - isCompleted, - completedAt, - wasSuccessful, - errors: action.error?.message ? [action.error.message] : errors, - agentState, - isExpired, - status, - // 8.8 onwards, show outputs only for actions with matching requested action ids - outputs: withOutputs && withOutputs.includes(action.id) ? outputs : undefined, - createdBy: action.createdBy, - comment: action.comment, - parameters: action.parameters, - alertIds: action.alertIds, - ruleId: action.ruleId, - ruleName: action.ruleName, - }; + if (withOutputs && !withOutputs.includes(action.id)) { + delete actionRecord.outputs; + } return actionRecord; }); diff --git a/x-pack/plugins/security_solution/server/endpoint/services/actions/clients/endpoint_actions_client.ts b/x-pack/plugins/security_solution/server/endpoint/services/actions/clients/endpoint_actions_client.ts index a999659f2273..2acc6dec8f2a 100644 --- a/x-pack/plugins/security_solution/server/endpoint/services/actions/clients/endpoint_actions_client.ts +++ b/x-pack/plugins/security_solution/server/endpoint/services/actions/clients/endpoint_actions_client.ts @@ -5,9 +5,12 @@ * 2.0. */ -import { dump } from '../../../utils/dump'; +import { stringify } from '../../../utils/stringify'; import type { HapiReadableStream } from '../../../../types'; -import type { ResponseActionsApiCommandNames } from '../../../../../common/endpoint/service/response_actions/constants'; +import type { + ResponseActionsApiCommandNames, + ResponseActionAgentType, +} from '../../../../../common/endpoint/service/response_actions/constants'; import { updateCases } from '../create/update_cases'; import type { CreateActionPayload } from '../create/types'; import type { @@ -36,6 +39,8 @@ import type { } from '../../../../../common/endpoint/types'; export class EndpointActionsClient extends ResponseActionsClientImpl { + protected readonly agentType: ResponseActionAgentType = 'endpoint'; + private async checkAgentIds(ids: string[]): Promise<{ valid: string[]; invalid: string[]; @@ -83,7 +88,7 @@ export class EndpointActionsClient extends ResponseActionsClientImpl { }); } catch (err) { // failures during update of cases should not cause the response action to fail. Just log error - this.log.warn(`failed to update cases: ${err.message}\n${dump(err)}`); + this.log.warn(`failed to update cases: ${err.message}\n${stringify(err)}`); } return response as TResponse; diff --git a/x-pack/plugins/security_solution/server/endpoint/services/actions/clients/errors.ts b/x-pack/plugins/security_solution/server/endpoint/services/actions/clients/errors.ts index 300f2fa56cad..2e644f9a3a76 100644 --- a/x-pack/plugins/security_solution/server/endpoint/services/actions/clients/errors.ts +++ b/x-pack/plugins/security_solution/server/endpoint/services/actions/clients/errors.ts @@ -8,7 +8,7 @@ /* eslint-disable max-classes-per-file */ import type { ResponseActionsApiCommandNames } from '../../../../../common/endpoint/service/response_actions/constants'; -import { dump } from '../../../utils/dump'; +import { stringify } from '../../../utils/stringify'; import { CustomHttpRequestError } from '../../../../utils/custom_http_request_error'; /** @@ -25,7 +25,7 @@ export class ResponseActionsClientError extends CustomHttpRequestError { } toString() { - return JSON.stringify(dump(this.toJSON()), null, 2); + return JSON.stringify(stringify(this.toJSON()), null, 2); } } diff --git a/x-pack/plugins/security_solution/server/endpoint/services/actions/clients/get_response_actions_client.test.ts b/x-pack/plugins/security_solution/server/endpoint/services/actions/clients/get_response_actions_client.test.ts index f0cee2a61646..224c8eac855e 100644 --- a/x-pack/plugins/security_solution/server/endpoint/services/actions/clients/get_response_actions_client.test.ts +++ b/x-pack/plugins/security_solution/server/endpoint/services/actions/clients/get_response_actions_client.test.ts @@ -11,6 +11,7 @@ import { RESPONSE_ACTION_AGENT_TYPE } from '../../../../../common/endpoint/servi import { getResponseActionsClient } from '../..'; import { ResponseActionsClientImpl } from './lib/base_response_actions_client'; import { UnsupportedResponseActionsAgentTypeError } from './errors'; +import { sentinelOneMock } from './sentinelone/mock'; describe('getResponseActionsClient()', () => { let options: GetResponseActionsClientConstructorOptions; @@ -18,7 +19,7 @@ describe('getResponseActionsClient()', () => { beforeEach(() => { options = { ...responseActionsClientMock.createConstructorOptions(), - connectorActions: responseActionsClientMock.createConnectorActionsClient(), + connectorActions: sentinelOneMock.createConnectorActionsClient(), }; }); diff --git a/x-pack/plugins/security_solution/server/endpoint/services/actions/clients/lib/base_response_actions_client.test.ts b/x-pack/plugins/security_solution/server/endpoint/services/actions/clients/lib/base_response_actions_client.test.ts index 7b6d991e28f0..aaceb2d6aef7 100644 --- a/x-pack/plugins/security_solution/server/endpoint/services/actions/clients/lib/base_response_actions_client.test.ts +++ b/x-pack/plugins/security_solution/server/endpoint/services/actions/clients/lib/base_response_actions_client.test.ts @@ -5,6 +5,7 @@ * 2.0. */ +// eslint-disable-next-line max-classes-per-file import type { ResponseActionsClient } from './types'; import type { ResponseActionsClientUpdateCasesOptions, @@ -16,6 +17,7 @@ import type { ActionDetails, LogsEndpointAction, LogsEndpointActionResponse, + EndpointActionResponseDataOutput, } from '../../../../../../common/endpoint/types'; import type { EndpointAppContextService } from '../../../../endpoint_app_context_services'; import type { ElasticsearchClientMock } from '@kbn/core-elasticsearch-client-server-mocks'; @@ -30,6 +32,8 @@ import { ENDPOINT_ACTIONS_INDEX } from '../../../../../../common/endpoint/consta import type { DeepMutable } from '../../../../../../common/endpoint/types/utility_types'; import { set } from 'lodash'; import { responseActionsClientMock } from '../mocks'; +import type { ResponseActionAgentType } from '../../../../../../common/endpoint/service/response_actions/constants'; +import { getResponseActionFeatureKey } from '../../../feature_usage/feature_keys'; jest.mock('../../action_details_by_id', () => { const original = jest.requireActual('../../action_details_by_id'); @@ -43,6 +47,7 @@ jest.mock('../../action_details_by_id', () => { const getActionDetailsByIdMock = _getActionDetailsById as jest.Mock; describe('ResponseActionsClientImpl base class', () => { + let constructorOptions: ReturnType; let esClient: ElasticsearchClientMock; let endpointAppContextService: EndpointAppContextService; let baseClassMock: MockClassWithExposedProtectedMembers; @@ -50,7 +55,7 @@ describe('ResponseActionsClientImpl base class', () => { let logger: Logger; beforeEach(async () => { - const constructorOptions = responseActionsClientMock.createConstructorOptions(); + constructorOptions = responseActionsClientMock.createConstructorOptions(); esClient = constructorOptions.esClient; casesClient = constructorOptions.casesClient; @@ -361,14 +366,29 @@ describe('ResponseActionsClientImpl base class', () => { await expect( baseClassMock.writeActionRequestToEndpointIndex(indexDocOptions) ).resolves.toEqual(expectedIndexDoc); + + expect(endpointAppContextService.getFeatureUsageService().notifyUsage).toHaveBeenCalledWith( + getResponseActionFeatureKey(indexDocOptions.command) + ); + }); + + it('should notify feature usage', async () => { + await baseClassMock.writeActionRequestToEndpointIndex(indexDocOptions); + + expect(endpointAppContextService.getFeatureUsageService().notifyUsage).toHaveBeenCalledWith( + getResponseActionFeatureKey(indexDocOptions.command) + ); }); it('should set `EndpointActions.input_type` to the correct value', async () => { + const baseClassMock2 = new (class extends MockClassWithExposedProtectedMembers { + protected readonly agentType = 'sentinel_one'; + })(constructorOptions); indexDocOptions.agent_type = 'sentinel_one'; set(expectedIndexDoc, 'EndpointActions.input_type', 'sentinel_one'); await expect( - baseClassMock.writeActionRequestToEndpointIndex(indexDocOptions) + baseClassMock2.writeActionRequestToEndpointIndex(indexDocOptions) ).resolves.toEqual(expectedIndexDoc); }); @@ -457,12 +477,14 @@ describe('ResponseActionsClientImpl base class', () => { '@timestamp': expect.any(String), EndpointActions: { action_id: '1-2-3', + input_type: 'endpoint', completed_at: expect.any(String), + started_at: expect.any(String), data: { command: 'isolate', comment: 'some comment', + output: undefined, }, - started_at: expect.any(String), }, agent: { id: '123', @@ -470,7 +492,7 @@ describe('ResponseActionsClientImpl base class', () => { error: { message: 'test error', }, - }); + } as LogsEndpointActionResponse); }); it('should throw ResponseActionsClientError if operation fails', async () => { @@ -491,6 +513,8 @@ describe('ResponseActionsClientImpl base class', () => { }); class MockClassWithExposedProtectedMembers extends ResponseActionsClientImpl { + protected readonly agentType: ResponseActionAgentType = 'endpoint'; + public async updateCases(options: ResponseActionsClientUpdateCasesOptions): Promise { return super.updateCases(options); } @@ -507,7 +531,9 @@ class MockClassWithExposedProtectedMembers extends ResponseActionsClientImpl { return super.writeActionRequestToEndpointIndex(actionRequest); } - public async writeActionResponseToEndpointIndex( + public async writeActionResponseToEndpointIndex< + TOutputContent extends EndpointActionResponseDataOutput = EndpointActionResponseDataOutput + >( options: ResponseActionsClientWriteActionResponseToEndpointIndexOptions ): Promise> { return super.writeActionResponseToEndpointIndex(options); diff --git a/x-pack/plugins/security_solution/server/endpoint/services/actions/clients/lib/base_response_actions_client.ts b/x-pack/plugins/security_solution/server/endpoint/services/actions/clients/lib/base_response_actions_client.ts index cea80bd3f9bc..68e8db5fa1e6 100644 --- a/x-pack/plugins/security_solution/server/endpoint/services/actions/clients/lib/base_response_actions_client.ts +++ b/x-pack/plugins/security_solution/server/endpoint/services/actions/clients/lib/base_response_actions_client.ts @@ -13,7 +13,10 @@ import { AttachmentType } from '@kbn/cases-plugin/common'; import type { BulkCreateArgs } from '@kbn/cases-plugin/server/client/attachments/types'; import type { EndpointAppContextService } from '../../../../endpoint_app_context_services'; import { APP_ID } from '../../../../../../common'; -import type { ResponseActionsApiCommandNames } from '../../../../../../common/endpoint/service/response_actions/constants'; +import type { + ResponseActionsApiCommandNames, + ResponseActionAgentType, +} from '../../../../../../common/endpoint/service/response_actions/constants'; import { getActionDetailsById } from '../../action_details_by_id'; import { ResponseActionsClientError, ResponseActionsNotSupportedError } from '../errors'; import { @@ -42,6 +45,7 @@ import type { LogsEndpointAction, EndpointActionDataParameterTypes, LogsEndpointActionResponse, + EndpointActionResponseDataOutput, } from '../../../../../../common/endpoint/types'; import type { IsolationRouteRequestBody, @@ -52,7 +56,7 @@ import type { ResponseActionsRequestBody, } from '../../../../../../common/api/endpoint'; import type { CreateActionPayload } from '../../create/types'; -import { dump } from '../../../../utils/dump'; +import { stringify } from '../../../../utils/stringify'; export interface ResponseActionsClientOptions { endpointService: EndpointAppContextService; @@ -82,7 +86,7 @@ export type ResponseActionsClientWriteActionRequestToEndpointIndexOptions = Pick; export type ResponseActionsClientWriteActionResponseToEndpointIndexOptions< - TOutputContent extends object = object + TOutputContent extends EndpointActionResponseDataOutput = EndpointActionResponseDataOutput > = { agentId: LogsEndpointActionResponse['agent']['id']; actionId: string; @@ -92,9 +96,11 @@ export type ResponseActionsClientWriteActionResponseToEndpointIndexOptions< /** * Base class for a Response Actions client */ -export class ResponseActionsClientImpl implements ResponseActionsClient { +export abstract class ResponseActionsClientImpl implements ResponseActionsClient { protected readonly log: Logger; + protected abstract readonly agentType: ResponseActionAgentType; + constructor(protected readonly options: ResponseActionsClientOptions) { this.log = options.endpointService.createLogger( this.constructor.name ?? 'ResponseActionsClient' @@ -158,7 +164,7 @@ export class ResponseActionsClientImpl implements ResponseActionsClient { return; } - this.log.debug(`Updating cases:\n${dump(allCases)}`); + this.log.debug(`Updating cases:\n${stringify(allCases)}`); // Create an attachment for each case that includes info. about the response actions taken against the hosts const attachments = allCases.map(() => ({ @@ -181,14 +187,14 @@ export class ResponseActionsClientImpl implements ResponseActionsClient { .catch((err) => { // Log any error, BUT: do not fail execution this.log.warn( - `Attempt to update case ID [${caseId}] failed: ${err.message}\n${dump(err)}` + `Attempt to update case ID [${caseId}] failed: ${err.message}\n${stringify(err)}` ); return null; }) ) ); - this.log.debug(`Update to cases done:\n${dump(casesUpdateResponse)}`); + this.log.debug(`Update to cases done:\n${stringify(casesUpdateResponse)}`); } /** @@ -213,6 +219,8 @@ export class ResponseActionsClientImpl implements ResponseActionsClient { protected async writeActionRequestToEndpointIndex( actionRequest: ResponseActionsClientWriteActionRequestToEndpointIndexOptions ): Promise { + this.notifyUsage(actionRequest.command); + const doc: LogsEndpointAction = { '@timestamp': new Date().toISOString(), agent: { @@ -222,7 +230,7 @@ export class ResponseActionsClientImpl implements ResponseActionsClient { action_id: uuidv4(), expiration: getActionRequestExpiration(), type: 'INPUT_ACTION', - input_type: actionRequest.agent_type ?? 'endpoint', + input_type: this.agentType, data: { command: actionRequest.command, comment: actionRequest.comment ?? undefined, @@ -274,7 +282,10 @@ export class ResponseActionsClientImpl implements ResponseActionsClient { * @param options * @protected */ - protected async writeActionResponseToEndpointIndex({ + protected async writeActionResponseToEndpointIndex< + // Default type purposely set to empty object in order to ensure proper types are used when calling the method + TOutputContent extends EndpointActionResponseDataOutput = Record + >({ actionId, error, agentId, @@ -290,6 +301,7 @@ export class ResponseActionsClientImpl implements ResponseActionsClient { }, EndpointActions: { action_id: actionId, + input_type: this.agentType, started_at: timestamp, completed_at: timestamp, data, @@ -297,10 +309,10 @@ export class ResponseActionsClientImpl implements ResponseActionsClient { error, }; - this.log.debug(`Writing response action response:\n${dump(doc)}`); + this.log.debug(`Writing response action response:\n${stringify(doc)}`); await this.options.esClient - .index({ + .index>({ index: ENDPOINT_ACTION_RESPONSES_INDEX, document: doc, refresh: 'wait_for', @@ -316,6 +328,20 @@ export class ResponseActionsClientImpl implements ResponseActionsClient { return doc; } + protected notifyUsage(responseAction: ResponseActionsApiCommandNames): void { + const usageService = this.options.endpointService.getFeatureUsageService(); + const featureKey = usageService.getResponseActionFeatureKey(responseAction); + + if (!featureKey) { + this.log.warn( + `Response action [${responseAction}] does not have a usage feature key defined!` + ); + return; + } + + usageService.notifyUsage(featureKey); + } + public async isolate(options: IsolationRouteRequestBody): Promise { throw new ResponseActionsNotSupportedError('isolate'); } diff --git a/x-pack/plugins/security_solution/server/endpoint/services/actions/clients/mocks.ts b/x-pack/plugins/security_solution/server/endpoint/services/actions/clients/mocks.ts index 27773a898b93..2523765e5f45 100644 --- a/x-pack/plugins/security_solution/server/endpoint/services/actions/clients/mocks.ts +++ b/x-pack/plugins/security_solution/server/endpoint/services/actions/clients/mocks.ts @@ -5,10 +5,8 @@ * 2.0. */ -import type { ActionsClientMock } from '@kbn/actions-plugin/server/actions_client/actions_client.mock'; import { actionsClientMock } from '@kbn/actions-plugin/server/actions_client/actions_client.mock'; import type { ConnectorWithExtraFindData } from '@kbn/actions-plugin/server/application/connector/types'; -import { SENTINELONE_CONNECTOR_ID } from '@kbn/stack-connectors-plugin/common/sentinelone/constants'; import type { DeepPartial } from 'utility-types'; import type { ActionTypeExecutorResult } from '@kbn/actions-plugin/common'; import type { ElasticsearchClientMock } from '@kbn/core-elasticsearch-client-server-mocks'; @@ -138,29 +136,6 @@ const createIsolateOptionsMock = ( return merge(isolateOptions, overrides); }; -const createConnectorActionsClientMock = (): ActionsClientMock => { - const client = actionsClientMock.create(); - - // Mock result of retrieving list of connectors - (client.getAll as jest.Mock).mockImplementation(async () => { - const result: ConnectorWithExtraFindData[] = [ - // SentinelOne connector - createConnectorMock({ - actionTypeId: SENTINELONE_CONNECTOR_ID, - id: 's1-connector-instance-id', - }), - ]; - - return result; - }); - - (client.execute as jest.Mock).mockImplementation(async () => { - return createConnectorAcitonExecuteResponseMock(); - }); - - return client; -}; - const createConnectorMock = ( overrides: DeepPartial = {} ): ConnectorWithExtraFindData => { @@ -180,10 +155,10 @@ const createConnectorMock = ( ); }; -const createConnectorAcitonExecuteResponseMock = ( - overrides: DeepPartial> = {} +const createConnectorActionExecuteResponseMock = ( + overrides: DeepPartial> = {} ): ActionTypeExecutorResult<{}> => { - const result: ActionTypeExecutorResult<{}> = { + const result: ActionTypeExecutorResult = { actionId: 'execute-response-mock-1', data: undefined, message: 'some mock message', @@ -199,11 +174,13 @@ export const responseActionsClientMock = Object.freeze({ createConstructorOptions: createConstructorOptionsMock, createIsolateOptions: createIsolateOptionsMock, createReleaseOptions: createIsolateOptionsMock, + // TODO:PT add more methods to get option mocks for other class methods createIndexedResponse: createEsIndexTransportResponseMock, - createConnectorActionsClient: createConnectorActionsClientMock, + // Some common mocks when working with connector actions + createConnectorActionsClient: actionsClientMock.create, createConnector: createConnectorMock, - createConnectorActionExecuteResponse: createConnectorAcitonExecuteResponseMock, + createConnectorActionExecuteResponse: createConnectorActionExecuteResponseMock, }); diff --git a/x-pack/plugins/security_solution/server/endpoint/services/actions/clients/sentinelone/mock.ts b/x-pack/plugins/security_solution/server/endpoint/services/actions/clients/sentinelone/mock.ts new file mode 100644 index 000000000000..48a6ace18adc --- /dev/null +++ b/x-pack/plugins/security_solution/server/endpoint/services/actions/clients/sentinelone/mock.ts @@ -0,0 +1,177 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { SentinelOneGetAgentsResponse } from '@kbn/stack-connectors-plugin/common/sentinelone/types'; +import { + SENTINELONE_CONNECTOR_ID, + SUB_ACTION, +} from '@kbn/stack-connectors-plugin/common/sentinelone/constants'; +import type { ActionsClientMock } from '@kbn/actions-plugin/server/actions_client/actions_client.mock'; +import type { ConnectorWithExtraFindData } from '@kbn/actions-plugin/server/application/connector/types'; +import type { ResponseActionsClientOptionsMock } from '../mocks'; +import { responseActionsClientMock } from '../mocks'; + +export interface SentinelOneActionsClientOptionsMock extends ResponseActionsClientOptionsMock { + connectorActions: ActionsClientMock; +} + +const createSentinelOneGetAgentsApiResponseMock = (): SentinelOneGetAgentsResponse => { + return { + pagination: { + nextCursor: 'next-0', + totalItems: 1, + }, + errors: null, + data: [ + { + accountId: '11111111111', + accountName: 'Elastic', + groupUpdatedAt: null, + policyUpdatedAt: null, + activeDirectory: { + computerDistinguishedName: null, + computerMemberOf: [], + lastUserDistinguishedName: null, + lastUserMemberOf: [], + userPrincipalName: null, + mail: null, + }, + activeThreats: 0, + agentVersion: '23.3.2.12', + allowRemoteShell: true, + appsVulnerabilityStatus: 'not_applicable', + cloudProviders: {}, + computerName: 'sentinelone-1460', + consoleMigrationStatus: 'N/A', + coreCount: 1, + cpuCount: 1, + cpuId: 'ARM Cortex-A72', + createdAt: '2023-12-21T20:32:52.290978Z', + detectionState: null, + domain: 'unknown', + encryptedApplications: false, + externalId: '', + externalIp: '108.77.84.191', + firewallEnabled: true, + firstFullModeTime: null, + fullDiskScanLastUpdatedAt: '2023-12-21T20:57:55.690655Z', + groupId: '9999999999999', + groupIp: '108.77.84.x', + groupName: 'Default Group', + id: '1845174760470303882', + inRemoteShellSession: false, + infected: false, + installerType: '.deb', + isActive: true, + isDecommissioned: false, + isPendingUninstall: false, + isUninstalled: false, + isUpToDate: true, + lastActiveDate: '2023-12-26T21:34:28.032981Z', + lastIpToMgmt: '192.168.64.2', + lastLoggedInUserName: '', + licenseKey: '', + locationEnabled: false, + locationType: 'not_supported', + locations: null, + machineType: 'server', + mitigationMode: 'detect', + mitigationModeSuspicious: 'detect', + modelName: 'QEMU QEMU Virtual Machine', + networkInterfaces: [ + { + gatewayIp: '192.168.64.1', + gatewayMacAddress: 'be:d0:74:50:d8:64', + id: '1845174760470303883', + inet: ['192.168.64.2'], + inet6: ['fdf4:f033:b1d4:8c51:5054:ff:febc:6253'], + name: 'enp0s1', + physical: '52:54:00:BC:62:53', + }, + ], + networkQuarantineEnabled: false, + networkStatus: 'connecting', + operationalState: 'na', + operationalStateExpiration: null, + osArch: '64 bit', + osName: 'Linux', + osRevision: 'Ubuntu 22.04.3 LTS 5.15.0-91-generic', + osStartTime: '2023-12-21T20:31:51Z', + osType: 'linux', + osUsername: 'root', + rangerStatus: 'Enabled', + rangerVersion: '23.4.0.9', + registeredAt: '2023-12-21T20:32:52.286752Z', + remoteProfilingState: 'disabled', + remoteProfilingStateExpiration: null, + scanAbortedAt: null, + scanFinishedAt: '2023-12-21T20:57:55.690655Z', + scanStartedAt: '2023-12-21T20:33:31.170460Z', + scanStatus: 'finished', + serialNumber: null, + showAlertIcon: false, + siteId: '88888888888', + siteName: 'Default site', + storageName: null, + storageType: null, + tags: { sentinelone: [] }, + threatRebootRequired: false, + totalMemory: 1966, + updatedAt: '2023-12-26T21:35:35.986596Z', + userActionsNeeded: [], + uuid: 'a2f4603d-c9e2-d7a2-bec2-0d646f3bbc9f', + }, + ], + }; +}; + +const createConnectorActionsClientMock = (): ActionsClientMock => { + const client = responseActionsClientMock.createConnectorActionsClient(); + + (client.getAll as jest.Mock).mockImplementation(async () => { + const result: ConnectorWithExtraFindData[] = [ + // SentinelOne connector + responseActionsClientMock.createConnector({ + actionTypeId: SENTINELONE_CONNECTOR_ID, + id: 's1-connector-instance-id', + }), + ]; + + return result; + }); + + (client.execute as jest.Mock).mockImplementation( + async (options: Parameters[0]) => { + const subAction = options.params.subAction; + + switch (subAction) { + case SUB_ACTION.GET_AGENTS: + return responseActionsClientMock.createConnectorActionExecuteResponse({ + data: createSentinelOneGetAgentsApiResponseMock(), + }); + + default: + return responseActionsClientMock.createConnectorActionExecuteResponse(); + } + } + ); + + return client; +}; + +const createConstructorOptionsMock = (): SentinelOneActionsClientOptionsMock => { + return { + ...responseActionsClientMock.createConstructorOptions(), + connectorActions: createConnectorActionsClientMock(), + }; +}; + +export const sentinelOneMock = { + createGetAgentsResponse: createSentinelOneGetAgentsApiResponseMock, + createConnectorActionsClient: createConnectorActionsClientMock, + createConstructorOptions: createConstructorOptionsMock, +}; diff --git a/x-pack/plugins/security_solution/server/endpoint/services/actions/clients/sentinelone/sentinel_one_actions_client.test.ts b/x-pack/plugins/security_solution/server/endpoint/services/actions/clients/sentinelone/sentinel_one_actions_client.test.ts index a56b54ce2e65..c506e8615ed0 100644 --- a/x-pack/plugins/security_solution/server/endpoint/services/actions/clients/sentinelone/sentinel_one_actions_client.test.ts +++ b/x-pack/plugins/security_solution/server/endpoint/services/actions/clients/sentinelone/sentinel_one_actions_client.test.ts @@ -7,11 +7,16 @@ import type { ResponseActionsClient } from '../lib/types'; import { responseActionsClientMock } from '../mocks'; -import type { SentinelOneActionsClientOptions } from '../../..'; -import { SentinelOneActionsClient } from '../../..'; +import { SentinelOneActionsClient } from './sentinel_one_actions_client'; import { getActionDetailsById as _getActionDetailsById } from '../../action_details_by_id'; import { ResponseActionsClientError, ResponseActionsNotSupportedError } from '../errors'; import type { ActionsClientMock } from '@kbn/actions-plugin/server/actions_client/actions_client.mock'; +import type { SentinelOneActionsClientOptionsMock } from './mock'; +import { sentinelOneMock } from './mock'; +import { + ENDPOINT_ACTION_RESPONSES_INDEX, + ENDPOINT_ACTIONS_INDEX, +} from '../../../../../../common/endpoint/constants'; jest.mock('../../action_details_by_id', () => { const originalMod = jest.requireActual('../../action_details_by_id'); @@ -25,27 +30,20 @@ jest.mock('../../action_details_by_id', () => { const getActionDetailsByIdMock = _getActionDetailsById as jest.Mock; describe('SentinelOneActionsClient class', () => { - let classConstructorOptions: SentinelOneActionsClientOptions; + let classConstructorOptions: SentinelOneActionsClientOptionsMock; let s1ActionsClient: ResponseActionsClient; let connectorActionsMock: ActionsClientMock; - const createS1IsolateOptions = () => + const createS1IsolationOptions = () => responseActionsClientMock.createIsolateOptions({ agent_type: 'sentinel_one' }); beforeEach(() => { - connectorActionsMock = responseActionsClientMock.createConnectorActionsClient(); - - connectorActionsMock.getAll(); - - classConstructorOptions = { - ...responseActionsClientMock.createConstructorOptions(), - connectorActions: connectorActionsMock, - }; + classConstructorOptions = sentinelOneMock.createConstructorOptions(); + connectorActionsMock = classConstructorOptions.connectorActions; s1ActionsClient = new SentinelOneActionsClient(classConstructorOptions); }); it.each([ - 'release', 'killProcess', 'suspendProcess', 'runningProcesses', @@ -66,7 +64,7 @@ describe('SentinelOneActionsClient class', () => { connectorActionsMock.getAll.mockImplementation(async () => { throw new Error('oh oh'); }); - const responsePromise = s1ActionsClient.isolate(createS1IsolateOptions()); + const responsePromise = s1ActionsClient.isolate(createS1IsolationOptions()); await expect(responsePromise).rejects.toBeInstanceOf(ResponseActionsClientError); await expect(responsePromise).rejects.toHaveProperty( @@ -81,7 +79,7 @@ describe('SentinelOneActionsClient class', () => { throw new Error('oh oh'); }); - await expect(s1ActionsClient.isolate(createS1IsolateOptions())).rejects.toMatchObject({ + await expect(s1ActionsClient.isolate(createS1IsolationOptions())).rejects.toMatchObject({ message: `Unable to retrieve list of stack connectors: oh oh`, statusCode: 400, }); @@ -100,14 +98,14 @@ describe('SentinelOneActionsClient class', () => { ])('should error if: %s', async (_, getAllImplementation) => { (connectorActionsMock.getAll as jest.Mock).mockImplementation(getAllImplementation); - await expect(s1ActionsClient.isolate(createS1IsolateOptions())).rejects.toMatchObject({ + await expect(s1ActionsClient.isolate(createS1IsolationOptions())).rejects.toMatchObject({ message: `No SentinelOne stack connector found`, statusCode: 400, }); }); it('should error if multiple agent ids are received', async () => { - const payload = createS1IsolateOptions(); + const payload = createS1IsolationOptions(); payload.endpoint_ids.push('second-host-id'); await expect(s1ActionsClient.isolate(payload)).rejects.toMatchObject({ @@ -118,7 +116,7 @@ describe('SentinelOneActionsClient class', () => { describe(`#isolate()`, () => { it('should send action to sentinelone', async () => { - await s1ActionsClient.isolate(createS1IsolateOptions()); + await s1ActionsClient.isolate(createS1IsolationOptions()); expect(connectorActionsMock.execute as jest.Mock).toHaveBeenCalledWith({ actionId: 's1-connector-instance-id', @@ -132,10 +130,82 @@ describe('SentinelOneActionsClient class', () => { }); it('should write action request and response to endpoint indexes', async () => { - await s1ActionsClient.isolate(createS1IsolateOptions()); + await s1ActionsClient.isolate(createS1IsolationOptions()); + + expect(classConstructorOptions.esClient.index).toHaveBeenCalledTimes(2); + expect(classConstructorOptions.esClient.index).toHaveBeenNthCalledWith( + 1, + { + document: { + '@timestamp': expect.any(String), + EndpointActions: { + action_id: expect.any(String), + data: { + command: 'isolate', + comment: 'test comment', + parameters: undefined, + hosts: { + '1-2-3': { + name: 'sentinelone-1460', + }, + }, + }, + expiration: expect.any(String), + input_type: 'sentinel_one', + type: 'INPUT_ACTION', + }, + agent: { id: ['1-2-3'] }, + user: { id: 'foo' }, + }, + index: ENDPOINT_ACTIONS_INDEX, + refresh: 'wait_for', + }, + { meta: true } + ); + expect(classConstructorOptions.esClient.index).toHaveBeenNthCalledWith(2, { + document: { + '@timestamp': expect.any(String), + EndpointActions: { + action_id: expect.any(String), + data: { command: 'isolate' }, + input_type: 'sentinel_one', + started_at: expect.any(String), + completed_at: expect.any(String), + }, + agent: { id: ['1-2-3'] }, + error: undefined, + }, + index: ENDPOINT_ACTION_RESPONSES_INDEX, + refresh: 'wait_for', + }); + }); + + it('should return action details', async () => { + await s1ActionsClient.isolate(createS1IsolationOptions()); + + expect(getActionDetailsByIdMock).toHaveBeenCalled(); + }); + }); + + describe('#release()', () => { + it('should send action to sentinelone', async () => { + await s1ActionsClient.release(createS1IsolationOptions()); + + expect(connectorActionsMock.execute as jest.Mock).toHaveBeenCalledWith({ + actionId: 's1-connector-instance-id', + params: { + subAction: 'releaseHost', + subActionParams: { + uuid: '1-2-3', + }, + }, + }); + }); + + it('should write action request and response to endpoint indexes', async () => { + await s1ActionsClient.release(createS1IsolationOptions()); - expect(classConstructorOptions.esClient.index).toHaveBeenCalledTimes(1); - // FIXME:PT once we start writing the Response, check above should be removed and new assertion added for it + expect(classConstructorOptions.esClient.index).toHaveBeenCalledTimes(2); expect(classConstructorOptions.esClient.index).toHaveBeenNthCalledWith( 1, { @@ -143,7 +213,16 @@ describe('SentinelOneActionsClient class', () => { '@timestamp': expect.any(String), EndpointActions: { action_id: expect.any(String), - data: { command: 'isolate', comment: 'test comment', parameters: undefined }, + data: { + command: 'unisolate', + comment: 'test comment', + parameters: undefined, + hosts: { + '1-2-3': { + name: 'sentinelone-1460', + }, + }, + }, expiration: expect.any(String), input_type: 'sentinel_one', type: 'INPUT_ACTION', @@ -151,15 +230,31 @@ describe('SentinelOneActionsClient class', () => { agent: { id: ['1-2-3'] }, user: { id: 'foo' }, }, - index: '.logs-endpoint.actions-default', + index: ENDPOINT_ACTIONS_INDEX, refresh: 'wait_for', }, { meta: true } ); + expect(classConstructorOptions.esClient.index).toHaveBeenNthCalledWith(2, { + document: { + '@timestamp': expect.any(String), + EndpointActions: { + action_id: expect.any(String), + data: { command: 'unisolate' }, + input_type: 'sentinel_one', + started_at: expect.any(String), + completed_at: expect.any(String), + }, + agent: { id: ['1-2-3'] }, + error: undefined, + }, + index: ENDPOINT_ACTION_RESPONSES_INDEX, + refresh: 'wait_for', + }); }); it('should return action details', async () => { - await s1ActionsClient.isolate(createS1IsolateOptions()); + await s1ActionsClient.release(createS1IsolationOptions()); expect(getActionDetailsByIdMock).toHaveBeenCalled(); }); diff --git a/x-pack/plugins/security_solution/server/endpoint/services/actions/clients/sentinelone/sentinel_one_actions_client.ts b/x-pack/plugins/security_solution/server/endpoint/services/actions/clients/sentinelone/sentinel_one_actions_client.ts index 4837f427a926..d196232e8391 100644 --- a/x-pack/plugins/security_solution/server/endpoint/services/actions/clients/sentinelone/sentinel_one_actions_client.ts +++ b/x-pack/plugins/security_solution/server/endpoint/services/actions/clients/sentinelone/sentinel_one_actions_client.ts @@ -13,14 +13,23 @@ import { import type { ConnectorWithExtraFindData } from '@kbn/actions-plugin/server/application/connector/types'; import { once } from 'lodash'; import type { ActionTypeExecutorResult } from '@kbn/actions-plugin/common'; -import { dump } from '../../../../utils/dump'; +import type { + SentinelOneGetAgentsResponse, + SentinelOneGetAgentsParams, +} from '@kbn/stack-connectors-plugin/common/sentinelone/types'; +import type { ResponseActionAgentType } from '../../../../../../common/endpoint/service/response_actions/constants'; +import type { SentinelOneConnectorExecuteOptions } from './types'; +import { stringify } from '../../../../utils/stringify'; import { ResponseActionsClientError } from '../errors'; -import type { ActionDetails } from '../../../../../../common/endpoint/types'; +import type { ActionDetails, LogsEndpointAction } from '../../../../../../common/endpoint/types'; import type { IsolationRouteRequestBody, BaseActionRequestBody, } from '../../../../../../common/api/endpoint'; -import type { ResponseActionsClientOptions } from '../lib/base_response_actions_client'; +import type { + ResponseActionsClientOptions, + ResponseActionsClientWriteActionRequestToEndpointIndexOptions, +} from '../lib/base_response_actions_client'; import { ResponseActionsClientImpl } from '../lib/base_response_actions_client'; export type SentinelOneActionsClientOptions = ResponseActionsClientOptions & { @@ -28,6 +37,7 @@ export type SentinelOneActionsClientOptions = ResponseActionsClientOptions & { }; export class SentinelOneActionsClient extends ResponseActionsClientImpl { + protected readonly agentType: ResponseActionAgentType = 'sentinel_one'; private readonly connectorActionsClient: ActionsClient; private readonly getConnector: () => Promise; @@ -67,14 +77,27 @@ export class SentinelOneActionsClient extends ResponseActionsClientImpl { }); } + protected async writeActionRequestToEndpointIndex( + actionRequest: Omit + ): Promise { + const agentId = actionRequest.endpoint_ids[0]; + const agentDetails = await this.getAgentDetails(agentId); + + return super.writeActionRequestToEndpointIndex({ + ...actionRequest, + hosts: { + [agentId]: { name: agentDetails.computerName }, + }, + }); + } + /** - * Sends actions to SentinelOne directly + * Sends actions to SentinelOne directly (via Connector) * @private */ private async sendAction( actionType: SUB_ACTION, actionParams: object - // FIXME:PT type properly the options above once PR 168441 for 8.12 merges ): Promise> { const { id: connectorId } = await this.getConnector(); const executeOptions: Parameters[0] = { @@ -86,13 +109,13 @@ export class SentinelOneActionsClient extends ResponseActionsClientImpl { }; this.log.debug( - `calling connector actions 'execute()' for SentinelOne with:\n${dump(executeOptions)}` + `calling connector actions 'execute()' for SentinelOne with:\n${stringify(executeOptions)}` ); const actionSendResponse = await this.connectorActionsClient.execute(executeOptions); if (actionSendResponse.status === 'error') { - this.log.error(dump(actionSendResponse)); + this.log.error(stringify(actionSendResponse)); throw new ResponseActionsClientError( `Attempt to send [${actionType}] to SentinelOne failed: ${ @@ -103,12 +126,50 @@ export class SentinelOneActionsClient extends ResponseActionsClientImpl { ); } - this.log.debug(`Response:\n${dump(actionSendResponse)}`); + this.log.debug(`Response:\n${stringify(actionSendResponse)}`); return actionSendResponse; } + private async getAgentDetails(id: string): Promise { + const { id: connectorId } = await this.getConnector(); + const executeOptions: SentinelOneConnectorExecuteOptions = { + actionId: connectorId, + params: { + subAction: SUB_ACTION.GET_AGENTS, + subActionParams: { + uuid: id, + }, + }, + }; + + let s1ApiResponse: SentinelOneGetAgentsResponse | undefined; + + try { + const response = (await this.connectorActionsClient.execute( + executeOptions + )) as ActionTypeExecutorResult; + + this.log.debug(`Response for SentinelOne agent id [${id}] returned:\n${stringify(response)}`); + + s1ApiResponse = response.data; + } catch (err) { + throw new ResponseActionsClientError( + `Error while attempting to retrieve SentinelOne host with agent id [${id}]`, + 500, + err + ); + } + + if (!s1ApiResponse || !s1ApiResponse.data[0]) { + throw new ResponseActionsClientError(`SentinelOne agent id [${id}] not found`, 404); + } + + return s1ApiResponse.data[0]; + } + private async validateRequest(payload: BaseActionRequestBody): Promise { + // TODO:PT support multiple agents if (payload.endpoint_ids.length > 1) { throw new ResponseActionsClientError( `[body.endpoint_ids]: Multiple agents IDs not currently supported for SentinelOne`, @@ -118,30 +179,43 @@ export class SentinelOneActionsClient extends ResponseActionsClientImpl { } async isolate(options: IsolationRouteRequestBody): Promise { - // TODO:PT support multiple agents await this.validateRequest(options); + await this.sendAction(SUB_ACTION.ISOLATE_HOST, { uuid: options.endpoint_ids[0] }); - const agentUUID = options.endpoint_ids[0]; - - await this.sendAction(SUB_ACTION.ISOLATE_HOST, { - uuid: agentUUID, + const reqIndexOptions: ResponseActionsClientWriteActionRequestToEndpointIndexOptions = { + ...options, + command: 'isolate', + }; + const actionRequestDoc = await this.writeActionRequestToEndpointIndex(reqIndexOptions); + await this.writeActionResponseToEndpointIndex({ + actionId: actionRequestDoc.EndpointActions.action_id, + agentId: actionRequestDoc.agent.id, + data: { + command: actionRequestDoc.EndpointActions.data.command, + }, }); - // FIXME:PT need to grab data from the response above and store it with the Request or Response documents on our side + return this.fetchActionDetails(actionRequestDoc.EndpointActions.action_id); + } + + async release(options: IsolationRouteRequestBody): Promise { + await this.validateRequest(options); + await this.sendAction(SUB_ACTION.RELEASE_HOST, { + uuid: options.endpoint_ids[0], + }); const actionRequestDoc = await this.writeActionRequestToEndpointIndex({ ...options, - command: 'isolate', + command: 'unisolate', }); - // TODO: un-comment code below once we have proper authz given to `kibana_system` account (security issue #8190) - // await this.writeActionResponseToEndpointIndex({ - // actionId: actionRequestDoc.EndpointActions.action_id, - // agentId: actionRequestDoc.agent.id, - // data: { - // command: actionRequestDoc.EndpointActions.data.command, - // }, - // }); + await this.writeActionResponseToEndpointIndex({ + actionId: actionRequestDoc.EndpointActions.action_id, + agentId: actionRequestDoc.agent.id, + data: { + command: actionRequestDoc.EndpointActions.data.command, + }, + }); return this.fetchActionDetails(actionRequestDoc.EndpointActions.action_id); } diff --git a/x-pack/plugins/security_solution/server/endpoint/services/actions/clients/sentinelone/types.ts b/x-pack/plugins/security_solution/server/endpoint/services/actions/clients/sentinelone/types.ts new file mode 100644 index 000000000000..fbb28df5e444 --- /dev/null +++ b/x-pack/plugins/security_solution/server/endpoint/services/actions/clients/sentinelone/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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +/* eslint-disable @typescript-eslint/no-explicit-any */ + +import type { ActionsClient } from '@kbn/actions-plugin/server'; +import type { SUB_ACTION } from '@kbn/stack-connectors-plugin/common/sentinelone/constants'; + +type ConnectorActionsExecuteOptions = Parameters[0]; + +interface SentinelOneConnectorExecuteParams< + P extends Record = Record +> { + subAction: SUB_ACTION; + subActionParams: P; +} + +export type SentinelOneConnectorExecuteOptions< + P extends Record = Record +> = Omit & { + params: SentinelOneConnectorExecuteParams

    & Record; +}; diff --git a/x-pack/plugins/security_solution/server/endpoint/services/actions/create/index.ts b/x-pack/plugins/security_solution/server/endpoint/services/actions/create/index.ts index 1c3d57dc241b..94cd181edc5e 100644 --- a/x-pack/plugins/security_solution/server/endpoint/services/actions/create/index.ts +++ b/x-pack/plugins/security_solution/server/endpoint/services/actions/create/index.ts @@ -13,23 +13,13 @@ import type { ActionDetails, EndpointActionDataParameterTypes, HostMetadata, + EndpointActionResponseDataOutput, } from '../../../../../common/endpoint/types'; import type { EndpointAppContext } from '../../../types'; -import type { FeatureKeys } from '../../feature_usage'; import { getActionDetailsById } from '..'; import type { ActionCreateService, CreateActionMetadata, CreateActionPayload } from './types'; import { writeActionToIndices } from './write_action_to_indices'; -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'], - ['execute', 'EXECUTE'], -]); - const returnActionIdCommands: ResponseActionsApiCommandNames[] = ['isolate', 'unisolate']; export const actionCreateService = ( @@ -37,16 +27,18 @@ export const actionCreateService = ( endpointContext: EndpointAppContext ): ActionCreateService => { const createAction = async < - TOutputContent extends object = object, + TOutputContent extends EndpointActionResponseDataOutput = EndpointActionResponseDataOutput, TParameters extends EndpointActionDataParameterTypes = EndpointActionDataParameterTypes >( payload: CreateActionPayload, agents: string[], { minimumLicenseRequired = 'basic' }: CreateActionMetadata = {} ): Promise> => { - const featureKey = commandToFeatureKeyMap.get(payload.command) as FeatureKeys; + const usageService = endpointContext.service.getFeatureUsageService(); + const featureKey = usageService.getResponseActionFeatureKey(payload.command); + if (featureKey) { - endpointContext.service.getFeatureUsageService().notifyUsage(featureKey); + usageService.notifyUsage(featureKey); } // create an Action ID and use that to dispatch action to ES & Fleet Server diff --git a/x-pack/plugins/security_solution/server/endpoint/services/actions/create/types.ts b/x-pack/plugins/security_solution/server/endpoint/services/actions/create/types.ts index f8a10b18d594..131869e5248f 100644 --- a/x-pack/plugins/security_solution/server/endpoint/services/actions/create/types.ts +++ b/x-pack/plugins/security_solution/server/endpoint/services/actions/create/types.ts @@ -11,6 +11,7 @@ import type { ResponseActionBodySchema } from '../../../../../common/api/endpoin import type { ActionDetails, EndpointActionDataParameterTypes, + EndpointActionResponseDataOutput, } from '../../../../../common/endpoint/types'; import type { ResponseActionsApiCommandNames } from '../../../../../common/endpoint/service/response_actions/constants'; @@ -30,7 +31,7 @@ export interface CreateActionMetadata { export interface ActionCreateService { createActionFromAlert: (payload: CreateActionPayload, agents: string[]) => Promise; createAction: < - TOutputContent extends object = object, + TOutputContent extends EndpointActionResponseDataOutput = EndpointActionResponseDataOutput, TParameters extends EndpointActionDataParameterTypes = EndpointActionDataParameterTypes >( payload: CreateActionPayload, diff --git a/x-pack/plugins/security_solution/server/endpoint/services/actions/create/write_action_to_indices.ts b/x-pack/plugins/security_solution/server/endpoint/services/actions/create/write_action_to_indices.ts index b502ec082c69..a0626b2e4d88 100644 --- a/x-pack/plugins/security_solution/server/endpoint/services/actions/create/write_action_to_indices.ts +++ b/x-pack/plugins/security_solution/server/endpoint/services/actions/create/write_action_to_indices.ts @@ -10,6 +10,7 @@ import type { Logger } from '@kbn/core/server'; import moment from 'moment'; import type { LicenseType } from '@kbn/licensing-plugin/common/types'; import type { FleetActionRequest } from '@kbn/fleet-plugin/server/services/actions/types'; +import { isExecuteAction } from '../../../../../common/endpoint/service/response_actions/type_guards'; import { DEFAULT_EXECUTE_ACTION_TIMEOUT } from '../../../../../common/endpoint/service/response_actions/constants'; import { ENDPOINT_ACTIONS_DS, @@ -143,6 +144,7 @@ export const writeActionToIndices = async ({ completed_at: moment().toISOString(), started_at: moment().toISOString(), data: doc.EndpointActions.data, + input_type: 'endpoint', }, }, logger, @@ -193,8 +195,8 @@ export const getActionParameters = ( action: Pick ): ResponseActionsExecuteParameters | Readonly<{}> | undefined => { // set timeout to 4h (if not specified or when timeout is specified as 0) when command is `execute` - if (action.command === 'execute') { - const actionRequestParams = action.parameters as ResponseActionsExecuteParameters; + if (isExecuteAction(action)) { + const actionRequestParams = action.parameters; if (typeof actionRequestParams?.timeout === 'undefined') { return { ...actionRequestParams, timeout: DEFAULT_EXECUTE_ACTION_TIMEOUT }; } diff --git a/x-pack/plugins/security_solution/server/endpoint/services/actions/fetch_action_responses.test.ts b/x-pack/plugins/security_solution/server/endpoint/services/actions/fetch_action_responses.test.ts new file mode 100644 index 000000000000..012379758fab --- /dev/null +++ b/x-pack/plugins/security_solution/server/endpoint/services/actions/fetch_action_responses.test.ts @@ -0,0 +1,232 @@ +/* + * 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 { applyActionListEsSearchMock } from './mocks'; +import { elasticsearchServiceMock } from '@kbn/core-elasticsearch-server-mocks'; +import type { ElasticsearchClientMock } from '@kbn/core-elasticsearch-client-server-mocks'; +import { fetchActionResponses } from './fetch_action_responses'; +import { BaseDataGenerator } from '../../../../common/endpoint/data_generators/base_data_generator'; +import { AGENT_ACTIONS_RESULTS_INDEX } from '@kbn/fleet-plugin/common'; +import { ENDPOINT_ACTION_RESPONSES_INDEX_PATTERN } from '../../../../common/endpoint/constants'; +import { ACTIONS_SEARCH_PAGE_SIZE } from './constants'; + +describe('fetchActionResponses()', () => { + let esClientMock: ElasticsearchClientMock; + + beforeEach(() => { + esClientMock = elasticsearchServiceMock.createScopedClusterClient().asInternalUser; + applyActionListEsSearchMock(esClientMock); + }); + + it('should return results', async () => { + await expect(fetchActionResponses({ esClient: esClientMock })).resolves.toEqual({ + data: [ + { + _id: 'ef278144-d8b9-45c6-9c3c-484c86b57d0b', + _index: '.fleet-actions-results', + _score: 1, + _source: { + '@timestamp': '2022-04-30T16:08:47.449Z', + action_data: { + command: 'get-file', + comment: '', + }, + action_id: '123', + agent_id: 'agent-a', + completed_at: '2022-04-30T10:53:59.449Z', + error: '', + started_at: '2022-04-30T12:56:00.449Z', + }, + }, + { + _id: 'ef278144-d8b9-45c6-9c3c-484c86b57d0b', + _index: '.ds-.logs-endpoint.action.responses-some_namespace-something', + _score: 1, + _source: { + '@timestamp': '2022-04-30T16:08:47.449Z', + EndpointActions: { + action_id: '123', + completed_at: '2022-04-30T10:53:59.449Z', + data: { + command: 'get-file', + comment: '', + output: { + content: { + code: 'ra_get-file_success_done', + contents: [ + { + file_name: 'bad_file.txt', + path: '/some/path/bad_file.txt', + sha256: '9558c5cb39622e9b3653203e772b129d6c634e7dbd7af1b244352fc1d704601f', + size: 1234, + type: 'file', + }, + ], + zip_size: 123, + }, + type: 'json', + }, + }, + started_at: '2022-04-30T12:56:00.449Z', + }, + agent: { + id: 'agent-a', + }, + }, + }, + { + _id: 'ef278144-d8b9-45c6-9c3c-484c86b57d0b', + _index: '.fleet-actions-results', + _score: 1, + _source: { + '@timestamp': '2022-04-30T16:08:47.449Z', + action_data: { + command: 'get-file', + comment: '', + }, + action_id: '123', + agent_id: 'agent-a', + completed_at: '2022-04-30T10:53:59.449Z', + error: '', + started_at: '2022-04-30T12:56:00.449Z', + }, + }, + { + _id: 'ef278144-d8b9-45c6-9c3c-484c86b57d0b', + _index: '.ds-.logs-endpoint.action.responses-some_namespace-something', + _score: 1, + _source: { + '@timestamp': '2022-04-30T16:08:47.449Z', + EndpointActions: { + action_id: '123', + completed_at: '2022-04-30T10:53:59.449Z', + data: { + command: 'get-file', + comment: '', + output: { + content: { + code: 'ra_get-file_success_done', + contents: [ + { + file_name: 'bad_file.txt', + path: '/some/path/bad_file.txt', + sha256: '9558c5cb39622e9b3653203e772b129d6c634e7dbd7af1b244352fc1d704601f', + size: 1234, + type: 'file', + }, + ], + zip_size: 123, + }, + type: 'json', + }, + }, + started_at: '2022-04-30T12:56:00.449Z', + }, + agent: { + id: 'agent-a', + }, + }, + }, + ], + }); + }); + + it('should return empty array with no responses exist', async () => { + applyActionListEsSearchMock(esClientMock, undefined, BaseDataGenerator.toEsSearchResponse([])); + + await expect(fetchActionResponses({ esClient: esClientMock })).resolves.toEqual({ data: [] }); + }); + + it('should query both fleet and endpoint indexes', async () => { + await fetchActionResponses({ esClient: esClientMock }); + const expectedQuery = { + query: { + bool: { + filter: [], + }, + }, + }; + + expect(esClientMock.search).toHaveBeenCalledWith( + { index: AGENT_ACTIONS_RESULTS_INDEX, size: ACTIONS_SEARCH_PAGE_SIZE, body: expectedQuery }, + { ignore: [404] } + ); + expect(esClientMock.search).toHaveBeenCalledWith( + { + index: ENDPOINT_ACTION_RESPONSES_INDEX_PATTERN, + size: ACTIONS_SEARCH_PAGE_SIZE, + body: expectedQuery, + }, + { ignore: [404] } + ); + }); + + it('should filter by agentIds', async () => { + await fetchActionResponses({ esClient: esClientMock, agentIds: ['a', 'b', 'c'] }); + const expectedQuery = { + query: { bool: { filter: [{ terms: { agent_id: ['a', 'b', 'c'] } }] } }, + }; + + expect(esClientMock.search).toHaveBeenCalledWith( + expect.objectContaining({ index: AGENT_ACTIONS_RESULTS_INDEX, body: expectedQuery }), + { ignore: [404] } + ); + expect(esClientMock.search).toHaveBeenCalledWith( + expect.objectContaining({ + index: ENDPOINT_ACTION_RESPONSES_INDEX_PATTERN, + body: expectedQuery, + }), + { ignore: [404] } + ); + }); + + it('should filter by action ids', async () => { + await fetchActionResponses({ esClient: esClientMock, actionIds: ['a', 'b', 'c'] }); + const expectedQuery = { + query: { bool: { filter: [{ terms: { action_id: ['a', 'b', 'c'] } }] } }, + }; + + expect(esClientMock.search).toHaveBeenCalledWith( + expect.objectContaining({ index: AGENT_ACTIONS_RESULTS_INDEX, body: expectedQuery }), + { ignore: [404] } + ); + expect(esClientMock.search).toHaveBeenCalledWith( + expect.objectContaining({ + index: ENDPOINT_ACTION_RESPONSES_INDEX_PATTERN, + body: expectedQuery, + }), + { ignore: [404] } + ); + }); + + it('should filter by both agent and action ids', async () => { + await fetchActionResponses({ + esClient: esClientMock, + agentIds: ['1', '2'], + actionIds: ['a', 'b', 'c'], + }); + const expectedQuery = { + query: { + bool: { + filter: [{ terms: { agent_id: ['1', '2'] } }, { terms: { action_id: ['a', 'b', 'c'] } }], + }, + }, + }; + + expect(esClientMock.search).toHaveBeenCalledWith( + expect.objectContaining({ index: AGENT_ACTIONS_RESULTS_INDEX, body: expectedQuery }), + { ignore: [404] } + ); + expect(esClientMock.search).toHaveBeenCalledWith( + expect.objectContaining({ + index: ENDPOINT_ACTION_RESPONSES_INDEX_PATTERN, + body: expectedQuery, + }), + { ignore: [404] } + ); + }); +}); diff --git a/x-pack/plugins/security_solution/server/endpoint/services/actions/fetch_action_responses.ts b/x-pack/plugins/security_solution/server/endpoint/services/actions/fetch_action_responses.ts new file mode 100644 index 000000000000..7ed0bad9a42b --- /dev/null +++ b/x-pack/plugins/security_solution/server/endpoint/services/actions/fetch_action_responses.ts @@ -0,0 +1,89 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; +import { AGENT_ACTIONS_RESULTS_INDEX } from '@kbn/fleet-plugin/common'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type { + EndpointActionResponse, + LogsEndpointActionResponse, +} from '../../../../common/endpoint/types'; +import { ACTIONS_SEARCH_PAGE_SIZE } from './constants'; +import { catchAndWrapError } from '../../utils'; +import { ENDPOINT_ACTION_RESPONSES_INDEX_PATTERN } from '../../../../common/endpoint/constants'; + +interface FetchActionResponsesOptions { + esClient: ElasticsearchClient; + /** List of specific action ids to filter for */ + actionIds?: string[]; + /** List of specific agent ids to filter for */ + agentIds?: string[]; +} + +interface FetchActionResponsesResult { + data: Array>; +} + +/** + * Fetch Response Action responses + */ +export const fetchActionResponses = async ({ + esClient, + actionIds = [], + agentIds = [], +}: FetchActionResponsesOptions): Promise => { + const filter = []; + + if (agentIds?.length) { + filter.push({ terms: { agent_id: agentIds } }); + } + if (actionIds.length) { + filter.push({ terms: { action_id: actionIds } }); + } + + const query: estypes.QueryDslQueryContainer = { + bool: { + filter, + }, + }; + + // Get the Action Response(s) from both the Fleet action response index and the Endpoint + // action response index. + // We query both indexes separately in order to ensure they are both queried - example if the + // Fleet actions responses index does not exist yet, ES would generate a `404` and would + // never actually query the Endpoint Actions index. With support for 3rd party response + // actions, we need to ensure that both indexes are queried. + const [fleetResponses, endpointResponses] = await Promise.all([ + // Responses in Fleet index + esClient + .search( + { + index: AGENT_ACTIONS_RESULTS_INDEX, + size: ACTIONS_SEARCH_PAGE_SIZE, + body: { query }, + }, + { ignore: [404] } + ) + .catch(catchAndWrapError), + + // Responses in Endpoint index + esClient + .search( + { + index: ENDPOINT_ACTION_RESPONSES_INDEX_PATTERN, + size: ACTIONS_SEARCH_PAGE_SIZE, + body: { query }, + }, + { ignore: [404] } + ) + .catch(catchAndWrapError), + ]); + + return { + data: [...(fleetResponses?.hits?.hits ?? []), ...(endpointResponses?.hits?.hits ?? [])], + }; +}; diff --git a/x-pack/plugins/security_solution/server/endpoint/services/actions/mocks.ts b/x-pack/plugins/security_solution/server/endpoint/services/actions/mocks.ts index a4536f54b92d..0c5ac6cf38b3 100644 --- a/x-pack/plugins/security_solution/server/endpoint/services/actions/mocks.ts +++ b/x-pack/plugins/security_solution/server/endpoint/services/actions/mocks.ts @@ -9,6 +9,7 @@ import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { ElasticsearchClientMock } from '@kbn/core/server/mocks'; import { AGENT_ACTIONS_RESULTS_INDEX } from '@kbn/fleet-plugin/common'; import { Readable } from 'stream'; +import type { TransportRequestOptions } from '@elastic/transport'; import type { HapiReadableStream } from '../../../types'; import { EndpointActionGenerator } from '../../../../common/endpoint/data_generators/endpoint_action_generator'; import { FleetActionGenerator } from '../../../../common/endpoint/data_generators/fleet_action_generator'; @@ -146,15 +147,24 @@ export const applyActionListEsSearchMock = ( // @ts-expect-error incorrect type esClient.search.mockImplementation(async (...args) => { const params = args[0] ?? {}; + const options: TransportRequestOptions = args[1] ?? {}; const indexes = Array.isArray(params.index) ? params.index : [params.index]; if (indexes.includes(ENDPOINT_ACTIONS_INDEX)) { - return { body: { ...actionRequests } }; + if (options.meta) { + return { body: { ...actionRequests } }; + } + + return actionRequests; } else if ( indexes.includes(AGENT_ACTIONS_RESULTS_INDEX) || indexes.includes(ENDPOINT_ACTION_RESPONSES_INDEX_PATTERN) ) { - return { body: { ...actionResponses } }; + if (options.meta) { + return { body: { ...actionResponses } }; + } + + return actionResponses; } if (priorSearchMockImplementation) { diff --git a/x-pack/plugins/security_solution/server/endpoint/services/actions/utils.test.ts b/x-pack/plugins/security_solution/server/endpoint/services/actions/utils.test.ts index b5c2119281e7..e63caeb222be 100644 --- a/x-pack/plugins/security_solution/server/endpoint/services/actions/utils.test.ts +++ b/x-pack/plugins/security_solution/server/endpoint/services/actions/utils.test.ts @@ -8,6 +8,7 @@ import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { EndpointActionGenerator } from '../../../../common/endpoint/data_generators/endpoint_action_generator'; import { FleetActionGenerator } from '../../../../common/endpoint/data_generators/fleet_action_generator'; +import type { NormalizedActionRequest } from './utils'; import { categorizeActionResults, categorizeResponseResults, @@ -18,6 +19,7 @@ import { isLogsEndpointAction, isLogsEndpointActionResponse, mapToNormalizedActionRequest, + createActionDetailsRecord, } from './utils'; import type { ActivityLogAction, @@ -28,10 +30,12 @@ import type { EndpointActivityLogActionResponse, LogsEndpointAction, LogsEndpointActionResponse, + EndpointActionResponseDataOutput, } from '../../../../common/endpoint/types'; import { v4 as uuidv4 } from 'uuid'; import type { Results } from '../../routes/actions/mocks'; import { mockAuditLogSearchResult } from '../../routes/actions/mocks'; +import { ActivityLogItemTypes } from '../../../../common/endpoint/types'; describe('When using Actions service utilities', () => { let fleetActionGenerator: FleetActionGenerator; @@ -72,6 +76,8 @@ describe('When using Actions service utilities', () => { ) ).toEqual({ agents: ['6e6796b0-af39-4f12-b025-fcb06db499e5'], + agentType: 'endpoint', + hosts: {}, command: 'kill-process', comment: expect.any(String), createdAt: '2022-04-27T16:08:47.449Z', @@ -92,6 +98,8 @@ describe('When using Actions service utilities', () => { ) ).toEqual({ agents: ['90d62689-f72d-4a05-b5e3-500cad0dc366'], + agentType: 'endpoint', + hosts: {}, command: 'kill-process', comment: expect.any(String), createdAt: '2022-04-27T16:08:47.449Z', @@ -176,7 +184,7 @@ describe('When using Actions service utilities', () => { agent: { id: '123' }, EndpointActions: { completed_at: COMPLETED_AT, - data: { output: { type: 'json', content: { foo: 'bar' } } }, + data: { output: { type: 'json', content: { code: 'aaa' } } }, }, }, }, @@ -198,7 +206,7 @@ describe('When using Actions service utilities', () => { outputs: { '123': { content: { - foo: 'bar', + code: 'aaa', }, type: 'json', }, @@ -388,9 +396,18 @@ describe('When using Actions service utilities', () => { describe('with multiple agent ids', () => { let agentIds: string[]; let actionId: string; - let action123Responses: Array; - let action456Responses: Array; - let action789Responses: Array; + let action123Responses: Array< + | ActivityLogActionResponse + | EndpointActivityLogActionResponse + >; + let action456Responses: Array< + | ActivityLogActionResponse + | EndpointActivityLogActionResponse + >; + let action789Responses: Array< + | ActivityLogActionResponse + | EndpointActivityLogActionResponse + >; beforeEach(() => { agentIds = ['123', '456', '789']; @@ -605,11 +622,11 @@ describe('When using Actions service utilities', () => { it('should include output for agents for which the action was complete', () => { // Add output to the completed actions ( - action123Responses[1] as EndpointActivityLogActionResponse + action123Responses[1] as EndpointActivityLogActionResponse ).item.data.EndpointActions.data.output = { type: 'json', content: { - foo: 'bar', + code: 'bar', }, }; @@ -662,7 +679,7 @@ describe('When using Actions service utilities', () => { outputs: { '123': { content: { - foo: 'bar', + code: 'bar', }, type: 'json', }, @@ -955,4 +972,121 @@ describe('When using Actions service utilities', () => { ).toEqual({ isExpired: false, status: 'failed' }); }); }); + + describe('#createActionDetailsRecord()', () => { + let actionRequest: NormalizedActionRequest; + let actionResponses: Array; + let agentHostInfo: Record; + + beforeEach(() => { + actionRequest = { + agents: ['6e6796b0-af39-4f12-b025-fcb06db499e5'], + command: 'kill-process', + comment: 'kill this one', + createdAt: '2022-04-27T16:08:47.449Z', + createdBy: 'elastic', + expiration: '2022-04-29T16:08:47.449Z', + id: '90d62689-f72d-4a05-b5e3-500cad0dc366', + type: 'ACTION_REQUEST', + parameters: undefined, + agentType: 'endpoint', + hosts: {}, + }; + + actionResponses = [ + { + type: ActivityLogItemTypes.FLEET_RESPONSE, + item: { + id: actionRequest.id, + data: fleetActionGenerator.generateResponse({ + action_id: actionRequest.id, + agent_id: actionRequest.agents[0], + }), + }, + }, + + { + type: ActivityLogItemTypes.RESPONSE, + item: { + id: actionRequest.id, + data: endpointActionGenerator.generateResponse({ + agent: { id: actionRequest.agents }, + EndpointActions: { + action_id: actionRequest.id, + }, + }), + }, + }, + ]; + + agentHostInfo = { + [actionRequest.agents[0]]: 'host-a', + }; + }); + + it('should return expected action details record', () => { + expect(createActionDetailsRecord(actionRequest, actionResponses, agentHostInfo)).toEqual({ + action: '90d62689-f72d-4a05-b5e3-500cad0dc366', + id: '90d62689-f72d-4a05-b5e3-500cad0dc366', + agentType: 'endpoint', + agents: ['6e6796b0-af39-4f12-b025-fcb06db499e5'], + command: 'kill-process', + comment: 'kill this one', + completedAt: expect.any(String), + startedAt: '2022-04-27T16:08:47.449Z', + status: 'successful', + wasSuccessful: true, + errors: undefined, + createdBy: 'elastic', + isCompleted: true, + isExpired: false, + parameters: undefined, + agentState: { + '6e6796b0-af39-4f12-b025-fcb06db499e5': { + completedAt: expect.any(String), + isCompleted: true, + wasSuccessful: true, + }, + }, + hosts: { + '6e6796b0-af39-4f12-b025-fcb06db499e5': { + name: 'host-a', + }, + }, + outputs: { + '6e6796b0-af39-4f12-b025-fcb06db499e5': { + content: { + code: 'ra_get-file_success_done', + contents: [ + { + file_name: 'bad_file.txt', + path: '/some/path/bad_file.txt', + sha256: '9558c5cb39622e9b3653203e772b129d6c634e7dbd7af1b244352fc1d704601f', + size: 1234, + type: 'file', + }, + ], + zip_size: 123, + }, + type: 'json', + }, + }, + }); + }); + + it('should populate host name from action request', () => { + agentHostInfo = {}; + actionRequest.hosts[actionRequest.agents[0]] = { name: 'host-b' }; + + expect( + createActionDetailsRecord(actionRequest, actionResponses, agentHostInfo) + ).toMatchObject({ + hosts: { + '6e6796b0-af39-4f12-b025-fcb06db499e5': { + name: 'host-b', + }, + }, + }); + }); + }); }); 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 1d16c944d2ce..b851b087c823 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 @@ -8,7 +8,10 @@ import type { ElasticsearchClient } from '@kbn/core/server'; import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { EcsError } from '@kbn/ecs'; -import type { ResponseActionsApiCommandNames } from '../../../../common/endpoint/service/response_actions/constants'; +import type { + ResponseActionsApiCommandNames, + ResponseActionAgentType, +} from '../../../../common/endpoint/service/response_actions/constants'; import { ENDPOINT_ACTIONS_DS, ENDPOINT_ACTION_RESPONSES_DS, @@ -26,6 +29,8 @@ import type { EndpointActivityLogActionResponse, LogsEndpointAction, LogsEndpointActionResponse, + EndpointActionResponseDataOutput, + WithAllKeys, } from '../../../../common/endpoint/types'; import { ActivityLogItemTypes } from '../../../../common/endpoint/types'; import type { EndpointMetadataService } from '../metadata'; @@ -44,14 +49,15 @@ export const isLogsEndpointAction = ( * @param item */ export const isLogsEndpointActionResponse = ( - item: EndpointActionResponse | LogsEndpointActionResponse -): item is LogsEndpointActionResponse => { + item: EndpointActionResponse | LogsEndpointActionResponse +): item is LogsEndpointActionResponse => { return 'EndpointActions' in item && 'agent' in item; }; -interface NormalizedActionRequest { +export interface NormalizedActionRequest { id: string; type: 'ACTION_REQUEST'; + agentType: ResponseActionAgentType; expiration: string; agents: string[]; createdBy: string; @@ -63,6 +69,8 @@ interface NormalizedActionRequest { ruleId?: string; ruleName?: string; error?: EcsError; + /** Host info that might have been stored along with the Action Request (ex. 3rd party EDR actions) */ + hosts: ActionDetails['hosts']; } /** @@ -80,6 +88,7 @@ export const mapToNormalizedActionRequest = ( agents: Array.isArray(actionRequest.agent.id) ? actionRequest.agent.id : [actionRequest.agent.id], + agentType: actionRequest.EndpointActions.input_type, command: actionRequest.EndpointActions.data.command, comment: actionRequest.EndpointActions.data.comment, createdBy: actionRequest.user.id, @@ -92,12 +101,14 @@ export const mapToNormalizedActionRequest = ( ruleId: actionRequest.rule?.id, ruleName: actionRequest.rule?.name, error: actionRequest.error, + hosts: actionRequest.EndpointActions.data.hosts ?? {}, }; } // Else, it's a Fleet Endpoint Action record return { agents: actionRequest.agents, + agentType: actionRequest.input_type, command: actionRequest.data.command, comment: actionRequest.data.comment, createdBy: actionRequest.user_id, @@ -106,6 +117,7 @@ export const mapToNormalizedActionRequest = ( id: actionRequest.action_id, type, parameters: actionRequest.data.parameters, + hosts: {}, }; }; @@ -114,11 +126,15 @@ type ActionCompletionInfo = Pick< 'isCompleted' | 'completedAt' | 'wasSuccessful' | 'errors' | 'outputs' | 'agentState' >; -export const getActionCompletionInfo = ( +export const getActionCompletionInfo = < + TOutputContent extends EndpointActionResponseDataOutput = EndpointActionResponseDataOutput +>( /** The normalized action request */ action: NormalizedActionRequest, /** List of action Log responses received for the action */ - actionResponses: Array + actionResponses: Array< + ActivityLogActionResponse | EndpointActivityLogActionResponse + > ): ActionCompletionInfo => { const agentIds = action.agents; const completedInfo: ActionCompletionInfo = { @@ -235,13 +251,15 @@ export const getActionStatus = ({ return { isExpired, status }; }; -interface NormalizedAgentActionResponse { +interface NormalizedAgentActionResponse< + TOutputContent extends EndpointActionResponseDataOutput = EndpointActionResponseDataOutput +> { isCompleted: boolean; completedAt: undefined | string; wasSuccessful: boolean; errors: undefined | string[]; fleetResponse: undefined | ActivityLogActionResponse; - endpointResponse: undefined | EndpointActivityLogActionResponse; + endpointResponse: undefined | EndpointActivityLogActionResponse; } type ActionResponseByAgentId = Record; @@ -251,8 +269,12 @@ type ActionResponseByAgentId = Record; * value is a object having information about the action responses associated with that agent id * @param actionResponses */ -const mapActionResponsesByAgentId = ( - actionResponses: Array +const mapActionResponsesByAgentId = < + TOutputContent extends EndpointActionResponseDataOutput = EndpointActionResponseDataOutput +>( + actionResponses: Array< + ActivityLogActionResponse | EndpointActivityLogActionResponse + > ): ActionResponseByAgentId => { const response: ActionResponseByAgentId = {}; @@ -337,7 +359,9 @@ const mapActionResponsesByAgentId = ( * @param actionResponse */ const getAgentIdFromActionResponse = ( - actionResponse: ActivityLogActionResponse | EndpointActivityLogActionResponse + actionResponse: + | ActivityLogActionResponse + | EndpointActivityLogActionResponse ): string => { const responseData = actionResponse.item.data; @@ -524,3 +548,47 @@ export const getAgentHostNamesWithIds = async ({ return agentsMetadataInfo; }; + +export const createActionDetailsRecord = ( + actionRequest: NormalizedActionRequest, + actionResponses: Array, + agentHostInfo: Record +): T => { + const { isCompleted, completedAt, wasSuccessful, errors, outputs, agentState } = + getActionCompletionInfo(actionRequest, actionResponses); + + const { isExpired, status } = getActionStatus({ + expirationDate: actionRequest.expiration, + isCompleted, + wasSuccessful, + }); + + const actionDetails: WithAllKeys = { + action: actionRequest.id, + id: actionRequest.id, + agentType: actionRequest.agentType, + agents: actionRequest.agents, + hosts: actionRequest.agents.reduce((acc, id) => { + acc[id] = { name: agentHostInfo[id] || actionRequest.hosts[id]?.name || '' }; + return acc; + }, {}), + command: actionRequest.command, + startedAt: actionRequest.createdAt, + isCompleted, + completedAt, + wasSuccessful, + errors, + isExpired, + status, + outputs, + agentState, + createdBy: actionRequest.createdBy, + comment: actionRequest.comment, + parameters: actionRequest.parameters, + alertIds: actionRequest.alertIds, + ruleId: actionRequest.ruleId, + ruleName: actionRequest.ruleName, + }; + + return actionDetails as T; +}; diff --git a/x-pack/plugins/security_solution/server/endpoint/services/feature_usage/feature_keys.ts b/x-pack/plugins/security_solution/server/endpoint/services/feature_usage/feature_keys.ts new file mode 100644 index 000000000000..b7e8b8ab8754 --- /dev/null +++ b/x-pack/plugins/security_solution/server/endpoint/services/feature_usage/feature_keys.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 type { ResponseActionsApiCommandNames } from '../../../../common/endpoint/service/response_actions/constants'; + +export const FEATURE_KEYS = { + HOST_ISOLATION: 'Host isolation', + HOST_ISOLATION_EXCEPTION: 'Host isolation exception', + HOST_ISOLATION_EXCEPTION_BY_POLICY: 'Host isolation exception by policy', + TRUSTED_APP_BY_POLICY: 'Trusted app by policy', + EVENT_FILTERS_BY_POLICY: 'Event filters by policy', + BLOCKLIST_BY_POLICY: 'Blocklists by policy', + RANSOMWARE_PROTECTION: 'Ransomeware protection', + MEMORY_THREAT_PROTECTION: 'Memory threat protection', + BEHAVIOR_PROTECTION: 'Behavior protection', + KILL_PROCESS: 'Kill process', + SUSPEND_PROCESS: 'Suspend process', + RUNNING_PROCESSES: 'Get running processes', + GET_FILE: 'Get file', + UPLOAD: 'Upload file', + EXECUTE: 'Execute command', + ALERTS_BY_PROCESS_ANCESTRY: 'Get related alerts by process ancestry', + ENDPOINT_EXCEPTIONS: 'Endpoint exceptions', +} as const; + +export type FeatureKeys = keyof typeof FEATURE_KEYS; + +const RESPONSE_ACTIONS_FEATURE_KEY: Readonly> = + { + isolate: 'HOST_ISOLATION', + unisolate: 'HOST_ISOLATION', + 'kill-process': 'KILL_PROCESS', + 'suspend-process': 'SUSPEND_PROCESS', + 'running-processes': 'RUNNING_PROCESSES', + 'get-file': 'GET_FILE', + execute: 'EXECUTE', + upload: 'UPLOAD', + }; + +export const getResponseActionFeatureKey = ( + responseAction: ResponseActionsApiCommandNames +): FeatureKeys | undefined => { + return RESPONSE_ACTIONS_FEATURE_KEY[responseAction]; +}; diff --git a/x-pack/plugins/security_solution/server/endpoint/services/feature_usage/index.ts b/x-pack/plugins/security_solution/server/endpoint/services/feature_usage/index.ts index 5c880f67847e..8b58f62e45e1 100644 --- a/x-pack/plugins/security_solution/server/endpoint/services/feature_usage/index.ts +++ b/x-pack/plugins/security_solution/server/endpoint/services/feature_usage/index.ts @@ -6,6 +6,6 @@ */ import { FeatureUsageService } from './service'; -export type { FeatureKeys } from './service'; +export type { FeatureKeys } from './feature_keys'; export const featureUsageService = new FeatureUsageService(); diff --git a/x-pack/plugins/security_solution/server/endpoint/services/feature_usage/mocks.ts b/x-pack/plugins/security_solution/server/endpoint/services/feature_usage/mocks.ts index 1eb1b3b82371..d032085bfe40 100644 --- a/x-pack/plugins/security_solution/server/endpoint/services/feature_usage/mocks.ts +++ b/x-pack/plugins/security_solution/server/endpoint/services/feature_usage/mocks.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { getResponseActionFeatureKey } from './feature_keys'; import type { FeatureUsageService } from './service'; import type { PolicyData } from '../../../../common/endpoint/types'; @@ -13,6 +14,7 @@ export function createFeatureUsageServiceMock() { setup: jest.fn(), start: jest.fn(), notifyUsage: jest.fn(), + getResponseActionFeatureKey: jest.fn(getResponseActionFeatureKey), } as unknown as jest.Mocked; } 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 ffebaac4420f..a236d6b569e2 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 @@ -7,37 +7,19 @@ import type { Values } from '@kbn/utility-types'; import type { LicensingPluginSetup, LicensingPluginStart } from '@kbn/licensing-plugin/server'; - -const FEATURES = { - HOST_ISOLATION: 'Host isolation', - HOST_ISOLATION_EXCEPTION: 'Host isolation exception', - HOST_ISOLATION_EXCEPTION_BY_POLICY: 'Host isolation exception by policy', - TRUSTED_APP_BY_POLICY: 'Trusted app by policy', - EVENT_FILTERS_BY_POLICY: 'Event filters by policy', - BLOCKLIST_BY_POLICY: 'Blocklists by policy', - RANSOMWARE_PROTECTION: 'Ransomeware protection', - MEMORY_THREAT_PROTECTION: 'Memory threat protection', - BEHAVIOR_PROTECTION: 'Behavior protection', - KILL_PROCESS: 'Kill process', - SUSPEND_PROCESS: 'Suspend process', - RUNNING_PROCESSES: 'Get running processes', - GET_FILE: 'Get file', - EXECUTE: 'Execute command', - ALERTS_BY_PROCESS_ANCESTRY: 'Get related alerts by process ancestry', - ENDPOINT_EXCEPTIONS: 'Endpoint exceptions', -} as const; - -export type FeatureKeys = keyof typeof FEATURES; +import type { ResponseActionsApiCommandNames } from '../../../../common/endpoint/service/response_actions/constants'; +import type { FeatureKeys } from './feature_keys'; +import { getResponseActionFeatureKey, FEATURE_KEYS } from './feature_keys'; export class FeatureUsageService { private licensingPluginStart: LicensingPluginStart | undefined; - private get notify(): (featureName: Values) => void { + private get notify(): (featureName: Values) => void { return this.licensingPluginStart?.featureUsage.notifyUsage || function () {}; } public setup(licensingPluginSetup: LicensingPluginSetup): void { - Object.values(FEATURES).map((featureValue) => + Object.values(FEATURE_KEYS).map((featureValue) => licensingPluginSetup.featureUsage.register(featureValue, 'platinum') ); } @@ -47,6 +29,12 @@ export class FeatureUsageService { } public notifyUsage(featureKey: FeatureKeys): void { - this.notify(FEATURES[featureKey]); + this.notify(FEATURE_KEYS[featureKey]); + } + + public getResponseActionFeatureKey( + responseAction: ResponseActionsApiCommandNames + ): FeatureKeys | undefined { + return getResponseActionFeatureKey(responseAction); } } diff --git a/x-pack/plugins/security_solution/server/endpoint/utils/action_list_helpers.test.ts b/x-pack/plugins/security_solution/server/endpoint/utils/action_list_helpers.test.ts index cfee4407500b..c552cb360153 100644 --- a/x-pack/plugins/security_solution/server/endpoint/utils/action_list_helpers.test.ts +++ b/x-pack/plugins/security_solution/server/endpoint/utils/action_list_helpers.test.ts @@ -5,15 +5,13 @@ * 2.0. */ -import { v4 as uuidv4 } from 'uuid'; import type { ScopedClusterClientMock } from '@kbn/core/server/mocks'; import { elasticsearchServiceMock } from '@kbn/core/server/mocks'; import { applyActionListEsSearchMock, createActionRequestsEsSearchResultsMock, - createActionResponsesEsSearchResultsMock, } from '../services/actions/mocks'; -import { getActions, getActionResponses } from './action_list_helpers'; +import { getActions } from './action_list_helpers'; describe('action helpers', () => { let mockScopedEsClient: ScopedClusterClientMock; @@ -36,18 +34,7 @@ describe('action helpers', () => { must: [ { bool: { - filter: [ - { - term: { - input_type: 'endpoint', - }, - }, - { - term: { - type: 'INPUT_ACTION', - }, - }, - ], + filter: [], }, }, ], @@ -96,16 +83,6 @@ describe('action helpers', () => { { bool: { filter: [ - { - term: { - input_type: 'endpoint', - }, - }, - { - term: { - type: 'INPUT_ACTION', - }, - }, { range: { '@timestamp': { @@ -210,16 +187,6 @@ describe('action helpers', () => { { bool: { filter: [ - { - term: { - input_type: 'endpoint', - }, - }, - { - term: { - type: 'INPUT_ACTION', - }, - }, { range: { '@timestamp': { @@ -307,97 +274,4 @@ describe('action helpers', () => { expect(actions.actionRequests?.body?.hits?.hits[0]._source?.agent.id).toEqual('agent-a'); }); }); - - describe('#getActionResponses', () => { - it('should use base filters correctly when no other filter options provided', async () => { - const esClient = mockScopedEsClient.asInternalUser; - applyActionListEsSearchMock(esClient); - await getActionResponses({ esClient, actionIds: [] }); - - expect(esClient.search).toHaveBeenCalledWith( - { - body: { - query: { - bool: { - filter: [], - }, - }, - }, - from: 0, - index: ['.fleet-actions-results', '.logs-endpoint.action.responses-*'], - size: 10000, - }, - { - headers: { - 'X-elastic-product-origin': 'fleet', - }, - ignore: [404], - meta: true, - } - ); - }); - it('should query with actionIds and elasticAgentIds when provided', async () => { - const actionIds = [uuidv4(), uuidv4()]; - const elasticAgentIds = ['123', '456']; - const esClient = mockScopedEsClient.asInternalUser; - applyActionListEsSearchMock(esClient); - await getActionResponses({ esClient, actionIds, elasticAgentIds }); - - expect(esClient.search).toHaveBeenCalledWith( - { - body: { - query: { - bool: { - filter: [ - { - terms: { - agent_id: elasticAgentIds, - }, - }, - { - terms: { - action_id: actionIds, - }, - }, - ], - }, - }, - }, - from: 0, - index: ['.fleet-actions-results', '.logs-endpoint.action.responses-*'], - size: 10000, - }, - { - headers: { - 'X-elastic-product-origin': 'fleet', - }, - ignore: [404], - meta: true, - } - ); - }); - it('should return expected output', async () => { - const esClient = mockScopedEsClient.asInternalUser; - const actionRes = createActionResponsesEsSearchResultsMock(); - applyActionListEsSearchMock(esClient, undefined, actionRes); - - const responses = await getActionResponses({ - esClient, - actionIds: ['123'], - elasticAgentIds: ['agent-a'], - }); - - const responseHits = responses.body.hits.hits; - - expect(responseHits.length).toEqual(2); - expect( - responseHits.map((e) => e._index).filter((e) => e.includes('.fleet-actions-results')).length - ).toEqual(1); - expect( - responseHits - .map((e) => e._index) - .filter((e) => e.includes('.logs-endpoint.action.responses')).length - ).toEqual(1); - }); - }); }); diff --git a/x-pack/plugins/security_solution/server/endpoint/utils/action_list_helpers.ts b/x-pack/plugins/security_solution/server/endpoint/utils/action_list_helpers.ts index c74373311cf7..4c1d7e584f21 100644 --- a/x-pack/plugins/security_solution/server/endpoint/utils/action_list_helpers.ts +++ b/x-pack/plugins/security_solution/server/endpoint/utils/action_list_helpers.ts @@ -5,19 +5,13 @@ * 2.0. */ -import type { ElasticsearchClient } from '@kbn/core/server'; import type { SearchRequest } from '@kbn/data-plugin/public'; import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { TransportResult } from '@elastic/elasticsearch'; import { fromKueryExpression, toElasticsearchQuery } from '@kbn/es-query'; import { ENDPOINT_ACTIONS_INDEX } from '../../../common/endpoint/constants'; -import type { - LogsEndpointAction, - EndpointActionResponse, - LogsEndpointActionResponse, -} from '../../../common/endpoint/types'; -import { ACTIONS_SEARCH_PAGE_SIZE, ACTION_RESPONSE_INDICES } from '../services/actions/constants'; +import type { LogsEndpointAction } from '../../../common/endpoint/types'; import { getDateFilters } from '../services/actions/utils'; import { catchAndWrapError } from './wrap_errors'; import type { GetActionDetailsListParam } from '../services/actions/action_list'; @@ -61,12 +55,7 @@ export const getActions = async ({ const dateFilters = getDateFilters({ startDate, endDate }); - const actionsFilters = [ - { term: { input_type: 'endpoint' } }, - { term: { type: 'INPUT_ACTION' } }, - ...dateFilters, - ...additionalFilters, - ]; + const actionsFilters = [...dateFilters, ...additionalFilters]; const must: SearchRequest = [ { @@ -144,53 +133,3 @@ export const getActions = async ({ return { actionIds, actionRequests }; }; - -export const getActionResponses = async ({ - actionIds, - elasticAgentIds, - esClient, -}: { - actionIds: string[]; - elasticAgentIds?: string[]; - esClient: ElasticsearchClient; -}): Promise< - TransportResult< - estypes.SearchResponse, - unknown - > -> => { - const filter = []; - if (elasticAgentIds?.length) { - filter.push({ terms: { agent_id: elasticAgentIds } }); - } - if (actionIds.length) { - filter.push({ terms: { action_id: actionIds } }); - } - - const responsesSearchQuery: SearchRequest = { - index: ACTION_RESPONSE_INDICES, - size: ACTIONS_SEARCH_PAGE_SIZE, - from: 0, - body: { - query: { - bool: { - filter: filter.length ? filter : [], - }, - }, - }, - }; - - const actionResponses: TransportResult< - estypes.SearchResponse, - unknown - > = await esClient - .search(responsesSearchQuery, { - ...queryOptions, - headers: { - 'X-elastic-product-origin': 'fleet', - }, - meta: true, - }) - .catch(catchAndWrapError); - return actionResponses; -}; diff --git a/x-pack/plugins/security_solution/server/endpoint/utils/dump.ts b/x-pack/plugins/security_solution/server/endpoint/utils/stringify.ts similarity index 88% rename from x-pack/plugins/security_solution/server/endpoint/utils/dump.ts rename to x-pack/plugins/security_solution/server/endpoint/utils/stringify.ts index ae05b73fac05..bd61861b6b9f 100644 --- a/x-pack/plugins/security_solution/server/endpoint/utils/dump.ts +++ b/x-pack/plugins/security_solution/server/endpoint/utils/stringify.ts @@ -13,6 +13,6 @@ import { inspect } from 'util'; * @param depth */ // eslint-disable-next-line @typescript-eslint/no-explicit-any -export const dump = (content: any, depth = 8): string => { +export const stringify = (content: any, depth = 8): string => { return inspect(content, { depth }); }; 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 4630ad9edec0..4d92f5f2c9dd 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 @@ -11,6 +11,7 @@ import { isEqual } from 'lodash/fp'; import type { ExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types'; import { OperatingSystem } from '@kbn/securitysolution-utils'; +import type { FeatureKeys } from '../../../endpoint/services'; import type { EndpointAuthz } from '../../../../common/endpoint/types/authz'; import type { EndpointAppContextService } from '../../../endpoint/endpoint_app_context_services'; import type { ExceptionItemLikeOptions } from '../types'; @@ -21,7 +22,6 @@ import { } from '../../../../common/endpoint/service/artifacts'; import { EndpointArtifactExceptionValidationError } from './errors'; import { EndpointExceptionsValidationError } from './endpoint_exception_errors'; -import type { FeatureKeys } from '../../../endpoint/services/feature_usage/service'; export const BasicEndpointExceptionDataSchema = schema.object( { From 0a90b66ed37936086ce272424124fa51ee98aa14 Mon Sep 17 00:00:00 2001 From: Jonathan Budzenski Date: Thu, 4 Jan 2024 09:35:15 -0600 Subject: [PATCH 08/57] skip suite failing es promotion (#172984) --- x-pack/test/functional/apps/aiops/change_point_detection.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/functional/apps/aiops/change_point_detection.ts b/x-pack/test/functional/apps/aiops/change_point_detection.ts index 787d1b31df11..158d9a9c10cd 100644 --- a/x-pack/test/functional/apps/aiops/change_point_detection.ts +++ b/x-pack/test/functional/apps/aiops/change_point_detection.ts @@ -16,7 +16,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { // aiops lives in the ML UI so we need some related services. const ml = getService('ml'); - describe('change point detection', async function () { + // Failing ES Promotion: https://github.com/elastic/kibana/issues/172984 + describe.skip('change point detection', async function () { before(async () => { await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/ml/ecommerce'); await ml.testResources.createDataViewIfNeeded('ft_ecommerce', 'order_date'); From 1182ce678c3b190aa5172f2b473db0d84ba12f5d Mon Sep 17 00:00:00 2001 From: jennypavlova Date: Thu, 4 Jan 2024 17:09:09 +0100 Subject: [PATCH 09/57] [ObsUX][Profiling, Infra] Add NEW badge to the Profiling tab (#174242) Closes #173156 ## Summary This PR adds a `NEW` badge to the profiling tab and changes the profiling prompt badge color to pink ## Testing The badges can be checked on the node details page and inside the host details flyout: ![image](https://github.com/elastic/kibana/assets/14139027/30f4ca24-b460-4fe9-8c2c-372e435a1c64) ![image](https://github.com/elastic/kibana/assets/14139027/423232b2-fc2e-4718-a089-180157db22da) --- .../asset_details_tabs.tsx | 3 +++ .../overview/kpis/cpu_profiling_prompt.tsx | 8 ++------ .../public/components/asset_details/types.ts | 1 + .../infra/public/components/new_badge.tsx | 18 ++++++++++++++++++ 4 files changed, 24 insertions(+), 6 deletions(-) create mode 100644 x-pack/plugins/infra/public/components/new_badge.tsx diff --git a/x-pack/plugins/infra/public/common/asset_details_config/asset_details_tabs.tsx b/x-pack/plugins/infra/public/common/asset_details_config/asset_details_tabs.tsx index 312ed7eb04a9..2bc3d5661e22 100644 --- a/x-pack/plugins/infra/public/common/asset_details_config/asset_details_tabs.tsx +++ b/x-pack/plugins/infra/public/common/asset_details_config/asset_details_tabs.tsx @@ -6,7 +6,9 @@ */ import { i18n } from '@kbn/i18n'; +import React from 'react'; import { ContentTabIds, type Tab } from '../../components/asset_details/types'; +import { NewBadge } from '../../components/new_badge'; export const commonFlyoutTabs: Tab[] = [ { @@ -32,6 +34,7 @@ export const commonFlyoutTabs: Tab[] = [ name: i18n.translate('xpack.infra.metrics.nodeDetails.tabs.profiling', { defaultMessage: 'Universal Profiling', }), + append: , }, { id: ContentTabIds.LOGS, diff --git a/x-pack/plugins/infra/public/components/asset_details/tabs/overview/kpis/cpu_profiling_prompt.tsx b/x-pack/plugins/infra/public/components/asset_details/tabs/overview/kpis/cpu_profiling_prompt.tsx index 54651b46bcce..256ef447f870 100644 --- a/x-pack/plugins/infra/public/components/asset_details/tabs/overview/kpis/cpu_profiling_prompt.tsx +++ b/x-pack/plugins/infra/public/components/asset_details/tabs/overview/kpis/cpu_profiling_prompt.tsx @@ -8,8 +8,8 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; import { EuiButtonEmpty } from '@elastic/eui'; -import { EuiBadge } from '@elastic/eui'; import { EuiFlexGroup } from '@elastic/eui'; +import { NewBadge } from '../../../../new_badge'; import { useProfilingIntegrationSetting } from '../../../../../hooks/use_profiling_integration_setting'; import { useTabSwitcherContext } from '../../../hooks/use_tab_switcher'; @@ -28,11 +28,7 @@ export function CpuProfilingPrompt() { gutterSize="s" data-test-subj="infraAssetDetailsCPUProfilingPrompt" > - - {i18n.translate('xpack.infra.cpuProfilingPrompt.newBadgeLabel', { - defaultMessage: 'NEW', - })} - + {i18n.translate('xpack.infra.cpuProfilingPrompt.promptText', { defaultMessage: 'View CPU Breakdown using', diff --git a/x-pack/plugins/infra/public/components/asset_details/types.ts b/x-pack/plugins/infra/public/components/asset_details/types.ts index dd3ae9af9d62..346eda2bb3c3 100644 --- a/x-pack/plugins/infra/public/components/asset_details/types.ts +++ b/x-pack/plugins/infra/public/components/asset_details/types.ts @@ -60,6 +60,7 @@ export type RenderMode = FlyoutProps | FullPageProps; export interface Tab { id: ContentTabIds; name: string; + append?: JSX.Element; } export type LinkOptions = 'alertRule' | 'nodeDetails' | 'apmServices'; diff --git a/x-pack/plugins/infra/public/components/new_badge.tsx b/x-pack/plugins/infra/public/components/new_badge.tsx new file mode 100644 index 000000000000..efbe026d8b7a --- /dev/null +++ b/x-pack/plugins/infra/public/components/new_badge.tsx @@ -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 { EuiBadge } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import React from 'react'; + +export const NewBadge = () => ( + + {i18n.translate('xpack.infra.newBadgeLabel', { + defaultMessage: 'NEW', + })} + +); From 9cb830fe9a021cda1d091effbe3e0cd300220969 Mon Sep 17 00:00:00 2001 From: Lukas Olson Date: Thu, 4 Jan 2024 09:16:03 -0700 Subject: [PATCH 10/57] Fix saved query update test (#173576) ## Summary Fixes https://github.com/elastic/kibana/issues/173094. Relying on the text from the toast notification was problematic because sometimes the toast would already have disappeared by the time the check was happening. Instead, this updates the test to refresh and check the saved query list for the updated saved query. Flaky test runner: https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/4750 ### Checklist Delete any items that are not applicable to this PR. - [ ] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md) - [ ] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials - [ ] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [ ] [Flaky Test Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was used on any tests changed - [ ] Any UI touched in this PR is usable by keyboard only (learn more about [keyboard accessibility](https://webaim.org/techniques/keyboard/)) - [ ] Any UI touched in this PR does not create any new axe failures (run axe in browser: [FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/), [Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US)) - [ ] If a plugin configuration key changed, check if it needs to be allowlisted in the cloud and added to the [docker list](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker) - [ ] This renders correctly on smaller devices using a responsive layout. (You can test this [in your browser](https://www.browserstack.com/guide/responsive-testing-on-local-server)) - [ ] This was checked for [cross-browser compatibility](https://www.elastic.co/support/matrix#matrix_browsers) ### Risk Matrix Delete this section if it is not applicable to this PR. Before closing this PR, invite QA, stakeholders, and other developers to identify risks that should be tested prior to the change/feature release. When forming the risk matrix, consider some of the following examples and how they may potentially impact the change: | Risk | Probability | Severity | Mitigation/Notes | |---------------------------|-------------|----------|-------------------------| | Multiple Spaces—unexpected behavior in non-default Kibana Space. | Low | High | Integration tests will verify that all features are still supported in non-default Kibana Space and when user switches between spaces. | | Multiple nodes—Elasticsearch polling might have race conditions when multiple Kibana nodes are polling for the same tasks. | High | Low | Tasks are idempotent, so executing them multiple times will not result in logical error, but will degrade performance. To test for this case we add plenty of unit tests around this logic and document manual testing procedure. | | Code should gracefully handle cases when feature X or plugin Y are disabled. | Medium | High | Unit tests will verify that any feature flag or plugin combination still results in our service operational. | | [See more potential risk examples](https://github.com/elastic/kibana/blob/main/RISK_MATRIX.mdx) | ### For maintainers - [ ] This was checked for breaking API changes and was [labeled appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) --- .../functional/apps/discover/saved_queries.ts | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/x-pack/test/functional/apps/discover/saved_queries.ts b/x-pack/test/functional/apps/discover/saved_queries.ts index 466524f4dbf8..3daf70e3f560 100644 --- a/x-pack/test/functional/apps/discover/saved_queries.ts +++ b/x-pack/test/functional/apps/discover/saved_queries.ts @@ -5,7 +5,6 @@ * 2.0. */ -import expect from '@kbn/expect'; import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { @@ -13,7 +12,6 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const esArchiver = getService('esArchiver'); const kibanaServer = getService('kibanaServer'); const spaces = getService('spaces'); - const toasts = getService('toasts'); const PageObjects = getPageObjects([ 'common', 'discover', @@ -26,8 +24,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const savedQueryName = 'shared-saved-query'; const destinationSpaceId = 'nondefaultspace'; - // Failing: See https://github.com/elastic/kibana/issues/173094 - describe.skip('Discover Saved Queries', () => { + describe('Discover Saved Queries', () => { before('initialize tests', async () => { await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/logstash_functional'); await kibanaServer.importExport.load( @@ -53,6 +50,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { // Navigate to Discover & create a saved query await PageObjects.common.navigateToApp('discover'); await queryBar.setQuery('response:200'); + await queryBar.submitQuery(); await savedQueryManagementComponent.saveNewQuery(savedQueryName, '', true, false); await savedQueryManagementComponent.savedQueryExistOrFail(savedQueryName); await savedQueryManagementComponent.closeSavedQueryManagementComponent(); @@ -76,24 +74,26 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); it('updates a saved query', async () => { + const name = `${savedQueryName}-update`; + // Navigate to Discover & create a saved query await PageObjects.common.navigateToApp('discover'); await queryBar.setQuery('response:200'); - await savedQueryManagementComponent.saveNewQuery(savedQueryName, '', true, false); - await savedQueryManagementComponent.savedQueryExistOrFail(savedQueryName); + await queryBar.submitQuery(); + await savedQueryManagementComponent.saveNewQuery(name, '', true, false); + await savedQueryManagementComponent.savedQueryExistOrFail(name); await savedQueryManagementComponent.closeSavedQueryManagementComponent(); - // Navigate to Discover & create a saved query + // Update the saved query await queryBar.setQuery('response:404'); + await queryBar.submitQuery(); await savedQueryManagementComponent.updateCurrentlyLoadedQuery('', true, false); - // Expect to see a success toast - const successToast = await toasts.getToastElement(1); - const successText = await successToast.getVisibleText(); - expect(successText).to.equal(`Your query "${savedQueryName}" was saved`); - + // Navigate to Discover ensure updated query exists await PageObjects.common.navigateToApp('discover'); - await savedQueryManagementComponent.deleteSavedQuery(savedQueryName); + await savedQueryManagementComponent.savedQueryExistOrFail(name); + await savedQueryManagementComponent.closeSavedQueryManagementComponent(); + await savedQueryManagementComponent.deleteSavedQuery(name); }); }); }); From 615e3f554d13d9122142bc521b54285d48b9149a Mon Sep 17 00:00:00 2001 From: Jon Date: Thu, 4 Jan 2024 11:19:38 -0600 Subject: [PATCH 11/57] [build] Upload CDN assets (#173159) This uploads CDN assets to a GCS bucket on commit and after all tests have passed. This will run on pull requests with `ci:project-deploy-*` and `ci:build-serverless-image` labels, and on `main`. Assets will include the first 12 digits of the commit sha as a base path. --- .buildkite/scripts/lifecycle/pre_command.sh | 6 ++++++ .../scripts/steps/artifacts/docker_image.sh | 16 ++++++++++++---- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/.buildkite/scripts/lifecycle/pre_command.sh b/.buildkite/scripts/lifecycle/pre_command.sh index 9b19e5e82da8..c14325efaa2a 100755 --- a/.buildkite/scripts/lifecycle/pre_command.sh +++ b/.buildkite/scripts/lifecycle/pre_command.sh @@ -142,6 +142,12 @@ export SYNTHETICS_REMOTE_KIBANA_URL DEPLOY_TAGGER_SLACK_WEBHOOK_URL=${DEPLOY_TAGGER_SLACK_WEBHOOK_URL:-"$(vault_get kibana-serverless-release-tools DEPLOY_TAGGER_SLACK_WEBHOOK_URL)"} export DEPLOY_TAGGER_SLACK_WEBHOOK_URL +GCS_SA_CDN_QA_KEY="$(vault_get gcs-sa-cdn-qa key)" +export GCS_SA_CDN_QA_KEY + +GCS_SA_CDN_QA_BUCKET="$(vault_get gcs-sa-cdn-qa bucket)" +export GCS_SA_CDN_QA_BUCKET + # Setup Failed Test Reporter Elasticsearch credentials { TEST_FAILURES_ES_CLOUD_ID=$(vault_get failed_tests_reporter_es cloud_id) diff --git a/.buildkite/scripts/steps/artifacts/docker_image.sh b/.buildkite/scripts/steps/artifacts/docker_image.sh index 0518e17f6524..864bc26805fb 100755 --- a/.buildkite/scripts/steps/artifacts/docker_image.sh +++ b/.buildkite/scripts/steps/artifacts/docker_image.sh @@ -26,7 +26,7 @@ if docker manifest inspect $KIBANA_IMAGE &> /dev/null; then exit 1 fi -echo "--- Build images" +echo "--- Build Kibana" node scripts/build \ --debug \ --release \ @@ -37,8 +37,7 @@ node scripts/build \ --skip-docker-ubuntu \ --skip-docker-ubi \ --skip-docker-cloud \ - --skip-docker-contexts \ - --skip-cdn-assets + --skip-docker-contexts echo "--- Tag images" docker rmi "$KIBANA_IMAGE" @@ -88,12 +87,21 @@ fi echo "--- Build dependencies report" node scripts/licenses_csv_report "--csv=target/dependencies-$GIT_ABBREV_COMMIT.csv" -echo "--- Upload artifacts" +echo "--- Upload CDN assets" cd target +gcloud auth activate-service-account --key-file <(echo "$GCS_SA_CDN_QA_KEY") + +CDN_ASSETS_FOLDER=$(mktemp -d) +tar -xf "kibana-$BASE_VERSION-cdn-assets.tar.gz" -C "$CDN_ASSETS_FOLDER" --strip=1 + +gsutil -m cp -r "$CDN_ASSETS_FOLDER/*" "gs://$GCS_SA_CDN_QA_BUCKET/$GIT_ABBREV_COMMIT" + +echo "--- Upload archives" buildkite-agent artifact upload "kibana-$BASE_VERSION-linux-x86_64.tar.gz" buildkite-agent artifact upload "kibana-$BASE_VERSION-linux-aarch64.tar.gz" buildkite-agent artifact upload "kibana-$BASE_VERSION-docker-image.tar.gz" buildkite-agent artifact upload "kibana-$BASE_VERSION-docker-image-aarch64.tar.gz" +buildkite-agent artifact upload "kibana-$BASE_VERSION-cdn-assets.tar.gz" buildkite-agent artifact upload "dependencies-$GIT_ABBREV_COMMIT.csv" cd - From 7034f823d8446933b30f3d8236ce2ed75e441d8d Mon Sep 17 00:00:00 2001 From: Stratoula Kalafateli Date: Thu, 4 Jan 2024 19:22:45 +0200 Subject: [PATCH 12/57] [Lens] Fixes palette container to be full width (#174275) ## Summary Closes https://github.com/elastic/kibana/issues/174270 Fullwidth color mapping row image --- .../lens/public/visualizations/partition/dimension_editor.tsx | 1 + .../public/visualizations/tagcloud/tags_dimension_editor.tsx | 1 + .../visualizations/xy/xy_config_panel/dimension_editor.tsx | 1 + 3 files changed, 3 insertions(+) diff --git a/x-pack/plugins/lens/public/visualizations/partition/dimension_editor.tsx b/x-pack/plugins/lens/public/visualizations/partition/dimension_editor.tsx index e88d354acf68..7cf4c6bfff66 100644 --- a/x-pack/plugins/lens/public/visualizations/partition/dimension_editor.tsx +++ b/x-pack/plugins/lens/public/visualizations/partition/dimension_editor.tsx @@ -140,6 +140,7 @@ export function DimensionEditor(props: DimensionEditorProps) { defaultMessage: 'Color mapping', })} style={{ alignItems: 'center' }} + fullWidth > Date: Thu, 4 Jan 2024 18:24:09 +0100 Subject: [PATCH 13/57] [Defend Workflows][FTR] Reenable trusted apps list FTR (#174186) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Closes #171481 This PR enables Trusted Apps List FTR - they were flaky in Serverless environment in November, but now passed 250 times perfectly. - 50x https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/4741 50/50 ✅ - 200x https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/4746 200/200 ✅ --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../apps/integrations/trusted_apps_list.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/x-pack/test/security_solution_endpoint/apps/integrations/trusted_apps_list.ts b/x-pack/test/security_solution_endpoint/apps/integrations/trusted_apps_list.ts index 1d48a415b157..e00dde08d58f 100644 --- a/x-pack/test/security_solution_endpoint/apps/integrations/trusted_apps_list.ts +++ b/x-pack/test/security_solution_endpoint/apps/integrations/trusted_apps_list.ts @@ -16,8 +16,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const browser = getService('browser'); const endpointTestResources = getService('endpointTestResources'); - // FLAKY: https://github.com/elastic/kibana/issues/171481 - describe.skip('When on the Trusted Apps list', function () { + describe('When on the Trusted Apps list', function () { targetTags(this, ['@ess', '@serverless']); let indexedData: IndexedHostsAndAlertsResponse; @@ -34,8 +33,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await testSubjects.missingOrFail('header-page-title'); }); - // FLAKY: https://github.com/elastic/kibana/issues/171481 - it.skip('should be able to add a new trusted app and remove it', async () => { + it('should be able to add a new trusted app and remove it', async () => { const SHA256 = 'A4370C0CF81686C0B696FA6261c9d3e0d810ae704ab8301839dffd5d5112f476'; // Add it From 0515829a9e50740357c0226fd1cb5081a273ccd3 Mon Sep 17 00:00:00 2001 From: Tre Date: Thu, 4 Jan 2024 17:58:17 +0000 Subject: [PATCH 14/57] [FTR] Move find service to shared location (#173874) ## Summary Refactoring general ui service to a kbn package. Resolves an [Appex QA](https://github.com/elastic/appex-qa-team) issue. --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .eslintrc.js | 2 +- .../index.ts | 12 ++++++++++++ .../services/all.ts | 4 ++++ .../services}/find.ts | 10 ++++++---- .../services/ftr_provider_context.ts | 7 ++++++- .../config.js | 0 .../several_nested_window_size_changes/test.js | 0 .../several_nested_window_size_changes/test2.js | 0 .../test3.1.js | 0 .../several_nested_window_size_changes/test3.js | 0 .../__tests__/remote_default_window_size.js | 7 +++++-- .../services/remote/browsers.ts | 0 .../services/remote/create_stdout_stream.ts | 0 .../services/remote/index.ts | 2 ++ .../services/remote/network_profiles.ts | 0 .../services/remote/poll_for_log_entry.ts | 0 .../remote/prevent_parallel_calls.test.js | 0 .../services/remote/prevent_parallel_calls.ts | 0 .../services/remote/remote.ts | 2 +- .../services/remote/webdriver.ts | 0 .../web_element_wrapper/custom_cheerio_api.ts | 0 .../services}/web_element_wrapper/index.ts | 0 .../scroll_into_view_if_necessary.js | 2 +- .../web_element_wrapper/web_element_wrapper.ts | 2 +- .../tsconfig.json | 17 +++++++---------- .../types.ts | 0 test/examples/search/warnings.ts | 2 +- .../discover/group1/_discover_accessibility.ts | 2 +- .../apps/kibana_overview/_analytics.ts | 2 +- .../management/data_views/_field_formatter.ts | 2 +- test/functional/page_objects/console_page.ts | 2 +- .../page_objects/dashboard_page_controls.ts | 2 +- test/functional/page_objects/discover_page.ts | 2 +- .../page_objects/legacy/data_table_vis.ts | 2 +- test/functional/page_objects/tag_cloud_page.ts | 2 +- test/functional/page_objects/time_picker.ts | 2 +- test/functional/page_objects/timelion_page.ts | 2 +- .../page_objects/visual_builder_page.ts | 2 +- test/functional/services/combo_box.ts | 2 +- test/functional/services/common/browser.ts | 8 ++++---- test/functional/services/common/index.ts | 1 - test/functional/services/common/screenshots.ts | 2 +- .../functional/services/common/test_subjects.ts | 3 +-- .../services/dashboard/expectations.ts | 2 +- .../services/dashboard/panel_actions.ts | 2 +- .../dashboard/panel_drilldown_actions.ts | 2 +- .../services/dashboard/panel_settings.ts | 2 +- test/functional/services/data_grid.ts | 2 +- test/functional/services/doc_table.ts | 2 +- test/functional/services/index.ts | 4 ---- .../functional/services/saved_objects_finder.ts | 2 +- .../services/visualizations/elastic_chart.ts | 2 +- .../apps/group1/dashboard_panel_options.ts | 2 +- .../functional/apps/discover/visualize_field.ts | 2 +- x-pack/test/functional/apps/infra/hosts_view.ts | 2 +- .../dataset_selector.ts | 2 +- .../test/functional/page_objects/graph_page.ts | 2 +- .../functional/page_objects/infra_hosts_view.ts | 2 +- .../page_objects/infra_metrics_explorer.ts | 2 +- .../page_objects/ingest_pipelines_page.ts | 2 +- .../test/functional/page_objects/lens_page.ts | 2 +- .../page_objects/navigational_search.ts | 2 +- .../page_objects/observability_log_explorer.ts | 2 +- .../page_objects/tag_management_page.ts | 2 +- x-pack/test/functional/services/cases/list.ts | 2 +- .../services/infra_source_configuration_form.ts | 2 +- .../services/logs_ui/log_entry_categories.ts | 2 +- .../services/logs_ui/log_entry_rate.ts | 2 +- .../functional/services/logs_ui/log_stream.ts | 2 +- .../services/ml/common_table_service.ts | 2 +- x-pack/test/functional/services/ml/common_ui.ts | 2 +- .../services/ml/data_frame_analytics_results.ts | 2 +- .../services/ml/data_frame_analytics_table.ts | 2 +- .../services/ml/stack_management_jobs.ts | 2 +- x-pack/test/functional/services/ml/swim_lane.ts | 2 +- .../services/ml/trained_models_table.ts | 2 +- .../services/observability/alerts/common.ts | 2 +- .../test/functional/services/search_sessions.ts | 2 +- .../services/transform/transform_table.ts | 2 +- .../page_objects/app_search.ts | 2 +- .../page_objects/triggers_actions_ui_page.ts | 5 +---- .../test_suites/resolver/index.ts | 2 +- .../apps/integrations/endpoint_exceptions.ts | 2 +- .../page_objects/endpoint_page.ts | 2 +- ...ingest_manager_create_package_policy_page.ts | 2 +- .../page_objects/page_utils.ts | 2 +- .../page_objects/detections/index.ts | 2 +- .../page_objects/hosts/index.ts | 2 +- x-pack/test/tsconfig.json | 1 + .../upgrade/services/rules_upgrade_services.ts | 5 +---- .../page_objects/svl_common_navigation.ts | 2 +- .../svl_triggers_actions_ui_page.ts | 5 +---- .../common/discover/x_pack/visualize_field.ts | 2 +- .../common/examples/search/warnings.ts | 2 +- .../index_management/component_templates.ts | 2 +- .../index_management/index_templates.ts | 2 +- .../observability/infra/hosts_page.ts | 2 +- x-pack/test_serverless/tsconfig.json | 1 + 98 files changed, 119 insertions(+), 107 deletions(-) rename {test/functional/services/common => packages/kbn-ftr-common-functional-ui-services/services}/find.ts (98%) rename {test/functional => packages/kbn-ftr-common-functional-ui-services}/services/remote/__tests__/fixtures/several_nested_window_size_changes/config.js (100%) rename {test/functional => packages/kbn-ftr-common-functional-ui-services}/services/remote/__tests__/fixtures/several_nested_window_size_changes/test.js (100%) rename {test/functional => packages/kbn-ftr-common-functional-ui-services}/services/remote/__tests__/fixtures/several_nested_window_size_changes/test2.js (100%) rename {test/functional => packages/kbn-ftr-common-functional-ui-services}/services/remote/__tests__/fixtures/several_nested_window_size_changes/test3.1.js (100%) rename {test/functional => packages/kbn-ftr-common-functional-ui-services}/services/remote/__tests__/fixtures/several_nested_window_size_changes/test3.js (100%) rename {test/functional => packages/kbn-ftr-common-functional-ui-services}/services/remote/__tests__/remote_default_window_size.js (89%) rename {test/functional => packages/kbn-ftr-common-functional-ui-services}/services/remote/browsers.ts (100%) rename {test/functional => packages/kbn-ftr-common-functional-ui-services}/services/remote/create_stdout_stream.ts (100%) rename {test/functional => packages/kbn-ftr-common-functional-ui-services}/services/remote/index.ts (74%) rename {test/functional => packages/kbn-ftr-common-functional-ui-services}/services/remote/network_profiles.ts (100%) rename {test/functional => packages/kbn-ftr-common-functional-ui-services}/services/remote/poll_for_log_entry.ts (100%) rename {test/functional => packages/kbn-ftr-common-functional-ui-services}/services/remote/prevent_parallel_calls.test.js (100%) rename {test/functional => packages/kbn-ftr-common-functional-ui-services}/services/remote/prevent_parallel_calls.ts (100%) rename {test/functional => packages/kbn-ftr-common-functional-ui-services}/services/remote/remote.ts (98%) rename {test/functional => packages/kbn-ftr-common-functional-ui-services}/services/remote/webdriver.ts (100%) rename {test/functional/services/lib => packages/kbn-ftr-common-functional-ui-services/services}/web_element_wrapper/custom_cheerio_api.ts (100%) rename {test/functional/services/lib => packages/kbn-ftr-common-functional-ui-services/services}/web_element_wrapper/index.ts (100%) rename {test/functional/services/lib => packages/kbn-ftr-common-functional-ui-services/services}/web_element_wrapper/scroll_into_view_if_necessary.js (97%) rename {test/functional/services/lib => packages/kbn-ftr-common-functional-ui-services/services}/web_element_wrapper/web_element_wrapper.ts (99%) rename {test/functional/services/common => packages/kbn-ftr-common-functional-ui-services}/types.ts (100%) diff --git a/.eslintrc.js b/.eslintrc.js index 56fe621c99bb..96016911e40a 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -671,7 +671,7 @@ module.exports = { */ { files: [ - 'test/functional/services/lib/web_element_wrapper/scroll_into_view_if_necessary.js', + 'packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/scroll_into_view_if_necessary.js', '**/browser_exec_scripts/**/*.js', ], rules: { diff --git a/packages/kbn-ftr-common-functional-ui-services/index.ts b/packages/kbn-ftr-common-functional-ui-services/index.ts index 5fe8ae6fd016..e975c838a54a 100644 --- a/packages/kbn-ftr-common-functional-ui-services/index.ts +++ b/packages/kbn-ftr-common-functional-ui-services/index.ts @@ -8,3 +8,15 @@ export { services as commonFunctionalUIServices } from './services/all'; export type { FtrProviderContext } from './services/ftr_provider_context'; +export { WebElementWrapper } from './services/web_element_wrapper'; +export type { + CustomCheerio, + CustomCheerioStatic, +} from './services/web_element_wrapper/custom_cheerio_api'; +export { Browsers } from './services/remote/browsers'; +export { + NETWORK_PROFILES, + type NetworkOptions, + type NetworkProfile, +} from './services/remote/network_profiles'; +export type { TimeoutOpt } from './types'; diff --git a/packages/kbn-ftr-common-functional-ui-services/services/all.ts b/packages/kbn-ftr-common-functional-ui-services/services/all.ts index 8c8a72366011..a27655fc867e 100644 --- a/packages/kbn-ftr-common-functional-ui-services/services/all.ts +++ b/packages/kbn-ftr-common-functional-ui-services/services/all.ts @@ -7,7 +7,11 @@ */ import { RetryOnStaleProvider } from './retry_on_stale'; +import { RemoteProvider } from './remote'; +import { FindProvider } from './find'; export const services = { retryOnStale: RetryOnStaleProvider, + __webdriver__: RemoteProvider, + find: FindProvider, }; diff --git a/test/functional/services/common/find.ts b/packages/kbn-ftr-common-functional-ui-services/services/find.ts similarity index 98% rename from test/functional/services/common/find.ts rename to packages/kbn-ftr-common-functional-ui-services/services/find.ts index 682c79047a72..2f8ba340c40b 100644 --- a/test/functional/services/common/find.ts +++ b/packages/kbn-ftr-common-functional-ui-services/services/find.ts @@ -8,10 +8,12 @@ import { WebDriver, WebElement, By, until } from 'selenium-webdriver'; -import { Browsers } from '../remote/browsers'; -import { FtrService, FtrProviderContext } from '../../ftr_provider_context'; -import { WebElementWrapper } from '../lib/web_element_wrapper'; -import { TimeoutOpt } from './types'; +import { Browsers } from './remote/browsers'; +import type { FtrProviderContext } from './ftr_provider_context'; +import { WebElementWrapper } from './web_element_wrapper'; +import { TimeoutOpt } from '../types'; + +import { FtrService } from './ftr_provider_context'; export class FindService extends FtrService { private readonly log = this.ctx.getService('log'); diff --git a/packages/kbn-ftr-common-functional-ui-services/services/ftr_provider_context.ts b/packages/kbn-ftr-common-functional-ui-services/services/ftr_provider_context.ts index 979658fbd8ed..bf80085dd459 100644 --- a/packages/kbn-ftr-common-functional-ui-services/services/ftr_provider_context.ts +++ b/packages/kbn-ftr-common-functional-ui-services/services/ftr_provider_context.ts @@ -7,8 +7,13 @@ */ import { GenericFtrProviderContext, GenericFtrService } from '@kbn/test'; +import { RetryService } from '@kbn/ftr-common-functional-services'; +import { services as commonFunctionalUiServices } from './all'; -import type { services } from './all'; +const services = { + ...commonFunctionalUiServices, + retry: RetryService, +}; type Services = typeof services; diff --git a/test/functional/services/remote/__tests__/fixtures/several_nested_window_size_changes/config.js b/packages/kbn-ftr-common-functional-ui-services/services/remote/__tests__/fixtures/several_nested_window_size_changes/config.js similarity index 100% rename from test/functional/services/remote/__tests__/fixtures/several_nested_window_size_changes/config.js rename to packages/kbn-ftr-common-functional-ui-services/services/remote/__tests__/fixtures/several_nested_window_size_changes/config.js diff --git a/test/functional/services/remote/__tests__/fixtures/several_nested_window_size_changes/test.js b/packages/kbn-ftr-common-functional-ui-services/services/remote/__tests__/fixtures/several_nested_window_size_changes/test.js similarity index 100% rename from test/functional/services/remote/__tests__/fixtures/several_nested_window_size_changes/test.js rename to packages/kbn-ftr-common-functional-ui-services/services/remote/__tests__/fixtures/several_nested_window_size_changes/test.js diff --git a/test/functional/services/remote/__tests__/fixtures/several_nested_window_size_changes/test2.js b/packages/kbn-ftr-common-functional-ui-services/services/remote/__tests__/fixtures/several_nested_window_size_changes/test2.js similarity index 100% rename from test/functional/services/remote/__tests__/fixtures/several_nested_window_size_changes/test2.js rename to packages/kbn-ftr-common-functional-ui-services/services/remote/__tests__/fixtures/several_nested_window_size_changes/test2.js diff --git a/test/functional/services/remote/__tests__/fixtures/several_nested_window_size_changes/test3.1.js b/packages/kbn-ftr-common-functional-ui-services/services/remote/__tests__/fixtures/several_nested_window_size_changes/test3.1.js similarity index 100% rename from test/functional/services/remote/__tests__/fixtures/several_nested_window_size_changes/test3.1.js rename to packages/kbn-ftr-common-functional-ui-services/services/remote/__tests__/fixtures/several_nested_window_size_changes/test3.1.js diff --git a/test/functional/services/remote/__tests__/fixtures/several_nested_window_size_changes/test3.js b/packages/kbn-ftr-common-functional-ui-services/services/remote/__tests__/fixtures/several_nested_window_size_changes/test3.js similarity index 100% rename from test/functional/services/remote/__tests__/fixtures/several_nested_window_size_changes/test3.js rename to packages/kbn-ftr-common-functional-ui-services/services/remote/__tests__/fixtures/several_nested_window_size_changes/test3.js diff --git a/test/functional/services/remote/__tests__/remote_default_window_size.js b/packages/kbn-ftr-common-functional-ui-services/services/remote/__tests__/remote_default_window_size.js similarity index 89% rename from test/functional/services/remote/__tests__/remote_default_window_size.js rename to packages/kbn-ftr-common-functional-ui-services/services/remote/__tests__/remote_default_window_size.js index 48210ea209da..8d5182c45733 100644 --- a/test/functional/services/remote/__tests__/remote_default_window_size.js +++ b/packages/kbn-ftr-common-functional-ui-services/services/remote/__tests__/remote_default_window_size.js @@ -9,9 +9,12 @@ import { fork } from 'child_process'; import expect from '@kbn/expect'; +import { REPO_ROOT } from '@kbn/repo-info'; -const FTR_SCRIPT = require.resolve('../../../../../scripts/functional_test_runner'); -const CONFIG_PATH = require.resolve('./fixtures/several_nested_window_size_changes/config.js'); +const FTR_SCRIPT = require.resolve(`${REPO_ROOT}/scripts/functional_test_runner`); +const CONFIG_PATH = require.resolve( + `${REPO_ROOT}/packages/kbn-ftr-common-functional-ui-services/services/remote/__tests__/fixtures/several_nested_window_size_changes/config.js` +); const SECOND = 1000; const DEFAULT_SIZE = { width: 1600, height: 1000 }; diff --git a/test/functional/services/remote/browsers.ts b/packages/kbn-ftr-common-functional-ui-services/services/remote/browsers.ts similarity index 100% rename from test/functional/services/remote/browsers.ts rename to packages/kbn-ftr-common-functional-ui-services/services/remote/browsers.ts diff --git a/test/functional/services/remote/create_stdout_stream.ts b/packages/kbn-ftr-common-functional-ui-services/services/remote/create_stdout_stream.ts similarity index 100% rename from test/functional/services/remote/create_stdout_stream.ts rename to packages/kbn-ftr-common-functional-ui-services/services/remote/create_stdout_stream.ts diff --git a/test/functional/services/remote/index.ts b/packages/kbn-ftr-common-functional-ui-services/services/remote/index.ts similarity index 74% rename from test/functional/services/remote/index.ts rename to packages/kbn-ftr-common-functional-ui-services/services/remote/index.ts index 452a714c887f..a85a13948ccc 100644 --- a/test/functional/services/remote/index.ts +++ b/packages/kbn-ftr-common-functional-ui-services/services/remote/index.ts @@ -7,3 +7,5 @@ */ export { RemoteProvider } from './remote'; +export { Browsers } from './browsers'; +export { NETWORK_PROFILES, type NetworkOptions, type NetworkProfile } from './network_profiles'; diff --git a/test/functional/services/remote/network_profiles.ts b/packages/kbn-ftr-common-functional-ui-services/services/remote/network_profiles.ts similarity index 100% rename from test/functional/services/remote/network_profiles.ts rename to packages/kbn-ftr-common-functional-ui-services/services/remote/network_profiles.ts diff --git a/test/functional/services/remote/poll_for_log_entry.ts b/packages/kbn-ftr-common-functional-ui-services/services/remote/poll_for_log_entry.ts similarity index 100% rename from test/functional/services/remote/poll_for_log_entry.ts rename to packages/kbn-ftr-common-functional-ui-services/services/remote/poll_for_log_entry.ts diff --git a/test/functional/services/remote/prevent_parallel_calls.test.js b/packages/kbn-ftr-common-functional-ui-services/services/remote/prevent_parallel_calls.test.js similarity index 100% rename from test/functional/services/remote/prevent_parallel_calls.test.js rename to packages/kbn-ftr-common-functional-ui-services/services/remote/prevent_parallel_calls.test.js diff --git a/test/functional/services/remote/prevent_parallel_calls.ts b/packages/kbn-ftr-common-functional-ui-services/services/remote/prevent_parallel_calls.ts similarity index 100% rename from test/functional/services/remote/prevent_parallel_calls.ts rename to packages/kbn-ftr-common-functional-ui-services/services/remote/prevent_parallel_calls.ts diff --git a/test/functional/services/remote/remote.ts b/packages/kbn-ftr-common-functional-ui-services/services/remote/remote.ts similarity index 98% rename from test/functional/services/remote/remote.ts rename to packages/kbn-ftr-common-functional-ui-services/services/remote/remote.ts index 6ee7b6e8d908..6eb10984eeb6 100644 --- a/test/functional/services/remote/remote.ts +++ b/packages/kbn-ftr-common-functional-ui-services/services/remote/remote.ts @@ -7,7 +7,7 @@ */ import { NoSuchSessionError, NoSuchWindowError } from 'selenium-webdriver/lib/error'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../ftr_provider_context'; import { initWebDriver, BrowserConfig } from './webdriver'; import { Browsers } from './browsers'; diff --git a/test/functional/services/remote/webdriver.ts b/packages/kbn-ftr-common-functional-ui-services/services/remote/webdriver.ts similarity index 100% rename from test/functional/services/remote/webdriver.ts rename to packages/kbn-ftr-common-functional-ui-services/services/remote/webdriver.ts diff --git a/test/functional/services/lib/web_element_wrapper/custom_cheerio_api.ts b/packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts similarity index 100% rename from test/functional/services/lib/web_element_wrapper/custom_cheerio_api.ts rename to packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts diff --git a/test/functional/services/lib/web_element_wrapper/index.ts b/packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/index.ts similarity index 100% rename from test/functional/services/lib/web_element_wrapper/index.ts rename to packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/index.ts diff --git a/test/functional/services/lib/web_element_wrapper/scroll_into_view_if_necessary.js b/packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/scroll_into_view_if_necessary.js similarity index 97% rename from test/functional/services/lib/web_element_wrapper/scroll_into_view_if_necessary.js rename to packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/scroll_into_view_if_necessary.js index 514d1bb1d9d7..bc3453bffa7a 100644 --- a/test/functional/services/lib/web_element_wrapper/scroll_into_view_if_necessary.js +++ b/packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/scroll_into_view_if_necessary.js @@ -1,4 +1,4 @@ -/* eslint-disable @kbn/eslint/require-license-header */ +/* eslint-disable @kbn/eslint/require-license-header, no-var */ /* @notice * Based on the scroll-into-view-if-necessary module from npm diff --git a/test/functional/services/lib/web_element_wrapper/web_element_wrapper.ts b/packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts similarity index 99% rename from test/functional/services/lib/web_element_wrapper/web_element_wrapper.ts rename to packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts index 6a914c7273ba..568d8dc5cd87 100644 --- a/test/functional/services/lib/web_element_wrapper/web_element_wrapper.ts +++ b/packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts @@ -15,7 +15,7 @@ import { ToolingLog } from '@kbn/tooling-log'; import { CustomCheerio, CustomCheerioStatic } from './custom_cheerio_api'; // @ts-ignore not supported yet import { scrollIntoViewIfNecessary } from './scroll_into_view_if_necessary'; -import { Browsers } from '../../remote/browsers'; +import { Browsers } from '../remote/browsers'; interface TypeOptions { charByChar: boolean; diff --git a/packages/kbn-ftr-common-functional-ui-services/tsconfig.json b/packages/kbn-ftr-common-functional-ui-services/tsconfig.json index 0c77cc5d6b91..f8ae6aae1b9b 100644 --- a/packages/kbn-ftr-common-functional-ui-services/tsconfig.json +++ b/packages/kbn-ftr-common-functional-ui-services/tsconfig.json @@ -2,18 +2,15 @@ "extends": "../../tsconfig.base.json", "compilerOptions": { "outDir": "target/types", - "types": [ - "jest", - "node" - ] + "types": ["jest", "cheerio", "node"] }, - "include": [ - "**/*.ts", - ], - "exclude": [ - "target/**/*" - ], + "include": ["**/*.ts"], + "exclude": ["target/**/*"], "kbn_references": [ "@kbn/test", + "@kbn/tooling-log", + "@kbn/repo-info", + "@kbn/test-subj-selector", + "@kbn/ftr-common-functional-services" ] } diff --git a/test/functional/services/common/types.ts b/packages/kbn-ftr-common-functional-ui-services/types.ts similarity index 100% rename from test/functional/services/common/types.ts rename to packages/kbn-ftr-common-functional-ui-services/types.ts diff --git a/test/examples/search/warnings.ts b/test/examples/search/warnings.ts index 3a923b4a2ae6..80d4224d2ef8 100644 --- a/test/examples/search/warnings.ts +++ b/test/examples/search/warnings.ts @@ -9,8 +9,8 @@ import type { estypes } from '@elastic/elasticsearch'; import expect from '@kbn/expect'; import assert from 'assert'; +import type { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import type { FtrProviderContext } from '../../functional/ftr_provider_context'; -import type { WebElementWrapper } from '../../functional/services/lib/web_element_wrapper'; // eslint-disable-next-line import/no-default-export export default function ({ getService, getPageObjects }: FtrProviderContext) { diff --git a/test/functional/apps/discover/group1/_discover_accessibility.ts b/test/functional/apps/discover/group1/_discover_accessibility.ts index f5721f1e03f7..815d5aebe7bb 100644 --- a/test/functional/apps/discover/group1/_discover_accessibility.ts +++ b/test/functional/apps/discover/group1/_discover_accessibility.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; -import { WebElementWrapper } from '../../../services/lib/web_element_wrapper'; +import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import { FtrProviderContext } from '../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { diff --git a/test/functional/apps/kibana_overview/_analytics.ts b/test/functional/apps/kibana_overview/_analytics.ts index 1c4897d5830a..8fd51106cd23 100644 --- a/test/functional/apps/kibana_overview/_analytics.ts +++ b/test/functional/apps/kibana_overview/_analytics.ts @@ -7,8 +7,8 @@ */ import expect from '@kbn/expect'; +import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import { FtrProviderContext } from '../../ftr_provider_context'; -import { WebElementWrapper } from '../../services/lib/web_element_wrapper'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const find = getService('find'); diff --git a/test/functional/apps/management/data_views/_field_formatter.ts b/test/functional/apps/management/data_views/_field_formatter.ts index 881ba6197510..fb016151cce5 100644 --- a/test/functional/apps/management/data_views/_field_formatter.ts +++ b/test/functional/apps/management/data_views/_field_formatter.ts @@ -8,8 +8,8 @@ import { ES_FIELD_TYPES } from '@kbn/field-types'; import expect from '@kbn/expect'; import { FIELD_FORMAT_IDS } from '@kbn/field-formats-plugin/common'; +import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import { FtrProviderContext } from '../../../ftr_provider_context'; -import { WebElementWrapper } from '../../../services/lib/web_element_wrapper'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const kibanaServer = getService('kibanaServer'); diff --git a/test/functional/page_objects/console_page.ts b/test/functional/page_objects/console_page.ts index 2fabe4222ee4..51e671d26301 100644 --- a/test/functional/page_objects/console_page.ts +++ b/test/functional/page_objects/console_page.ts @@ -8,8 +8,8 @@ import { Key } from 'selenium-webdriver'; import { asyncForEach } from '@kbn/std'; +import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import { FtrService } from '../ftr_provider_context'; -import { WebElementWrapper } from '../services/lib/web_element_wrapper'; export class ConsolePageObject extends FtrService { private readonly testSubjects = this.ctx.getService('testSubjects'); diff --git a/test/functional/page_objects/dashboard_page_controls.ts b/test/functional/page_objects/dashboard_page_controls.ts index af6f3f81563d..f3ca32531995 100644 --- a/test/functional/page_objects/dashboard_page_controls.ts +++ b/test/functional/page_objects/dashboard_page_controls.ts @@ -17,8 +17,8 @@ import { OptionsListSortingType } from '@kbn/controls-plugin/common/options_list import expect from '@kbn/expect'; import { asyncForEach } from '@kbn/std'; +import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import { FtrService } from '../ftr_provider_context'; -import { WebElementWrapper } from '../services/lib/web_element_wrapper'; interface OptionsListAdditionalSettings { searchTechnique?: OptionsListSearchTechnique; diff --git a/test/functional/page_objects/discover_page.ts b/test/functional/page_objects/discover_page.ts index 9f636fcd8ec7..3ec60eae8e40 100644 --- a/test/functional/page_objects/discover_page.ts +++ b/test/functional/page_objects/discover_page.ts @@ -7,8 +7,8 @@ */ import expect from '@kbn/expect'; +import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import { FtrService } from '../ftr_provider_context'; -import { WebElementWrapper } from '../services/lib/web_element_wrapper'; export class DiscoverPageObject extends FtrService { private readonly retry = this.ctx.getService('retry'); diff --git a/test/functional/page_objects/legacy/data_table_vis.ts b/test/functional/page_objects/legacy/data_table_vis.ts index 122409f28de9..dbc25df9387d 100644 --- a/test/functional/page_objects/legacy/data_table_vis.ts +++ b/test/functional/page_objects/legacy/data_table_vis.ts @@ -6,8 +6,8 @@ * Side Public License, v 1. */ +import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import { FtrService } from '../../ftr_provider_context'; -import { WebElementWrapper } from '../../services/lib/web_element_wrapper'; export class LegacyDataTableVisPageObject extends FtrService { private readonly testSubjects = this.ctx.getService('testSubjects'); diff --git a/test/functional/page_objects/tag_cloud_page.ts b/test/functional/page_objects/tag_cloud_page.ts index ecd5aad78128..ba7648b323ca 100644 --- a/test/functional/page_objects/tag_cloud_page.ts +++ b/test/functional/page_objects/tag_cloud_page.ts @@ -6,8 +6,8 @@ * Side Public License, v 1. */ +import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import { FtrService } from '../ftr_provider_context'; -import { WebElementWrapper } from '../services/lib/web_element_wrapper'; export class TagCloudPageObject extends FtrService { private readonly find = this.ctx.getService('find'); diff --git a/test/functional/page_objects/time_picker.ts b/test/functional/page_objects/time_picker.ts index aa8832f28848..5ea80ce27126 100644 --- a/test/functional/page_objects/time_picker.ts +++ b/test/functional/page_objects/time_picker.ts @@ -7,8 +7,8 @@ */ import moment from 'moment'; +import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import { FtrService } from '../ftr_provider_context'; -import { WebElementWrapper } from '../services/lib/web_element_wrapper'; export type CommonlyUsed = | 'Today' diff --git a/test/functional/page_objects/timelion_page.ts b/test/functional/page_objects/timelion_page.ts index ba1db60bc635..f7fa16aa416b 100644 --- a/test/functional/page_objects/timelion_page.ts +++ b/test/functional/page_objects/timelion_page.ts @@ -6,8 +6,8 @@ * Side Public License, v 1. */ +import type { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import { FtrService } from '../ftr_provider_context'; -import type { WebElementWrapper } from '../services/lib/web_element_wrapper'; export class TimelionPageObject extends FtrService { private readonly testSubjects = this.ctx.getService('testSubjects'); diff --git a/test/functional/page_objects/visual_builder_page.ts b/test/functional/page_objects/visual_builder_page.ts index e20249f362b0..89f1a2e9389c 100644 --- a/test/functional/page_objects/visual_builder_page.ts +++ b/test/functional/page_objects/visual_builder_page.ts @@ -7,8 +7,8 @@ */ import type { DebugState } from '@elastic/charts'; +import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import { FtrService } from '../ftr_provider_context'; -import { WebElementWrapper } from '../services/lib/web_element_wrapper'; type Duration = | 'Milliseconds' diff --git a/test/functional/services/combo_box.ts b/test/functional/services/combo_box.ts index 4b23dd3bd8b9..69794f3d2a6c 100644 --- a/test/functional/services/combo_box.ts +++ b/test/functional/services/combo_box.ts @@ -7,8 +7,8 @@ */ import expect from '@kbn/expect'; +import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import { FtrService } from '../ftr_provider_context'; -import { WebElementWrapper } from './lib/web_element_wrapper'; /** * wrapper around EuiComboBox interactions diff --git a/test/functional/services/common/browser.ts b/test/functional/services/common/browser.ts index cac8eec71e7f..8054816bb4ee 100644 --- a/test/functional/services/common/browser.ts +++ b/test/functional/services/common/browser.ts @@ -15,14 +15,14 @@ import Url from 'url'; import { NoSuchSessionError } from 'selenium-webdriver/lib/error'; import sharp from 'sharp'; -import { FtrService, type FtrProviderContext } from '../../ftr_provider_context'; -import { WebElementWrapper } from '../lib/web_element_wrapper'; -import { Browsers } from '../remote/browsers'; import { + WebElementWrapper, + Browsers, NETWORK_PROFILES, type NetworkOptions, type NetworkProfile, -} from '../remote/network_profiles'; +} from '@kbn/ftr-common-functional-ui-services'; +import { FtrService, type FtrProviderContext } from '../../ftr_provider_context'; export type Browser = BrowserService; diff --git a/test/functional/services/common/index.ts b/test/functional/services/common/index.ts index b7b8c67a4280..3d1078d92dc5 100644 --- a/test/functional/services/common/index.ts +++ b/test/functional/services/common/index.ts @@ -9,7 +9,6 @@ export type { Browser } from './browser'; export { BrowserProvider } from './browser'; export { FailureDebuggingProvider } from './failure_debugging'; -export { FindProvider } from './find'; export { PngService } from './png'; export { ScreenshotsService } from './screenshots'; export { SnapshotsService } from './snapshots'; diff --git a/test/functional/services/common/screenshots.ts b/test/functional/services/common/screenshots.ts index 50421e480dd9..10b2ccb25161 100644 --- a/test/functional/services/common/screenshots.ts +++ b/test/functional/services/common/screenshots.ts @@ -12,9 +12,9 @@ import { promisify } from 'util'; import del from 'del'; +import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import { comparePngs } from '../lib/compare_pngs'; import { FtrProviderContext, FtrService } from '../../ftr_provider_context'; -import { WebElementWrapper } from '../lib/web_element_wrapper'; const mkdirAsync = promisify(mkdir); const writeFileAsync = promisify(writeFile); diff --git a/test/functional/services/common/test_subjects.ts b/test/functional/services/common/test_subjects.ts index b451d3139463..57d2bbbd6424 100644 --- a/test/functional/services/common/test_subjects.ts +++ b/test/functional/services/common/test_subjects.ts @@ -7,9 +7,8 @@ */ import { subj as testSubjSelector } from '@kbn/test-subj-selector'; -import { WebElementWrapper } from '../lib/web_element_wrapper'; +import { WebElementWrapper, type TimeoutOpt } from '@kbn/ftr-common-functional-ui-services'; import { FtrService } from '../../ftr_provider_context'; -import { TimeoutOpt } from './types'; interface ExistsOptions { timeout?: number; diff --git a/test/functional/services/dashboard/expectations.ts b/test/functional/services/dashboard/expectations.ts index a7993286d80f..476ffb49f13e 100644 --- a/test/functional/services/dashboard/expectations.ts +++ b/test/functional/services/dashboard/expectations.ts @@ -7,8 +7,8 @@ */ import expect from '@kbn/expect'; +import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import { FtrService } from '../../ftr_provider_context'; -import { WebElementWrapper } from '../lib/web_element_wrapper'; export class DashboardExpectService extends FtrService { private readonly log = this.ctx.getService('log'); diff --git a/test/functional/services/dashboard/panel_actions.ts b/test/functional/services/dashboard/panel_actions.ts index f07b0bd87177..14c69eb6b8e2 100644 --- a/test/functional/services/dashboard/panel_actions.ts +++ b/test/functional/services/dashboard/panel_actions.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { WebElementWrapper } from '../lib/web_element_wrapper'; +import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import { FtrService } from '../../ftr_provider_context'; const REMOVE_PANEL_DATA_TEST_SUBJ = 'embeddablePanelAction-deletePanel'; diff --git a/test/functional/services/dashboard/panel_drilldown_actions.ts b/test/functional/services/dashboard/panel_drilldown_actions.ts index 222e55950c8b..3a240d58c983 100644 --- a/test/functional/services/dashboard/panel_drilldown_actions.ts +++ b/test/functional/services/dashboard/panel_drilldown_actions.ts @@ -6,8 +6,8 @@ * Side Public License, v 1. */ +import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import { FtrProviderContext } from '../../ftr_provider_context'; -import { WebElementWrapper } from '../lib/web_element_wrapper'; const CREATE_DRILLDOWN_DATA_TEST_SUBJ = 'embeddablePanelAction-OPEN_FLYOUT_ADD_DRILLDOWN'; const MANAGE_DRILLDOWNS_DATA_TEST_SUBJ = 'embeddablePanelAction-OPEN_FLYOUT_EDIT_DRILLDOWN'; diff --git a/test/functional/services/dashboard/panel_settings.ts b/test/functional/services/dashboard/panel_settings.ts index de75a9c4a7a1..36bd01b1fad0 100644 --- a/test/functional/services/dashboard/panel_settings.ts +++ b/test/functional/services/dashboard/panel_settings.ts @@ -6,9 +6,9 @@ * Side Public License, v 1. */ +import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import { FtrProviderContext } from '../../ftr_provider_context'; import { CommonlyUsed } from '../../page_objects/time_picker'; -import { WebElementWrapper } from '../lib/web_element_wrapper'; export function DashboardCustomizePanelProvider({ getService, getPageObject }: FtrProviderContext) { const log = getService('log'); diff --git a/test/functional/services/data_grid.ts b/test/functional/services/data_grid.ts index df5ba570cfc5..88b95fc8a4ab 100644 --- a/test/functional/services/data_grid.ts +++ b/test/functional/services/data_grid.ts @@ -8,8 +8,8 @@ import { chunk } from 'lodash'; import { Key } from 'selenium-webdriver'; +import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import { FtrService } from '../ftr_provider_context'; -import { WebElementWrapper } from './lib/web_element_wrapper'; export interface TabbedGridData { columns: string[]; diff --git a/test/functional/services/doc_table.ts b/test/functional/services/doc_table.ts index 685f1748d56b..9be10301019c 100644 --- a/test/functional/services/doc_table.ts +++ b/test/functional/services/doc_table.ts @@ -6,8 +6,8 @@ * Side Public License, v 1. */ +import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import { FtrService } from '../ftr_provider_context'; -import { WebElementWrapper } from './lib/web_element_wrapper'; interface SelectOptions { isAnchorRow?: boolean; diff --git a/test/functional/services/index.ts b/test/functional/services/index.ts index dc151f1b243e..de503f8ccf99 100644 --- a/test/functional/services/index.ts +++ b/test/functional/services/index.ts @@ -13,7 +13,6 @@ import { AppsMenuService } from './apps_menu'; import { BrowserProvider, FailureDebuggingProvider, - FindProvider, PngService, ScreenshotsService, SnapshotsService, @@ -40,7 +39,6 @@ import { InspectorService } from './inspector'; import { FieldEditorService } from './field_editor'; import { ManagementMenuService } from './management'; import { QueryBarService } from './query_bar'; -import { RemoteProvider } from './remote'; import { RenderableService } from './renderable'; import { ToastsService } from './toasts'; import { DataGridService } from './data_grid'; @@ -61,10 +59,8 @@ import { DashboardSettingsProvider } from './dashboard/dashboard_settings'; export const services = { ...commonServiceProviders, ...commonFunctionalUIServices, - __webdriver__: RemoteProvider, filterBar: FilterBarService, queryBar: QueryBarService, - find: FindProvider, testSubjects: TestSubjects, docTable: DocTableService, png: PngService, diff --git a/test/functional/services/saved_objects_finder.ts b/test/functional/services/saved_objects_finder.ts index 12e06fe8a171..98af7785852d 100644 --- a/test/functional/services/saved_objects_finder.ts +++ b/test/functional/services/saved_objects_finder.ts @@ -7,8 +7,8 @@ */ import expect from '@kbn/expect'; +import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import { FtrService } from '../ftr_provider_context'; -import { WebElementWrapper } from './lib/web_element_wrapper'; export class SavedObjectsFinderService extends FtrService { private readonly testSubjects = this.ctx.getService('testSubjects'); diff --git a/test/functional/services/visualizations/elastic_chart.ts b/test/functional/services/visualizations/elastic_chart.ts index d87a7a0d3d06..da872eb21670 100644 --- a/test/functional/services/visualizations/elastic_chart.ts +++ b/test/functional/services/visualizations/elastic_chart.ts @@ -9,8 +9,8 @@ import { DebugState } from '@elastic/charts'; import expect from '@kbn/expect'; +import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import { FtrService } from '../../ftr_provider_context'; -import { WebElementWrapper } from '../lib/web_element_wrapper'; declare global { interface Window { diff --git a/x-pack/test/accessibility/apps/group1/dashboard_panel_options.ts b/x-pack/test/accessibility/apps/group1/dashboard_panel_options.ts index 5f12f3600c29..a5182a8d2ca0 100644 --- a/x-pack/test/accessibility/apps/group1/dashboard_panel_options.ts +++ b/x-pack/test/accessibility/apps/group1/dashboard_panel_options.ts @@ -5,8 +5,8 @@ * 2.0. */ +import type { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import { FtrProviderContext } from '../../ftr_provider_context'; -import type { WebElementWrapper } from '../../../../../test/functional/services/lib/web_element_wrapper'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const a11y = getService('a11y'); diff --git a/x-pack/test/functional/apps/discover/visualize_field.ts b/x-pack/test/functional/apps/discover/visualize_field.ts index 428ef13c3486..bbd5e94dc4c7 100644 --- a/x-pack/test/functional/apps/discover/visualize_field.ts +++ b/x-pack/test/functional/apps/discover/visualize_field.ts @@ -7,7 +7,7 @@ import expect from '@kbn/expect'; import { DebugState } from '@elastic/charts'; -import { WebElementWrapper } from '../../../../../test/functional/services/lib/web_element_wrapper'; +import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ getPageObjects, getService }: FtrProviderContext) { diff --git a/x-pack/test/functional/apps/infra/hosts_view.ts b/x-pack/test/functional/apps/infra/hosts_view.ts index f9932421690e..13657713faac 100644 --- a/x-pack/test/functional/apps/infra/hosts_view.ts +++ b/x-pack/test/functional/apps/infra/hosts_view.ts @@ -10,7 +10,7 @@ import expect from '@kbn/expect'; import { parse } from 'url'; import { enableInfrastructureHostsView } from '@kbn/observability-plugin/common'; import { ALERT_STATUS_ACTIVE, ALERT_STATUS_RECOVERED } from '@kbn/rule-data-utils'; -import { WebElementWrapper } from '../../../../../test/functional/services/lib/web_element_wrapper'; +import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import { FtrProviderContext } from '../../ftr_provider_context'; import { DATES, diff --git a/x-pack/test/functional/apps/observability_log_explorer/dataset_selector.ts b/x-pack/test/functional/apps/observability_log_explorer/dataset_selector.ts index d656301a1389..98cfc79c561a 100644 --- a/x-pack/test/functional/apps/observability_log_explorer/dataset_selector.ts +++ b/x-pack/test/functional/apps/observability_log_explorer/dataset_selector.ts @@ -5,8 +5,8 @@ * 2.0. */ import expect from '@kbn/expect'; +import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import { FtrProviderContext } from './config'; -import { WebElementWrapper } from '../../../../../test/functional/services/lib/web_element_wrapper'; const initialPackageMap = { apache: 'Apache HTTP Server', diff --git a/x-pack/test/functional/page_objects/graph_page.ts b/x-pack/test/functional/page_objects/graph_page.ts index 503e8666e0be..810048a7f144 100644 --- a/x-pack/test/functional/page_objects/graph_page.ts +++ b/x-pack/test/functional/page_objects/graph_page.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { WebElementWrapper } from '../../../../test/functional/services/lib/web_element_wrapper'; +import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import { FtrService } from '../ftr_provider_context'; interface Node { diff --git a/x-pack/test/functional/page_objects/infra_hosts_view.ts b/x-pack/test/functional/page_objects/infra_hosts_view.ts index 3fbb3d361d87..0c3004acc4fe 100644 --- a/x-pack/test/functional/page_objects/infra_hosts_view.ts +++ b/x-pack/test/functional/page_objects/infra_hosts_view.ts @@ -6,7 +6,7 @@ */ import { AlertStatus } from '@kbn/rule-data-utils'; -import { WebElementWrapper } from '../../../../test/functional/services/lib/web_element_wrapper'; +import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import { FtrProviderContext } from '../ftr_provider_context'; export function InfraHostsViewProvider({ getService }: FtrProviderContext) { diff --git a/x-pack/test/functional/page_objects/infra_metrics_explorer.ts b/x-pack/test/functional/page_objects/infra_metrics_explorer.ts index e8d9f878b43c..4e691a164cdb 100644 --- a/x-pack/test/functional/page_objects/infra_metrics_explorer.ts +++ b/x-pack/test/functional/page_objects/infra_metrics_explorer.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { WebElementWrapper } from '../../../../test/functional/services/lib/web_element_wrapper'; +import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import { FtrProviderContext } from '../ftr_provider_context'; export function InfraMetricsExplorerProvider({ getService }: FtrProviderContext) { diff --git a/x-pack/test/functional/page_objects/ingest_pipelines_page.ts b/x-pack/test/functional/page_objects/ingest_pipelines_page.ts index 3e0bc23869bb..c4800b55aa77 100644 --- a/x-pack/test/functional/page_objects/ingest_pipelines_page.ts +++ b/x-pack/test/functional/page_objects/ingest_pipelines_page.ts @@ -6,7 +6,7 @@ */ import path from 'path'; -import { WebElementWrapper } from '../../../../test/functional/services/lib/web_element_wrapper'; +import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import { FtrProviderContext } from '../ftr_provider_context'; export function IngestPipelinesPageProvider({ getService, getPageObjects }: FtrProviderContext) { diff --git a/x-pack/test/functional/page_objects/lens_page.ts b/x-pack/test/functional/page_objects/lens_page.ts index ee9ad1596fbe..2d3766c13766 100644 --- a/x-pack/test/functional/page_objects/lens_page.ts +++ b/x-pack/test/functional/page_objects/lens_page.ts @@ -9,7 +9,7 @@ import expect from '@kbn/expect'; import { setTimeout as setTimeoutAsync } from 'timers/promises'; import type { FittingFunction, XYCurveType } from '@kbn/lens-plugin/public'; import { DebugState } from '@elastic/charts'; -import { WebElementWrapper } from '../../../../test/functional/services/lib/web_element_wrapper'; +import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import { FtrProviderContext } from '../ftr_provider_context'; import { logWrapper } from './log_wrapper'; diff --git a/x-pack/test/functional/page_objects/navigational_search.ts b/x-pack/test/functional/page_objects/navigational_search.ts index ae27d6d68a4a..54c1582f322c 100644 --- a/x-pack/test/functional/page_objects/navigational_search.ts +++ b/x-pack/test/functional/page_objects/navigational_search.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { WebElementWrapper } from '../../../../test/functional/services/lib/web_element_wrapper'; +import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import { FtrService } from '../ftr_provider_context'; interface SearchResult { diff --git a/x-pack/test/functional/page_objects/observability_log_explorer.ts b/x-pack/test/functional/page_objects/observability_log_explorer.ts index a61682e62a8c..07cdf818a7ae 100644 --- a/x-pack/test/functional/page_objects/observability_log_explorer.ts +++ b/x-pack/test/functional/page_objects/observability_log_explorer.ts @@ -11,7 +11,7 @@ import { } from '@kbn/observability-log-explorer-plugin/common'; import rison from '@kbn/rison'; import querystring from 'querystring'; -import { WebElementWrapper } from '../../../../test/functional/services/lib/web_element_wrapper'; +import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import { FtrProviderContext } from '../ftr_provider_context'; export interface IntegrationPackage { diff --git a/x-pack/test/functional/page_objects/tag_management_page.ts b/x-pack/test/functional/page_objects/tag_management_page.ts index 5eb93aa977cf..30c6689d87b8 100644 --- a/x-pack/test/functional/page_objects/tag_management_page.ts +++ b/x-pack/test/functional/page_objects/tag_management_page.ts @@ -7,7 +7,7 @@ /* eslint-disable max-classes-per-file */ -import { WebElementWrapper } from '../../../../test/functional/services/lib/web_element_wrapper'; +import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import { FtrService, FtrProviderContext } from '../ftr_provider_context'; interface FillTagFormFields { diff --git a/x-pack/test/functional/services/cases/list.ts b/x-pack/test/functional/services/cases/list.ts index 61d588dc261e..03d1078ccec2 100644 --- a/x-pack/test/functional/services/cases/list.ts +++ b/x-pack/test/functional/services/cases/list.ts @@ -6,7 +6,7 @@ */ import { CaseSeverity, CaseStatuses } from '@kbn/cases-plugin/common/types/domain'; -import { WebElementWrapper } from '../../../../../test/functional/services/lib/web_element_wrapper'; +import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import { FtrProviderContext } from '../../ftr_provider_context'; import { CasesCommon } from './common'; diff --git a/x-pack/test/functional/services/infra_source_configuration_form.ts b/x-pack/test/functional/services/infra_source_configuration_form.ts index 741d42ac16fd..805dfcbbc9dc 100644 --- a/x-pack/test/functional/services/infra_source_configuration_form.ts +++ b/x-pack/test/functional/services/infra_source_configuration_form.ts @@ -5,8 +5,8 @@ * 2.0. */ +import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import { FtrProviderContext } from '../ftr_provider_context'; -import { WebElementWrapper } from '../../../../test/functional/services/lib/web_element_wrapper'; export function InfraSourceConfigurationFormProvider({ getService, diff --git a/x-pack/test/functional/services/logs_ui/log_entry_categories.ts b/x-pack/test/functional/services/logs_ui/log_entry_categories.ts index 0aec1cbea221..77098bd918ea 100644 --- a/x-pack/test/functional/services/logs_ui/log_entry_categories.ts +++ b/x-pack/test/functional/services/logs_ui/log_entry_categories.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { WebElementWrapper } from '../../../../../test/functional/services/lib/web_element_wrapper'; +import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import { FtrProviderContext } from '../../ftr_provider_context'; export function LogEntryCategoriesPageProvider({ getPageObjects, getService }: FtrProviderContext) { diff --git a/x-pack/test/functional/services/logs_ui/log_entry_rate.ts b/x-pack/test/functional/services/logs_ui/log_entry_rate.ts index bf58d74a06c4..f8a68f6c924e 100644 --- a/x-pack/test/functional/services/logs_ui/log_entry_rate.ts +++ b/x-pack/test/functional/services/logs_ui/log_entry_rate.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { WebElementWrapper } from '../../../../../test/functional/services/lib/web_element_wrapper'; +import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import { FtrProviderContext } from '../../ftr_provider_context'; export function LogEntryRatePageProvider({ getPageObjects, getService }: FtrProviderContext) { diff --git a/x-pack/test/functional/services/logs_ui/log_stream.ts b/x-pack/test/functional/services/logs_ui/log_stream.ts index 1a068439a2d2..160e949c84de 100644 --- a/x-pack/test/functional/services/logs_ui/log_stream.ts +++ b/x-pack/test/functional/services/logs_ui/log_stream.ts @@ -5,8 +5,8 @@ * 2.0. */ +import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import { FtrProviderContext } from '../../ftr_provider_context'; -import { WebElementWrapper } from '../../../../../test/functional/services/lib/web_element_wrapper'; import { TabsParams } from '../../page_objects/infra_logs_page'; export function LogStreamPageProvider({ getPageObjects, getService }: FtrProviderContext) { diff --git a/x-pack/test/functional/services/ml/common_table_service.ts b/x-pack/test/functional/services/ml/common_table_service.ts index ac403d62b5ac..683ac91f4e7a 100644 --- a/x-pack/test/functional/services/ml/common_table_service.ts +++ b/x-pack/test/functional/services/ml/common_table_service.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { WebElementWrapper } from '../../../../../test/functional/services/lib/web_element_wrapper'; +import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import { FtrProviderContext } from '../../ftr_provider_context'; export type MlTableService = ReturnType; diff --git a/x-pack/test/functional/services/ml/common_ui.ts b/x-pack/test/functional/services/ml/common_ui.ts index dc4836ed6f34..63a1fdf17cf4 100644 --- a/x-pack/test/functional/services/ml/common_ui.ts +++ b/x-pack/test/functional/services/ml/common_ui.ts @@ -7,7 +7,7 @@ import expect from '@kbn/expect'; import { ProvidedType } from '@kbn/test'; -import { WebElementWrapper } from '../../../../../test/functional/services/lib/web_element_wrapper'; +import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import { FtrProviderContext } from '../../ftr_provider_context'; import type { CanvasElementColorStats } from '../canvas_element'; diff --git a/x-pack/test/functional/services/ml/data_frame_analytics_results.ts b/x-pack/test/functional/services/ml/data_frame_analytics_results.ts index 0fc99e1e032a..17a409a082ce 100644 --- a/x-pack/test/functional/services/ml/data_frame_analytics_results.ts +++ b/x-pack/test/functional/services/ml/data_frame_analytics_results.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { WebElementWrapper } from '../../../../../test/functional/services/lib/web_element_wrapper'; +import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import { FtrProviderContext } from '../../ftr_provider_context'; import type { CanvasElementColorStats } from '../canvas_element'; import type { MlCommonUI } from './common_ui'; diff --git a/x-pack/test/functional/services/ml/data_frame_analytics_table.ts b/x-pack/test/functional/services/ml/data_frame_analytics_table.ts index 2b89364644a3..c85e38cd78b8 100644 --- a/x-pack/test/functional/services/ml/data_frame_analytics_table.ts +++ b/x-pack/test/functional/services/ml/data_frame_analytics_table.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; import { ProvidedType } from '@kbn/test'; -import { WebElementWrapper } from '../../../../../test/functional/services/lib/web_element_wrapper'; +import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import { FtrProviderContext } from '../../ftr_provider_context'; type ExpectedSectionTableEntries = Record; diff --git a/x-pack/test/functional/services/ml/stack_management_jobs.ts b/x-pack/test/functional/services/ml/stack_management_jobs.ts index f8db28deb509..52b8e005ac94 100644 --- a/x-pack/test/functional/services/ml/stack_management_jobs.ts +++ b/x-pack/test/functional/services/ml/stack_management_jobs.ts @@ -14,7 +14,7 @@ import path from 'path'; import type { JobType, MlSavedObjectType } from '@kbn/ml-plugin/common/types/saved_objects'; import type { Job, Datafeed } from '@kbn/ml-plugin/common/types/anomaly_detection_jobs'; import type { DataFrameAnalyticsConfig } from '@kbn/ml-data-frame-analytics-utils'; -import { WebElementWrapper } from '../../../../../test/functional/services/lib/web_element_wrapper'; +import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import type { FtrProviderContext } from '../../ftr_provider_context'; type SyncFlyoutObjectType = diff --git a/x-pack/test/functional/services/ml/swim_lane.ts b/x-pack/test/functional/services/ml/swim_lane.ts index 54895918a6d0..d9ad1dd44d98 100644 --- a/x-pack/test/functional/services/ml/swim_lane.ts +++ b/x-pack/test/functional/services/ml/swim_lane.ts @@ -9,8 +9,8 @@ import expect from '@kbn/expect'; import { ProvidedType } from '@kbn/test'; import { DebugState } from '@elastic/charts'; import { DebugStateAxis } from '@elastic/charts/dist/state/types'; +import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import { FtrProviderContext } from '../../ftr_provider_context'; -import { WebElementWrapper } from '../../../../../test/functional/services/lib/web_element_wrapper'; type HeatmapDebugState = Required>; diff --git a/x-pack/test/functional/services/ml/trained_models_table.ts b/x-pack/test/functional/services/ml/trained_models_table.ts index a186c531703b..4ea56286de4f 100644 --- a/x-pack/test/functional/services/ml/trained_models_table.ts +++ b/x-pack/test/functional/services/ml/trained_models_table.ts @@ -9,7 +9,7 @@ import expect from '@kbn/expect'; import { ProvidedType } from '@kbn/test'; import { upperFirst } from 'lodash'; -import { WebElementWrapper } from '../../../../../test/functional/services/lib/web_element_wrapper'; +import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import type { FtrProviderContext } from '../../ftr_provider_context'; import type { MlCommonUI } from './common_ui'; import { MappedInputParams, MappedOutput, ModelType, TrainedModelsActions } from './trained_models'; diff --git a/x-pack/test/functional/services/observability/alerts/common.ts b/x-pack/test/functional/services/observability/alerts/common.ts index 57403ef8c3ab..617fadcf25e2 100644 --- a/x-pack/test/functional/services/observability/alerts/common.ts +++ b/x-pack/test/functional/services/observability/alerts/common.ts @@ -8,8 +8,8 @@ import expect from '@kbn/expect'; import { chunk } from 'lodash'; import { ALERT_STATUS_ACTIVE, ALERT_STATUS_RECOVERED, AlertStatus } from '@kbn/rule-data-utils'; +import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import { FtrProviderContext } from '../../../ftr_provider_context'; -import { WebElementWrapper } from '../../../../../../test/functional/services/lib/web_element_wrapper'; // Based on the x-pack/test/functional/es_archives/observability/alerts archive. const DATE_WITH_DATA = { diff --git a/x-pack/test/functional/services/search_sessions.ts b/x-pack/test/functional/services/search_sessions.ts index a22e63574268..cd0b60d32127 100644 --- a/x-pack/test/functional/services/search_sessions.ts +++ b/x-pack/test/functional/services/search_sessions.ts @@ -9,7 +9,7 @@ import { ELASTIC_HTTP_VERSION_HEADER } from '@kbn/core-http-common'; import { INITIAL_SEARCH_SESSION_REST_VERSION } from '@kbn/data-plugin/server'; import expect from '@kbn/expect'; import { SavedObjectsFindResponse } from '@kbn/core/server'; -import { WebElementWrapper } from '../../../../test/functional/services/lib/web_element_wrapper'; +import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import { FtrService } from '../ftr_provider_context'; const SEARCH_SESSION_INDICATOR_TEST_SUBJ = 'searchSessionIndicator'; diff --git a/x-pack/test/functional/services/transform/transform_table.ts b/x-pack/test/functional/services/transform/transform_table.ts index 665b04b05810..7a5f303ba155 100644 --- a/x-pack/test/functional/services/transform/transform_table.ts +++ b/x-pack/test/functional/services/transform/transform_table.ts @@ -7,7 +7,7 @@ import expect from '@kbn/expect'; -import { WebElementWrapper } from '../../../../../test/functional/services/lib/web_element_wrapper'; +import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import { FtrProviderContext } from '../../ftr_provider_context'; diff --git a/x-pack/test/functional_enterprise_search/page_objects/app_search.ts b/x-pack/test/functional_enterprise_search/page_objects/app_search.ts index 8c02cdb70527..75fe3da03ed1 100644 --- a/x-pack/test/functional_enterprise_search/page_objects/app_search.ts +++ b/x-pack/test/functional_enterprise_search/page_objects/app_search.ts @@ -5,9 +5,9 @@ * 2.0. */ +import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import { FtrProviderContext } from '../ftr_provider_context'; import { TestSubjects } from '../../../../test/functional/services/common'; -import { WebElementWrapper } from '../../../../test/functional/services/lib/web_element_wrapper'; export function AppSearchPageProvider({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects(['common']); 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 f72677bff7f0..cdffa758420c 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 @@ -6,10 +6,7 @@ */ import expect from '@kbn/expect'; -import { - CustomCheerio, - CustomCheerioStatic, -} from '../../../../test/functional/services/lib/web_element_wrapper/custom_cheerio_api'; +import type { CustomCheerio, CustomCheerioStatic } from '@kbn/ftr-common-functional-ui-services'; import { FtrProviderContext } from '../ftr_provider_context'; const ENTER_KEY = '\uE007'; diff --git a/x-pack/test/plugin_functional/test_suites/resolver/index.ts b/x-pack/test/plugin_functional/test_suites/resolver/index.ts index edc5d2597107..51fa15867262 100644 --- a/x-pack/test/plugin_functional/test_suites/resolver/index.ts +++ b/x-pack/test/plugin_functional/test_suites/resolver/index.ts @@ -7,7 +7,7 @@ import expect from '@kbn/expect'; import { panAnimationDuration } from '@kbn/security-solution-plugin/public/resolver/store/camera/scaling_constants'; -import { WebElementWrapper } from '../../../../../test/functional/services/lib/web_element_wrapper'; +import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import { FtrProviderContext } from '../../ftr_provider_context'; diff --git a/x-pack/test/security_solution_endpoint/apps/integrations/endpoint_exceptions.ts b/x-pack/test/security_solution_endpoint/apps/integrations/endpoint_exceptions.ts index 539101c79504..8647d418a639 100644 --- a/x-pack/test/security_solution_endpoint/apps/integrations/endpoint_exceptions.ts +++ b/x-pack/test/security_solution_endpoint/apps/integrations/endpoint_exceptions.ts @@ -11,7 +11,7 @@ import { IndexedHostsAndAlertsResponse } from '@kbn/security-solution-plugin/com import { EXCEPTION_LIST_ITEM_URL } from '@kbn/securitysolution-list-constants'; import { ArtifactElasticsearchProperties } from '@kbn/fleet-plugin/server/services'; import { FoundExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types'; -import { WebElementWrapper } from '../../../../../test/functional/services/lib/web_element_wrapper'; +import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import { FtrProviderContext } from '../../ftr_provider_context'; import { targetTags } from '../../target_tags'; diff --git a/x-pack/test/security_solution_endpoint/page_objects/endpoint_page.ts b/x-pack/test/security_solution_endpoint/page_objects/endpoint_page.ts index ec3eaf97eb81..ceea71593a95 100644 --- a/x-pack/test/security_solution_endpoint/page_objects/endpoint_page.ts +++ b/x-pack/test/security_solution_endpoint/page_objects/endpoint_page.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { WebElementWrapper } from '../../../../test/functional/services/lib/web_element_wrapper'; +import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import { FtrProviderContext } from '../ftr_provider_context'; export function EndpointPageProvider({ getService, getPageObjects }: FtrProviderContext) { diff --git a/x-pack/test/security_solution_endpoint/page_objects/ingest_manager_create_package_policy_page.ts b/x-pack/test/security_solution_endpoint/page_objects/ingest_manager_create_package_policy_page.ts index 913d1e18d1dc..acdb58460cbb 100644 --- a/x-pack/test/security_solution_endpoint/page_objects/ingest_manager_create_package_policy_page.ts +++ b/x-pack/test/security_solution_endpoint/page_objects/ingest_manager_create_package_policy_page.ts @@ -5,8 +5,8 @@ * 2.0. */ +import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import { FtrProviderContext } from '../ftr_provider_context'; -import { WebElementWrapper } from '../../../../test/functional/services/lib/web_element_wrapper'; export function IngestManagerCreatePackagePolicy({ getService, diff --git a/x-pack/test/security_solution_endpoint/page_objects/page_utils.ts b/x-pack/test/security_solution_endpoint/page_objects/page_utils.ts index 69cb8e455b15..d14846f8583e 100644 --- a/x-pack/test/security_solution_endpoint/page_objects/page_utils.ts +++ b/x-pack/test/security_solution_endpoint/page_objects/page_utils.ts @@ -5,8 +5,8 @@ * 2.0. */ +import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import { FtrProviderContext } from '../ftr_provider_context'; -import { WebElementWrapper } from '../../../../test/functional/services/lib/web_element_wrapper'; export function EndpointPageUtils({ getService }: FtrProviderContext) { const testSubjects = getService('testSubjects'); diff --git a/x-pack/test/security_solution_ftr/page_objects/detections/index.ts b/x-pack/test/security_solution_ftr/page_objects/detections/index.ts index a8ff43a8e06b..e45fa7f7a5eb 100644 --- a/x-pack/test/security_solution_ftr/page_objects/detections/index.ts +++ b/x-pack/test/security_solution_ftr/page_objects/detections/index.ts @@ -5,8 +5,8 @@ * 2.0. */ +import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import { FtrService } from '../../../functional/ftr_provider_context'; -import { WebElementWrapper } from '../../../../../test/functional/services/lib/web_element_wrapper'; const ALERT_TABLE_ROW_CSS_SELECTOR = '[data-test-subj="alertsTable"] .euiDataGridRow'; diff --git a/x-pack/test/security_solution_ftr/page_objects/hosts/index.ts b/x-pack/test/security_solution_ftr/page_objects/hosts/index.ts index 0d80db314121..50e232a8693e 100644 --- a/x-pack/test/security_solution_ftr/page_objects/hosts/index.ts +++ b/x-pack/test/security_solution_ftr/page_objects/hosts/index.ts @@ -5,8 +5,8 @@ * 2.0. */ +import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import { FtrService } from '../../../functional/ftr_provider_context'; -import { WebElementWrapper } from '../../../../../test/functional/services/lib/web_element_wrapper'; export class HostsPageObject extends FtrService { private readonly pageObjects = this.ctx.getPageObjects(['common', 'header']); diff --git a/x-pack/test/tsconfig.json b/x-pack/test/tsconfig.json index 894d4c803994..4ca836a47554 100644 --- a/x-pack/test/tsconfig.json +++ b/x-pack/test/tsconfig.json @@ -165,5 +165,6 @@ "@kbn/log-explorer-plugin", "@kbn/security-plugin-types-common", "@kbn/typed-react-router-config", + "@kbn/ftr-common-functional-ui-services", ] } diff --git a/x-pack/test/upgrade/services/rules_upgrade_services.ts b/x-pack/test/upgrade/services/rules_upgrade_services.ts index 188f41bcddc9..54780fbe5adf 100644 --- a/x-pack/test/upgrade/services/rules_upgrade_services.ts +++ b/x-pack/test/upgrade/services/rules_upgrade_services.ts @@ -6,11 +6,8 @@ */ import expect from '@kbn/expect'; +import type { CustomCheerio, CustomCheerioStatic } from '@kbn/ftr-common-functional-ui-services'; import { FtrProviderContext } from '../ftr_provider_context'; -import { - CustomCheerio, - CustomCheerioStatic, -} from '../../../../test/functional/services/lib/web_element_wrapper/custom_cheerio_api'; export function RulesHelper({ getPageObjects, getService }: FtrProviderContext) { const find = getService('find'); diff --git a/x-pack/test_serverless/functional/page_objects/svl_common_navigation.ts b/x-pack/test_serverless/functional/page_objects/svl_common_navigation.ts index 93b5dea4f049..9a91f5da1240 100644 --- a/x-pack/test_serverless/functional/page_objects/svl_common_navigation.ts +++ b/x-pack/test_serverless/functional/page_objects/svl_common_navigation.ts @@ -16,8 +16,8 @@ import type { NavigationID as DevNavId } from '@kbn/default-nav-devtools'; // use this for nicer type suggestions, but allow any string anyway type NavigationId = MlNavId | AlNavId | MgmtNavId | DevNavId | string; +import type { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import type { FtrProviderContext } from '../ftr_provider_context'; -import type { WebElementWrapper } from '../../../../test/functional/services/lib/web_element_wrapper'; const getSectionIdTestSubj = (sectionId: NavigationId) => `~nav-item-${sectionId}`; diff --git a/x-pack/test_serverless/functional/page_objects/svl_triggers_actions_ui_page.ts b/x-pack/test_serverless/functional/page_objects/svl_triggers_actions_ui_page.ts index 589544cca9c5..e9f407c06753 100644 --- a/x-pack/test_serverless/functional/page_objects/svl_triggers_actions_ui_page.ts +++ b/x-pack/test_serverless/functional/page_objects/svl_triggers_actions_ui_page.ts @@ -6,10 +6,7 @@ */ import expect from '@kbn/expect'; -import type { - CustomCheerio, - CustomCheerioStatic, -} from '../../../../test/functional/services/lib/web_element_wrapper/custom_cheerio_api'; +import type { CustomCheerio, CustomCheerioStatic } from '@kbn/ftr-common-functional-ui-services'; import { FtrProviderContext } from '../ftr_provider_context'; const ENTER_KEY = '\uE007'; diff --git a/x-pack/test_serverless/functional/test_suites/common/discover/x_pack/visualize_field.ts b/x-pack/test_serverless/functional/test_suites/common/discover/x_pack/visualize_field.ts index ab1ad279b886..e412fea58df5 100644 --- a/x-pack/test_serverless/functional/test_suites/common/discover/x_pack/visualize_field.ts +++ b/x-pack/test_serverless/functional/test_suites/common/discover/x_pack/visualize_field.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import type { WebElementWrapper } from '../../../../../../../test/functional/services/lib/web_element_wrapper'; +import type { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import { FtrProviderContext } from '../../../../ftr_provider_context'; export default function ({ getPageObjects, getService }: FtrProviderContext) { diff --git a/x-pack/test_serverless/functional/test_suites/common/examples/search/warnings.ts b/x-pack/test_serverless/functional/test_suites/common/examples/search/warnings.ts index a254cb753c86..43ec250ff996 100644 --- a/x-pack/test_serverless/functional/test_suites/common/examples/search/warnings.ts +++ b/x-pack/test_serverless/functional/test_suites/common/examples/search/warnings.ts @@ -8,7 +8,7 @@ import type { estypes } from '@elastic/elasticsearch'; import expect from '@kbn/expect'; import assert from 'assert'; -import type { WebElementWrapper } from '../../../../../../../test/functional/services/lib/web_element_wrapper'; +import type { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import type { FtrProviderContext } from '../../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { diff --git a/x-pack/test_serverless/functional/test_suites/common/management/index_management/component_templates.ts b/x-pack/test_serverless/functional/test_suites/common/management/index_management/component_templates.ts index 9e044667692c..e70470582b2b 100644 --- a/x-pack/test_serverless/functional/test_suites/common/management/index_management/component_templates.ts +++ b/x-pack/test_serverless/functional/test_suites/common/management/index_management/component_templates.ts @@ -7,8 +7,8 @@ import expect from '@kbn/expect'; +import type { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import { FtrProviderContext } from '../../../../ftr_provider_context'; -import type { WebElementWrapper } from '../../../../../../../test/functional/services/lib/web_element_wrapper'; export default ({ getPageObjects, getService }: FtrProviderContext) => { const pageObjects = getPageObjects(['svlCommonPage', 'common', 'indexManagement', 'header']); diff --git a/x-pack/test_serverless/functional/test_suites/common/management/index_management/index_templates.ts b/x-pack/test_serverless/functional/test_suites/common/management/index_management/index_templates.ts index 791d3c313b7a..371ee4debe98 100644 --- a/x-pack/test_serverless/functional/test_suites/common/management/index_management/index_templates.ts +++ b/x-pack/test_serverless/functional/test_suites/common/management/index_management/index_templates.ts @@ -7,8 +7,8 @@ import expect from '@kbn/expect'; +import type { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import { FtrProviderContext } from '../../../../ftr_provider_context'; -import type { WebElementWrapper } from '../../../../../../../test/functional/services/lib/web_element_wrapper'; export default ({ getPageObjects, getService }: FtrProviderContext) => { const pageObjects = getPageObjects(['svlCommonPage', 'common', 'indexManagement', 'header']); diff --git a/x-pack/test_serverless/functional/test_suites/observability/infra/hosts_page.ts b/x-pack/test_serverless/functional/test_suites/observability/infra/hosts_page.ts index 7e23b43b253c..92dfb107dd44 100644 --- a/x-pack/test_serverless/functional/test_suites/observability/infra/hosts_page.ts +++ b/x-pack/test_serverless/functional/test_suites/observability/infra/hosts_page.ts @@ -7,7 +7,7 @@ import moment from 'moment'; import expect from '@kbn/expect'; -import type { WebElementWrapper } from '../../../../../../test/functional/services/lib/web_element_wrapper'; +import type { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; import type { FtrProviderContext } from '../../../ftr_provider_context'; import { HOSTS_VIEW_PATH } from './constants'; diff --git a/x-pack/test_serverless/tsconfig.json b/x-pack/test_serverless/tsconfig.json index 54c1e26f069d..c9c37a3c3f3a 100644 --- a/x-pack/test_serverless/tsconfig.json +++ b/x-pack/test_serverless/tsconfig.json @@ -84,5 +84,6 @@ "@kbn/log-explorer-plugin", "@kbn/index-management-plugin", "@kbn/alerting-plugin", + "@kbn/ftr-common-functional-ui-services", ] } From 49886a5d79308c6367a108140c5ddea1dbaf3df6 Mon Sep 17 00:00:00 2001 From: Jonathan Budzenski Date: Thu, 4 Jan 2024 12:30:53 -0600 Subject: [PATCH 15/57] skip failing test suite (#174194, #174195) --- .../actions/assignees/edit_assignees_flyout.test.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/cases/public/components/actions/assignees/edit_assignees_flyout.test.tsx b/x-pack/plugins/cases/public/components/actions/assignees/edit_assignees_flyout.test.tsx index d6f65ff09b69..9001faa12a2a 100644 --- a/x-pack/plugins/cases/public/components/actions/assignees/edit_assignees_flyout.test.tsx +++ b/x-pack/plugins/cases/public/components/actions/assignees/edit_assignees_flyout.test.tsx @@ -16,7 +16,9 @@ import { waitFor } from '@testing-library/react'; jest.mock('../../../containers/user_profiles/api'); -describe('EditAssigneesFlyout', () => { +// Failing: See https://github.com/elastic/kibana/issues/174194 +// Failing: See https://github.com/elastic/kibana/issues/174195 +describe.skip('EditAssigneesFlyout', () => { let appMock: AppMockRenderer; /** From 33f83681326ab05db53fcaafef382631201868a7 Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Thu, 4 Jan 2024 13:33:32 -0500 Subject: [PATCH 16/57] skip failing test suite (#174204) --- .../routes/csp_benchmark_rules_bulk_update.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/cloud_security_posture_api/routes/csp_benchmark_rules_bulk_update.ts b/x-pack/test/cloud_security_posture_api/routes/csp_benchmark_rules_bulk_update.ts index 022ab5e3b32f..2c7d0ce250b0 100644 --- a/x-pack/test/cloud_security_posture_api/routes/csp_benchmark_rules_bulk_update.ts +++ b/x-pack/test/cloud_security_posture_api/routes/csp_benchmark_rules_bulk_update.ts @@ -93,7 +93,8 @@ export default function ({ getService }: FtrProviderContext) { log.debug('CSP plugin is initialized'); }); - describe('Verify update csp rules states API', async () => { + // Failing: See https://github.com/elastic/kibana/issues/174204 + describe.skip('Verify update csp rules states API', async () => { before(async () => { await waitForPluginInitialized(); }); From 6d909fff999da629e7886a0683c78a1ebf9e254b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yulia=20=C4=8Cech?= <6585477+yuliacech@users.noreply.github.com> Date: Thu, 4 Jan 2024 19:58:09 +0100 Subject: [PATCH 17/57] [Index Management] Fix managed data streams badge (#173408) ## Summary This PR fixes the badge "managed" missing from the data streams list. The code used to check that the data stream has both conditions for a managed data streams `meta.managed: true` and `meta.managed_by: 'ingest-manager'`. The check for `ingest-manager` is not coorect since it's been renamed to fleet. Instead of updating the check though, I decided to only leave the condition for `meta.managed : true` and I removed all mentions of "Fleet" from the Data streams tab. I believe that is more consistent for the UI, since we don't mention "Fleet-managed" anywhere else like ILM, index templates etc. ### Screenshot Screenshot 2023-12-18 at 16 11 35 --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../home/data_streams_tab.test.ts | 24 ++++--------------- .../public/application/lib/data_streams.tsx | 9 ++++--- .../data_stream_list/data_stream_badges.tsx | 6 ++--- .../data_stream_list/data_stream_list.tsx | 6 ++--- .../translations/translations/fr-FR.json | 2 -- .../translations/translations/ja-JP.json | 2 -- .../translations/translations/zh-CN.json | 2 -- .../data_streams_tab/data_streams_tab.ts | 6 ++--- .../page_objects/index_management_page.ts | 8 ++----- .../test_suites/common/management/index.ts | 6 +---- .../index_management/data_streams.ts | 6 ++--- .../management/index_management/index.ts | 19 +++++++++++++++ 12 files changed, 43 insertions(+), 53 deletions(-) create mode 100644 x-pack/test_serverless/functional/test_suites/common/management/index_management/index.ts diff --git a/x-pack/plugins/index_management/__jest__/client_integration/home/data_streams_tab.test.ts b/x-pack/plugins/index_management/__jest__/client_integration/home/data_streams_tab.test.ts index db38796d2ab3..e306398c541c 100644 --- a/x-pack/plugins/index_management/__jest__/client_integration/home/data_streams_tab.test.ts +++ b/x-pack/plugins/index_management/__jest__/client_integration/home/data_streams_tab.test.ts @@ -71,7 +71,7 @@ describe('Data Streams tab', () => { expect(exists('emptyPrompt')).toBe(true); }); - test('when Ingest Manager is disabled, goes to index templates tab when "Get started" link is clicked', async () => { + test('when Fleet is disabled, goes to index templates tab when "Get started" link is clicked', async () => { testBed = await setup(httpSetup, { plugins: {}, url: urlServiceMock, @@ -796,7 +796,7 @@ describe('Data Streams tab', () => { _meta: { package: 'test', managed: true, - managed_by: 'ingest-manager', + managed_by: 'fleet', }, }); const nonManagedDataStream = createDataStreamPayload({ name: 'non-managed-data-stream' }); @@ -813,19 +813,12 @@ describe('Data Streams tab', () => { testBed.component.update(); }); - test('listed in the table with Fleet-managed label', () => { + test('listed in the table with managed label', () => { const { table } = testBed; const { tableCellsValues } = table.getMetaData('dataStreamTable'); expect(tableCellsValues).toEqual([ - [ - '', - `managed-data-stream${nonBreakingSpace}Fleet-managed`, - 'green', - '1', - '7 days', - 'Delete', - ], + ['', `managed-data-stream${nonBreakingSpace}Managed`, 'green', '1', '7 days', 'Delete'], ['', 'non-managed-data-stream', 'green', '1', '7 days', 'Delete'], ]); }); @@ -835,14 +828,7 @@ describe('Data Streams tab', () => { let { tableCellsValues } = table.getMetaData('dataStreamTable'); expect(tableCellsValues).toEqual([ - [ - '', - `managed-data-stream${nonBreakingSpace}Fleet-managed`, - 'green', - '1', - '7 days', - 'Delete', - ], + ['', `managed-data-stream${nonBreakingSpace}Managed`, 'green', '1', '7 days', 'Delete'], ['', 'non-managed-data-stream', 'green', '1', '7 days', 'Delete'], ]); diff --git a/x-pack/plugins/index_management/public/application/lib/data_streams.tsx b/x-pack/plugins/index_management/public/application/lib/data_streams.tsx index c16b28f73410..44852c5dc323 100644 --- a/x-pack/plugins/index_management/public/application/lib/data_streams.tsx +++ b/x-pack/plugins/index_management/public/application/lib/data_streams.tsx @@ -12,9 +12,8 @@ import { EuiIcon, EuiToolTip } from '@elastic/eui'; import { splitSizeAndUnits, DataStream } from '../../../common'; import { timeUnits, extraTimeUnits } from '../constants/time_units'; -export const isFleetManaged = (dataStream: DataStream): boolean => { - // TODO check if the wording will change to 'fleet' - return Boolean(dataStream._meta?.managed && dataStream._meta?.managed_by === 'ingest-manager'); +export const isManaged = (dataStream: DataStream): boolean => { + return Boolean(dataStream._meta?.managed); }; export const filterDataStreams = ( @@ -23,13 +22,13 @@ export const filterDataStreams = ( ): DataStream[] => { return dataStreams.filter((dataStream: DataStream) => { // include all data streams that are neither hidden nor managed - if (!dataStream.hidden && !isFleetManaged(dataStream)) { + if (!dataStream.hidden && !isManaged(dataStream)) { return true; } if (dataStream.hidden && visibleTypes.includes('hidden')) { return true; } - return isFleetManaged(dataStream) && visibleTypes.includes('managed'); + return isManaged(dataStream) && visibleTypes.includes('managed'); }); }; diff --git a/x-pack/plugins/index_management/public/application/sections/home/data_stream_list/data_stream_badges.tsx b/x-pack/plugins/index_management/public/application/sections/home/data_stream_list/data_stream_badges.tsx index 39c6f61e75dd..2f98b6ac357a 100644 --- a/x-pack/plugins/index_management/public/application/sections/home/data_stream_list/data_stream_badges.tsx +++ b/x-pack/plugins/index_management/public/application/sections/home/data_stream_list/data_stream_badges.tsx @@ -9,7 +9,7 @@ import React from 'react'; import { EuiBadge, EuiBadgeGroup } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import { DataStream } from '../../../../../common'; -import { isFleetManaged } from '../../../lib/data_streams'; +import { isManaged } from '../../../lib/data_streams'; interface Props { dataStream: DataStream; @@ -17,12 +17,12 @@ interface Props { export const DataStreamsBadges: React.FunctionComponent = ({ dataStream }) => { const badges = []; - if (isFleetManaged(dataStream)) { + if (isManaged(dataStream)) { badges.push( ); diff --git a/x-pack/plugins/index_management/public/application/sections/home/data_stream_list/data_stream_list.tsx b/x-pack/plugins/index_management/public/application/sections/home/data_stream_list/data_stream_list.tsx index fa4efa61bf54..125f676897ff 100644 --- a/x-pack/plugins/index_management/public/application/sections/home/data_stream_list/data_stream_list.tsx +++ b/x-pack/plugins/index_management/public/application/sections/home/data_stream_list/data_stream_list.tsx @@ -84,7 +84,7 @@ export const DataStreamList: React.FunctionComponent>({ managed: { name: i18n.translate('xpack.idxMgmt.dataStreamList.viewManagedLabel', { - defaultMessage: 'Fleet-managed data streams', + defaultMessage: 'Managed data streams', }), checked: 'on', }, @@ -226,7 +226,7 @@ export const DataStreamList: React.FunctionComponent {i18n.translate( - 'xpack.idxMgmt.dataStreamList.emptyPrompt.noDataStreamsCtaIngestManagerLink', + 'xpack.idxMgmt.dataStreamList.emptyPrompt.noDataStreamsCtaFleetLink', { defaultMessage: 'Fleet', } diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index cbbd515a86e1..e7fa92aa02a3 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -18390,7 +18390,6 @@ "xpack.idxMgmt.createIndex.successfullyCreatedIndexMessage": "Création réussie de l'index : {indexName}", "xpack.idxMgmt.dataStreamList.dataStreamsDescription": "Les flux de données conservent des données de séries temporelles sur plusieurs index. {learnMoreLink}", "xpack.idxMgmt.dataStreamList.emptyPrompt.noDataStreamsCtaIndexTemplateMessage": "Lancez-vous avec les flux de données en créant un {link}.", - "xpack.idxMgmt.dataStreamList.emptyPrompt.noDataStreamsCtaIngestManagerMessage": "Lancez-vous avec les flux de données dans {link}.", "xpack.idxMgmt.dataStreamList.table.deleteDataStreamsButtonLabel": "Supprimer {count, plural, one {le flux de données} many {flux de données} other {flux de données}}", "xpack.idxMgmt.deleteDataStreamsConfirmationModal.confirmButtonLabel": "Supprimer {dataStreamsCount, plural, one {le flux de données} many {flux de données} other {flux de données}}", "xpack.idxMgmt.deleteDataStreamsConfirmationModal.deleteDescription": "Vous êtes sur le point de supprimer {dataStreamsCount, plural, one {ce flux de données} many {ces flux de données} other {ces flux de données}} :", @@ -18687,7 +18686,6 @@ "xpack.idxMgmt.dataStreamDetailPanel.timestampFieldTitle": "Champ d'horodatage", "xpack.idxMgmt.dataStreamDetailPanel.timestampFieldToolTip": "Champ d'horodatage partagé par tous les documents du flux de données.", "xpack.idxMgmt.dataStreamList.emptyPrompt.noDataStreamsCtaIndexTemplateLink": "modèle d'index composable", - "xpack.idxMgmt.dataStreamList.emptyPrompt.noDataStreamsCtaIngestManagerLink": "Fleet", "xpack.idxMgmt.dataStreamList.emptyPrompt.noDataStreamsDescription": "Les flux de données conservent des données de séries temporelles sur plusieurs index.", "xpack.idxMgmt.dataStreamList.emptyPrompt.noDataStreamsTitle": "Vous n'avez pas encore de flux de données", "xpack.idxMgmt.dataStreamList.loadingDataStreamsDescription": "Chargement des flux de données en cours…", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index f0575cc0496f..4a23239256f5 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -18403,7 +18403,6 @@ "xpack.idxMgmt.createIndex.successfullyCreatedIndexMessage": "インデックスの作成が正常に完了しました:{indexName}", "xpack.idxMgmt.dataStreamList.dataStreamsDescription": "データストリームは複数のインデックスの時系列データを格納します。{learnMoreLink}", "xpack.idxMgmt.dataStreamList.emptyPrompt.noDataStreamsCtaIndexTemplateMessage": "{link}を作成して、データストリームを開始します。", - "xpack.idxMgmt.dataStreamList.emptyPrompt.noDataStreamsCtaIngestManagerMessage": "{link}でデータストリームを開始します。", "xpack.idxMgmt.dataStreamList.table.deleteDataStreamsButtonLabel": "{count, plural, other {データストリーム}}削除", "xpack.idxMgmt.deleteDataStreamsConfirmationModal.confirmButtonLabel": "{dataStreamsCount, plural, other {データストリーム}}削除", "xpack.idxMgmt.deleteDataStreamsConfirmationModal.deleteDescription": "{dataStreamsCount, plural, other {これらのデータストリーム}}を削除しようとしています:", @@ -18700,7 +18699,6 @@ "xpack.idxMgmt.dataStreamDetailPanel.timestampFieldTitle": "タイムスタンプフィールド", "xpack.idxMgmt.dataStreamDetailPanel.timestampFieldToolTip": "タイムスタンプフィールドはデータストリームのすべてのドキュメントで共有されます。", "xpack.idxMgmt.dataStreamList.emptyPrompt.noDataStreamsCtaIndexTemplateLink": "作成可能なインデックステンプレート", - "xpack.idxMgmt.dataStreamList.emptyPrompt.noDataStreamsCtaIngestManagerLink": "Fleet", "xpack.idxMgmt.dataStreamList.emptyPrompt.noDataStreamsDescription": "データストリームは複数のインデックスの時系列データを格納します。", "xpack.idxMgmt.dataStreamList.emptyPrompt.noDataStreamsTitle": "まだデータストリームがありません", "xpack.idxMgmt.dataStreamList.loadingDataStreamsDescription": "データストリームを読み込んでいます…", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 2a5c081a8d01..ccce90db35aa 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -18470,7 +18470,6 @@ "xpack.idxMgmt.createIndex.successfullyCreatedIndexMessage": "已成功创建索引:{indexName}", "xpack.idxMgmt.dataStreamList.dataStreamsDescription": "数据流在多个索引上存储时序数据。{learnMoreLink}", "xpack.idxMgmt.dataStreamList.emptyPrompt.noDataStreamsCtaIndexTemplateMessage": "通过创建 {link} 来开始使用数据流。", - "xpack.idxMgmt.dataStreamList.emptyPrompt.noDataStreamsCtaIngestManagerMessage": "开始使用 {link} 中的数据流。", "xpack.idxMgmt.dataStreamList.table.deleteDataStreamsButtonLabel": "删除 {count, plural, other {数据流}}", "xpack.idxMgmt.deleteDataStreamsConfirmationModal.confirmButtonLabel": "删除 {dataStreamsCount, plural, other {数据流}}", "xpack.idxMgmt.deleteDataStreamsConfirmationModal.deleteDescription": "您即将删除{dataStreamsCount, plural, other {以下数据流}}:", @@ -18767,7 +18766,6 @@ "xpack.idxMgmt.dataStreamDetailPanel.timestampFieldTitle": "时间戳字段", "xpack.idxMgmt.dataStreamDetailPanel.timestampFieldToolTip": "时间戳字段由数据流中的所有文档共享。", "xpack.idxMgmt.dataStreamList.emptyPrompt.noDataStreamsCtaIndexTemplateLink": "可组合索引模板", - "xpack.idxMgmt.dataStreamList.emptyPrompt.noDataStreamsCtaIngestManagerLink": "Fleet", "xpack.idxMgmt.dataStreamList.emptyPrompt.noDataStreamsDescription": "数据流存储多个索引的时序数据。", "xpack.idxMgmt.dataStreamList.emptyPrompt.noDataStreamsTitle": "您尚未有任何数据流", "xpack.idxMgmt.dataStreamList.loadingDataStreamsDescription": "正在加载数据流……", diff --git a/x-pack/test/functional/apps/index_management/data_streams_tab/data_streams_tab.ts b/x-pack/test/functional/apps/index_management/data_streams_tab/data_streams_tab.ts index 9d3da94fead4..4480063da220 100644 --- a/x-pack/test/functional/apps/index_management/data_streams_tab/data_streams_tab.ts +++ b/x-pack/test/functional/apps/index_management/data_streams_tab/data_streams_tab.ts @@ -78,7 +78,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { it('shows the details flyout when clicking on a data stream', async () => { // Open details flyout - await pageObjects.indexManagement.clickDataStreamAt(0); + await pageObjects.indexManagement.clickDataStreamNameLink(TEST_DS_NAME); // Verify url is stateful const url = await browser.getCurrentUrl(); expect(url).to.contain(`/data_streams/${TEST_DS_NAME}`); @@ -90,7 +90,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { it('allows to update data retention', async () => { // Open details flyout - await pageObjects.indexManagement.clickDataStreamAt(0); + await pageObjects.indexManagement.clickDataStreamNameLink(TEST_DS_NAME); // Open the edit retention dialog await testSubjects.click('manageDataStreamButton'); await testSubjects.click('editDataRetentionButton'); @@ -112,7 +112,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { it('allows to disable data retention', async () => { // Open details flyout - await pageObjects.indexManagement.clickDataStreamAt(0); + await pageObjects.indexManagement.clickDataStreamNameLink(TEST_DS_NAME); // Open the edit retention dialog await testSubjects.click('manageDataStreamButton'); await testSubjects.click('editDataRetentionButton'); diff --git a/x-pack/test/functional/page_objects/index_management_page.ts b/x-pack/test/functional/page_objects/index_management_page.ts index 9dc9d30fd375..19eb3f2824f3 100644 --- a/x-pack/test/functional/page_objects/index_management_page.ts +++ b/x-pack/test/functional/page_objects/index_management_page.ts @@ -22,9 +22,6 @@ export function IndexManagementPageProvider({ getService }: FtrProviderContext) async reloadIndicesButton() { return await testSubjects.find('reloadIndicesButton'); }, - async toggleRollupIndices() { - await testSubjects.click('checkboxToggles-rollupToggle'); - }, async toggleHiddenIndices() { await testSubjects.click('indexTableIncludeHiddenIndicesToggle'); }, @@ -34,9 +31,8 @@ export function IndexManagementPageProvider({ getService }: FtrProviderContext) await policyDetailsLinks[indexOfRow].click(); }, - async clickDataStreamAt(indexOfRow: number): Promise { - const dataStreamLinks = await testSubjects.findAll('nameLink'); - await dataStreamLinks[indexOfRow].click(); + async clickDataStreamNameLink(name: string): Promise { + await find.clickByLinkText(name); }, async clickDeleteEnrichPolicyAt(indexOfRow: number): Promise { diff --git a/x-pack/test_serverless/functional/test_suites/common/management/index.ts b/x-pack/test_serverless/functional/test_suites/common/management/index.ts index 3291f50dc6bc..e523e27c3cf0 100644 --- a/x-pack/test_serverless/functional/test_suites/common/management/index.ts +++ b/x-pack/test_serverless/functional/test_suites/common/management/index.ts @@ -9,11 +9,7 @@ import { FtrProviderContext } from '../../../ftr_provider_context'; export default ({ loadTestFile }: FtrProviderContext) => { describe('Serverless Common UI - Management', function () { - loadTestFile(require.resolve('./index_management/index_templates')); - loadTestFile(require.resolve('./index_management/indices')); - loadTestFile(require.resolve('./index_management/create_enrich_policy')); - loadTestFile(require.resolve('./index_management/enrich_policies')); - loadTestFile(require.resolve('./index_management/component_templates')); + loadTestFile(require.resolve('./index_management')); loadTestFile(require.resolve('./transforms/search_bar_features')); loadTestFile(require.resolve('./transforms/transform_list')); loadTestFile(require.resolve('./advanced_settings')); diff --git a/x-pack/test_serverless/functional/test_suites/common/management/index_management/data_streams.ts b/x-pack/test_serverless/functional/test_suites/common/management/index_management/data_streams.ts index bbf55e359d36..4bd839e2c9eb 100644 --- a/x-pack/test_serverless/functional/test_suites/common/management/index_management/data_streams.ts +++ b/x-pack/test_serverless/functional/test_suites/common/management/index_management/data_streams.ts @@ -88,7 +88,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { it('shows the details flyout when clicking on a data stream', async () => { // Open details flyout - await pageObjects.indexManagement.clickDataStreamAt(0); + await pageObjects.indexManagement.clickDataStreamNameLink(TEST_DS_NAME); // Verify url is stateful const url = await browser.getCurrentUrl(); expect(url).to.contain(`/data_streams/${TEST_DS_NAME}`); @@ -100,7 +100,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { it('allows to update data retention', async () => { // Open details flyout - await pageObjects.indexManagement.clickDataStreamAt(0); + await pageObjects.indexManagement.clickDataStreamNameLink(TEST_DS_NAME); // Open the edit retention dialog await testSubjects.click('manageDataStreamButton'); await testSubjects.click('editDataRetentionButton'); @@ -122,7 +122,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { it('allows to disable data retention', async () => { // Open details flyout - await pageObjects.indexManagement.clickDataStreamAt(0); + await pageObjects.indexManagement.clickDataStreamNameLink(TEST_DS_NAME); // Open the edit retention dialog await testSubjects.click('manageDataStreamButton'); await testSubjects.click('editDataRetentionButton'); diff --git a/x-pack/test_serverless/functional/test_suites/common/management/index_management/index.ts b/x-pack/test_serverless/functional/test_suites/common/management/index_management/index.ts new file mode 100644 index 000000000000..0df628a2ba58 --- /dev/null +++ b/x-pack/test_serverless/functional/test_suites/common/management/index_management/index.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 { FtrProviderContext } from '../../../../ftr_provider_context'; + +export default ({ loadTestFile }: FtrProviderContext) => { + describe('Index Management', function () { + loadTestFile(require.resolve('./component_templates')); + loadTestFile(require.resolve('./create_enrich_policy')); + loadTestFile(require.resolve('./data_streams')); + loadTestFile(require.resolve('./enrich_policies')); + loadTestFile(require.resolve('./index_templates')); + loadTestFile(require.resolve('./indices')); + }); +}; From 46a58541fa8ce21f86a32408cbc759c1bf22487b Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Thu, 4 Jan 2024 14:51:46 -0500 Subject: [PATCH 18/57] skip failing test suite (#173558) --- .../common/management/data_views/_runtime_fields.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test_serverless/functional/test_suites/common/management/data_views/_runtime_fields.ts b/x-pack/test_serverless/functional/test_suites/common/management/data_views/_runtime_fields.ts index f900329539e6..b7bc99d9aecb 100644 --- a/x-pack/test_serverless/functional/test_suites/common/management/data_views/_runtime_fields.ts +++ b/x-pack/test_serverless/functional/test_suites/common/management/data_views/_runtime_fields.ts @@ -16,7 +16,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects(['settings', 'common']); const testSubjects = getService('testSubjects'); - describe('runtime fields', function () { + // Failing: See https://github.com/elastic/kibana/issues/173558 + describe.skip('runtime fields', function () { this.tags(['skipFirefox']); before(async function () { From 133016850fabf44f3f527496a67eab5d102443b4 Mon Sep 17 00:00:00 2001 From: Hannah Mudge Date: Thu, 4 Jan 2024 14:39:44 -0700 Subject: [PATCH 19/57] [Dashboard Usability] Conditionally auto focus on title input in panel settings flyout (#173777) Closes https://github.com/elastic/kibana/issues/170786 ## Summary Currently, in order to change a panel title, the most efficient way to do this (assuming the dashboard is already in edit mode) is to click on the panel title -> click on the title input in the flyout -> click save at the bottom of the flyout. Notice that this process currently takes **three** clicks, which can start to add up if you need to change multiple titles in one session - so, in order to remove one click from this process, I've made it so that the title input is **auto focused** on when opening the settings flyout through the panel title (and not when it is opened from the context menu). > [!NOTE] > I chose to make this auto-focus behaviour conditional on how the flyout was opened because, from an a11y perspective, it can be jarring to have your focus taken out of the natural element order (as noted in the [EUI docs](https://eui.elastic.co/#/layout/popover#setting-an-initial-focus)). It feels natural that, in order to change the panel title, you click on it - so, auto focusing on the title input makes sense, even when using keyboard controls. However, if you are opening the settings flyout via the context menu, it is **less likely** that the goal is to change the title - so, forcing the focus could feel unnatural in this case. I added tests for this new auto focus behaviour and, since I was interested in learning a bit more about RTL, I also added a few other tests for the dashboard panel components. As part of this, I migrated a few functional tests to unit tests, since this is a faster and more reliable way to test certain rendering conditionals. ### Video https://github.com/elastic/kibana/assets/8698078/229c1303-c81d-46b8-a567-76885361d9fa ### Checklist - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [x] Any UI touched in this PR is usable by keyboard only (learn more about [keyboard accessibility](https://webaim.org/techniques/keyboard/)) - [x] Any UI touched in this PR does not create any new axe failures (run axe in browser: [FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/), [Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US)) - [x] This was checked for [cross-browser compatibility](https://www.elastic.co/support/matrix#matrix_browsers) ### For maintainers - [ ] This was checked for breaking API changes and was [labeled appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../embeddable_panel/embeddable_panel.tsx | 29 +-- .../can_inherit_time_range.ts | 2 +- .../custom_time_range_badge.test.ts | 31 +-- .../custom_time_range_badge.tsx | 12 +- .../customize_panel_action.test.ts | 15 +- .../customize_panel_action.tsx | 114 +--------- .../customize_panel_editor.test.tsx | 200 ++++++++++++++++++ .../customize_panel_editor.tsx | 55 +++-- .../does_inherit_time_range.ts | 4 +- .../filters_details.tsx | 3 + .../open_customize_panel.tsx | 75 +++++++ .../time_range_helpers.ts | 53 +++++ .../embeddable_panel_header.test.tsx | 171 +++++++++++++++ .../panel_header/embeddable_panel_header.tsx | 4 +- .../panel_header/embeddable_panel_title.tsx | 29 ++- src/plugins/embeddable/public/plugin.tsx | 11 +- src/plugins/embeddable/tsconfig.json | 3 +- .../apps/dashboard/group2/panel_time_range.ts | 15 -- .../apps/dashboard/group2/panel_titles.ts | 38 ---- 19 files changed, 601 insertions(+), 263 deletions(-) create mode 100644 src/plugins/embeddable/public/embeddable_panel/panel_actions/customize_panel_action/customize_panel_editor.test.tsx create mode 100644 src/plugins/embeddable/public/embeddable_panel/panel_actions/customize_panel_action/open_customize_panel.tsx create mode 100644 src/plugins/embeddable/public/embeddable_panel/panel_actions/customize_panel_action/time_range_helpers.ts create mode 100644 src/plugins/embeddable/public/embeddable_panel/panel_header/embeddable_panel_header.test.tsx diff --git a/src/plugins/embeddable/public/embeddable_panel/embeddable_panel.tsx b/src/plugins/embeddable/public/embeddable_panel/embeddable_panel.tsx index c24383ff9fb1..134b65efc9d8 100644 --- a/src/plugins/embeddable/public/embeddable_panel/embeddable_panel.tsx +++ b/src/plugins/embeddable/public/embeddable_panel/embeddable_panel.tsx @@ -6,20 +6,23 @@ * Side Public License, v 1. */ -import { isNil } from 'lodash'; +import { EuiFlexGroup, EuiFlexItem, EuiPanel, htmlIdGenerator } from '@elastic/eui'; import classNames from 'classnames'; -import { distinct, map } from 'rxjs'; +import { isNil } from 'lodash'; import React, { ReactNode, useEffect, useMemo, useState } from 'react'; -import { EuiFlexGroup, EuiFlexItem, EuiPanel, htmlIdGenerator } from '@elastic/eui'; +import { distinct, map } from 'rxjs'; -import { UI_SETTINGS } from '@kbn/data-plugin/common'; import { PanelLoader } from '@kbn/panel-loader'; +import { core, embeddableStart, inspector } from '../kibana_services'; +import { EmbeddableErrorHandler, EmbeddableOutput, ViewMode } from '../lib'; +import { EmbeddablePanelError } from './embeddable_panel_error'; import { + CustomizePanelAction, EditPanelAction, - RemovePanelAction, InspectPanelAction, - CustomizePanelAction, + RemovePanelAction, } from './panel_actions'; +import { EmbeddablePanelHeader } from './panel_header/embeddable_panel_header'; import { EmbeddablePhase, EmbeddablePhaseEvent, @@ -30,10 +33,6 @@ import { useSelectFromEmbeddableInput, useSelectFromEmbeddableOutput, } from './use_select_from_embeddable'; -import { EmbeddablePanelError } from './embeddable_panel_error'; -import { core, embeddableStart, inspector } from '../kibana_services'; -import { ViewMode, EmbeddableErrorHandler, EmbeddableOutput } from '../lib'; -import { EmbeddablePanelHeader } from './panel_header/embeddable_panel_header'; const getEventStatus = (output: EmbeddableOutput): EmbeddablePhase => { if (!isNil(output.error)) { @@ -61,8 +60,6 @@ export const EmbeddablePanel = (panelProps: UnwrappedEmbeddablePanelProps) => { * bypass the trigger registry. */ const universalActions = useMemo(() => { - const commonlyUsedRanges = core.uiSettings.get(UI_SETTINGS.TIMEPICKER_QUICK_RANGES); - const dateFormat = core.uiSettings.get(UI_SETTINGS.DATE_FORMAT); const stateTransfer = embeddableStart.getStateTransfer(); const editPanel = new EditPanelAction( embeddableStart.getEmbeddableFactory, @@ -71,13 +68,7 @@ export const EmbeddablePanel = (panelProps: UnwrappedEmbeddablePanelProps) => { ); const actions: PanelUniversalActions = { - customizePanel: new CustomizePanelAction( - core.overlays, - core.theme, - editPanel, - commonlyUsedRanges, - dateFormat - ), + customizePanel: new CustomizePanelAction(editPanel), removePanel: new RemovePanelAction(), editPanel, }; diff --git a/src/plugins/embeddable/public/embeddable_panel/panel_actions/customize_panel_action/can_inherit_time_range.ts b/src/plugins/embeddable/public/embeddable_panel/panel_actions/customize_panel_action/can_inherit_time_range.ts index 139933c8d939..f2c1a3b7a9aa 100644 --- a/src/plugins/embeddable/public/embeddable_panel/panel_actions/customize_panel_action/can_inherit_time_range.ts +++ b/src/plugins/embeddable/public/embeddable_panel/panel_actions/customize_panel_action/can_inherit_time_range.ts @@ -8,8 +8,8 @@ import type { TimeRange } from '@kbn/es-query'; -import { TimeRangeInput } from './customize_panel_action'; import { Embeddable, IContainer, ContainerInput } from '../../..'; +import { TimeRangeInput } from './time_range_helpers'; interface ContainerTimeRangeInput extends ContainerInput { timeRange: TimeRange; diff --git a/src/plugins/embeddable/public/embeddable_panel/panel_actions/customize_panel_action/custom_time_range_badge.test.ts b/src/plugins/embeddable/public/embeddable_panel/panel_actions/customize_panel_action/custom_time_range_badge.test.ts index 454c92a60269..1c1b7226b7f3 100644 --- a/src/plugins/embeddable/public/embeddable_panel/panel_actions/customize_panel_action/custom_time_range_badge.test.ts +++ b/src/plugins/embeddable/public/embeddable_panel/panel_actions/customize_panel_action/custom_time_range_badge.test.ts @@ -6,16 +6,13 @@ * Side Public License, v 1. */ -import { themeServiceMock } from '@kbn/core-theme-browser-mocks'; -import { overlayServiceMock } from '@kbn/core-overlays-browser-mocks'; - import { - TimeRangeEmbeddable, TimeRangeContainer, + TimeRangeEmbeddable, TIME_RANGE_EMBEDDABLE, } from '../../../lib/test_samples/embeddables'; -import { CustomTimeRangeBadge } from './custom_time_range_badge'; import { EditPanelAction } from '../edit_panel_action/edit_panel_action'; +import { CustomTimeRangeBadge } from './custom_time_range_badge'; const editPanelAction = { execute: jest.fn(), @@ -42,13 +39,7 @@ test(`badge is not compatible with embeddable that inherits from parent`, async const child = container.getChild('1'); - const compatible = await new CustomTimeRangeBadge( - overlayServiceMock.createStartContract(), - themeServiceMock.createStartContract(), - editPanelAction, - [], - 'MM YYYY' - ).isCompatible({ + const compatible = await new CustomTimeRangeBadge(editPanelAction, 'MM YYYY').isCompatible({ embeddable: child, }); expect(compatible).toBe(false); @@ -76,13 +67,7 @@ test(`badge is compatible with embeddable that has custom time range`, async () const child = container.getChild('1'); - const compatible = await new CustomTimeRangeBadge( - overlayServiceMock.createStartContract(), - themeServiceMock.createStartContract(), - editPanelAction, - [], - 'MM YYYY' - ).isCompatible({ + const compatible = await new CustomTimeRangeBadge(editPanelAction, 'MM YYYY').isCompatible({ embeddable: child, }); expect(compatible).toBe(true); @@ -109,13 +94,7 @@ test('Attempting to execute on incompatible embeddable throws an error', async ( const child = container.getChild('1'); - const badge = await new CustomTimeRangeBadge( - overlayServiceMock.createStartContract(), - themeServiceMock.createStartContract(), - editPanelAction, - [], - 'MM YYYY' - ); + const badge = await new CustomTimeRangeBadge(editPanelAction, 'MM YYYY'); async function check() { await badge.execute({ embeddable: child }); diff --git a/src/plugins/embeddable/public/embeddable_panel/panel_actions/customize_panel_action/custom_time_range_badge.tsx b/src/plugins/embeddable/public/embeddable_panel/panel_actions/customize_panel_action/custom_time_range_badge.tsx index 08e864b76b1a..5866c3b5ec19 100644 --- a/src/plugins/embeddable/public/embeddable_panel/panel_actions/customize_panel_action/custom_time_range_badge.tsx +++ b/src/plugins/embeddable/public/embeddable_panel/panel_actions/customize_panel_action/custom_time_range_badge.tsx @@ -11,9 +11,10 @@ import { PrettyDuration } from '@elastic/eui'; import { renderToString } from 'react-dom/server'; import { Action } from '@kbn/ui-actions-plugin/public'; -import { Embeddable } from '../../..'; +import { EditPanelAction, Embeddable } from '../../..'; import { doesInheritTimeRange } from './does_inherit_time_range'; -import { TimeRangeInput, hasTimeRange, CustomizePanelAction } from './customize_panel_action'; +import { CustomizePanelAction } from './customize_panel_action'; +import { hasTimeRange, TimeRangeInput } from './time_range_helpers'; export const CUSTOM_TIME_RANGE_BADGE = 'CUSTOM_TIME_RANGE_BADGE'; @@ -29,6 +30,13 @@ export class CustomTimeRangeBadge public readonly id = CUSTOM_TIME_RANGE_BADGE; public order = 7; + constructor( + protected readonly editPanel: EditPanelAction, + protected readonly dateFormat?: string + ) { + super(editPanel); + } + public getDisplayName({ embeddable }: TimeBadgeActionContext) { return renderToString( { }); test('execute should open flyout', async () => { - const customizePanelAction = new CustomizePanelAction(overlays, theme, editPanelActionMock); - const spy = jest.spyOn(overlays, 'openFlyout'); - await customizePanelAction.execute({ embeddable }); + const customizePanelAction = new CustomizePanelAction(editPanelActionMock); + const spy = jest.spyOn(openCustomizePanel, 'openCustomizePanelFlyout'); + await customizePanelAction.execute({ embeddable }); expect(spy).toHaveBeenCalled(); }); diff --git a/src/plugins/embeddable/public/embeddable_panel/panel_actions/customize_panel_action/customize_panel_action.tsx b/src/plugins/embeddable/public/embeddable_panel/panel_actions/customize_panel_action/customize_panel_action.tsx index 63fc1902102b..7f70ecf51aca 100644 --- a/src/plugins/embeddable/public/embeddable_panel/panel_actions/customize_panel_action/customize_panel_action.tsx +++ b/src/plugins/embeddable/public/embeddable_panel/panel_actions/customize_panel_action/customize_panel_action.tsx @@ -6,48 +6,16 @@ * Side Public License, v 1. */ -import React from 'react'; import { i18n } from '@kbn/i18n'; -import { TimeRange } from '@kbn/es-query'; -import { createKibanaReactContext } from '@kbn/kibana-react-plugin/public'; -import { OverlayStart, ThemeServiceStart } from '@kbn/core/public'; -import { toMountPoint } from '@kbn/react-kibana-mount'; import { Action, IncompatibleActionError } from '@kbn/ui-actions-plugin/public'; -import { core } from '../../../kibana_services'; -import { - IEmbeddable, - Embeddable, - EmbeddableInput, - EmbeddableOutput, - EditPanelAction, -} from '../../..'; -import { ViewMode, CommonlyUsedRange } from '../../../lib/types'; -import { tracksOverlays } from '../track_overlays'; -import { CustomizePanelEditor } from './customize_panel_editor'; +import { EditPanelAction, Embeddable, IEmbeddable } from '../../..'; +import { ViewMode } from '../../../lib/types'; +import { openCustomizePanelFlyout } from './open_customize_panel'; +import { isTimeRangeCompatible, TimeRangeInput } from './time_range_helpers'; export const ACTION_CUSTOMIZE_PANEL = 'ACTION_CUSTOMIZE_PANEL'; -const VISUALIZE_EMBEDDABLE_TYPE = 'visualization'; - -type VisualizeEmbeddable = IEmbeddable<{ id: string }, EmbeddableOutput & { visTypeName: string }>; - -function isVisualizeEmbeddable( - embeddable: IEmbeddable | VisualizeEmbeddable -): embeddable is VisualizeEmbeddable { - return embeddable.type === VISUALIZE_EMBEDDABLE_TYPE; -} - -export interface TimeRangeInput extends EmbeddableInput { - timeRange: TimeRange; -} - -export function hasTimeRange( - embeddable: IEmbeddable | Embeddable -): embeddable is Embeddable { - return (embeddable as Embeddable).getInput().timeRange !== undefined; -} - export interface CustomizePanelActionContext { embeddable: IEmbeddable | Embeddable; } @@ -57,35 +25,7 @@ export class CustomizePanelAction implements Action public id = ACTION_CUSTOMIZE_PANEL; public order = 40; - constructor( - protected readonly overlays: OverlayStart, - protected readonly theme: ThemeServiceStart, - protected readonly editPanel: EditPanelAction, - protected readonly commonlyUsedRanges?: CommonlyUsedRange[], - protected readonly dateFormat?: string - ) {} - - protected isTimeRangeCompatible({ embeddable }: CustomizePanelActionContext): boolean { - const isInputControl = - isVisualizeEmbeddable(embeddable) && - (embeddable as VisualizeEmbeddable).getOutput().visTypeName === 'input_control_vis'; - - const isMarkdown = - isVisualizeEmbeddable(embeddable) && - (embeddable as VisualizeEmbeddable).getOutput().visTypeName === 'markdown'; - - const isImage = embeddable.type === 'image'; - const isNavigation = embeddable.type === 'navigation'; - - return Boolean( - embeddable && - hasTimeRange(embeddable) && - !isInputControl && - !isMarkdown && - !isImage && - !isNavigation - ); - } + constructor(protected readonly editPanel: EditPanelAction) {} public getDisplayName({ embeddable }: CustomizePanelActionContext): string { return i18n.translate('embeddableApi.customizePanel.action.displayName', { @@ -100,7 +40,7 @@ export class CustomizePanelAction implements Action public async isCompatible({ embeddable }: CustomizePanelActionContext) { // It should be possible to customize just the time range in View mode return ( - embeddable.getInput().viewMode === ViewMode.EDIT || this.isTimeRangeCompatible({ embeddable }) + embeddable.getInput().viewMode === ViewMode.EDIT || isTimeRangeCompatible({ embeddable }) ); } @@ -109,46 +49,6 @@ export class CustomizePanelAction implements Action if (!isCompatible) { throw new IncompatibleActionError(); } - - // send the overlay ref to the root embeddable if it is capable of tracking overlays - const rootEmbeddable = embeddable.getRoot(); - const overlayTracker = tracksOverlays(rootEmbeddable) ? rootEmbeddable : undefined; - - const { Provider: KibanaReactContextProvider } = createKibanaReactContext({ - uiSettings: core.uiSettings, - }); - - const onEdit = () => { - this.editPanel.execute({ embeddable }); - }; - - const handle = this.overlays.openFlyout( - toMountPoint( - - { - if (overlayTracker) overlayTracker.clearOverlays(); - handle.close(); - }} - onEdit={onEdit} - /> - , - { theme: this.theme, i18n: core.i18n } - ), - { - size: 's', - 'data-test-subj': 'customizePanel', - onClose: (overlayRef) => { - if (overlayTracker) overlayTracker.clearOverlays(); - overlayRef.close(); - }, - maxWidth: true, - } - ); - overlayTracker?.openOverlay(handle); + openCustomizePanelFlyout({ editPanel: this.editPanel, embeddable }); } } diff --git a/src/plugins/embeddable/public/embeddable_panel/panel_actions/customize_panel_action/customize_panel_editor.test.tsx b/src/plugins/embeddable/public/embeddable_panel/panel_actions/customize_panel_action/customize_panel_editor.test.tsx new file mode 100644 index 000000000000..a2ccf9782deb --- /dev/null +++ b/src/plugins/embeddable/public/embeddable_panel/panel_actions/customize_panel_action/customize_panel_editor.test.tsx @@ -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 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 { __IntlProvider as IntlProvider } from '@kbn/i18n-react'; +import '@testing-library/jest-dom'; +import { render, screen, waitFor } from '@testing-library/react'; + +import { Filter } from '@kbn/es-query'; +import { ViewMode } from '../../../../common'; +import { FilterableEmbeddable, IEmbeddable } from '../../../lib'; +import { + ContactCardEmbeddable, + ContactCardEmbeddableFactory, + ContactCardEmbeddableInput, +} from '../../../lib/test_samples'; +import { EditPanelAction } from '../edit_panel_action/edit_panel_action'; +import { CustomizePanelAction } from './customize_panel_action'; +import { CustomizePanelEditor } from './customize_panel_editor'; + +const editPanelActionMock = { execute: jest.fn() } as unknown as EditPanelAction; + +const mockEmbeddableFactory = new ContactCardEmbeddableFactory((() => null) as any, {} as any); +const customizePanelAction = new CustomizePanelAction(editPanelActionMock); +customizePanelAction.execute = jest.fn(); + +const DEFAULT_PANEL_TITLE = 'Panel title'; + +const createEmbeddable = async ( + initialInput?: Partial +): Promise => { + return await mockEmbeddableFactory.create({ + id: '20', + firstName: 'Bilbo', + lastName: 'Baggins', + title: DEFAULT_PANEL_TITLE, + ...initialInput, + }); +}; + +const DEFAULT_PROPS = { + timeRangeCompatible: true, + onClose: jest.fn(), + onEdit: jest.fn(), +}; + +describe('panel title / description', () => { + test('does not render if in view mode', async () => { + const mockEmbeddable = await createEmbeddable({ viewMode: ViewMode.VIEW }); + render( + + + + ); + + const customizePanelForm = await screen.findByTestId('customizePanelForm'); + const titleDescriptionComponent = screen.queryByTestId('customEmbeddableTitleComponent'); + expect(customizePanelForm).not.toContainElement(titleDescriptionComponent); + }); + + test('title input receives focus when `focusOnTitle` is `true`', async () => { + const mockEmbeddable = await createEmbeddable({ viewMode: ViewMode.EDIT }); + render( + + + + ); + + const customTitleComponent = await screen.findByTestId('customEmbeddablePanelTitleInput'); + expect(customTitleComponent).toHaveFocus(); + }); + + test('title input does not receive focus when `focusOnTitle` is `false`', async () => { + const mockEmbeddable = await createEmbeddable({ viewMode: ViewMode.EDIT }); + render( + + + + ); + + const customTitleComponent = await screen.findByTestId('customEmbeddablePanelTitleInput'); + expect(customTitleComponent).not.toHaveFocus(); + }); +}); + +describe('custom time picker', () => { + test('renders custom time picker if embeddable supports it', async () => { + const mockEmbeddable = await createEmbeddable({ viewMode: ViewMode.EDIT }); + render( + + + + ); + + const customTimeRangeComponent = await screen.findByTestId('customizePanelTimeRangeDatePicker'); + expect(customTimeRangeComponent).toBeDefined(); + }); + + test('does not render custom time picker if embeddable does not support it', async () => { + const mockEmbeddable = await createEmbeddable({ viewMode: ViewMode.EDIT }); + render( + + + + ); + + const customizePanelForm = await screen.findByTestId('customizePanelForm'); + const customTimeRangeComponent = screen.queryByTestId('customizePanelTimeRangeDatePicker'); + expect(customizePanelForm).not.toContainElement(customTimeRangeComponent); + }); + + test('does not render filters and/or query info if embeddable does not support it', async () => { + const mockEmbeddable = await createEmbeddable({ + viewMode: ViewMode.EDIT, + }); + + render( + + + + ); + + const customizePanelForm = await screen.findByTestId('customizePanelForm'); + const customPanelQuery = screen.queryByTestId('panelCustomQueryRow'); + expect(customizePanelForm).not.toContainElement(customPanelQuery); + const customPanelFilters = screen.queryByTestId('panelCustomFiltersRow'); + expect(customizePanelForm).not.toContainElement(customPanelFilters); + }); + + describe('filterable embeddable', () => { + test('renders custom filters, if provided', async () => { + const mockEmbeddable: FilterableEmbeddable = (await createEmbeddable({ + viewMode: ViewMode.EDIT, + })) as unknown as FilterableEmbeddable; + + mockEmbeddable.getFilters = jest.fn().mockResolvedValue([ + { + meta: {}, + query: {}, + $state: {}, + }, + ] as Filter[]); + mockEmbeddable.getQuery = jest.fn().mockResolvedValue({}); + render( + + + + ); + await waitFor(() => { + expect(screen.getByTestId('euiSkeletonLoadingAriaWrapper')).toBeInTheDocument(); + }); + const customPanelQuery = await screen.findByTestId('panelCustomFiltersRow'); + expect(customPanelQuery).toBeInTheDocument(); + }); + + test('renders a custom query, if provided', async () => { + const mockEmbeddable: FilterableEmbeddable = (await createEmbeddable({ + viewMode: ViewMode.EDIT, + })) as unknown as FilterableEmbeddable; + mockEmbeddable.getFilters = jest.fn().mockResolvedValue([]); + mockEmbeddable.getQuery = jest.fn().mockResolvedValue({ query: 'field : value' }); + render( + + + + ); + await waitFor(() => { + expect(screen.getByTestId('euiSkeletonLoadingAriaWrapper')).toBeInTheDocument(); + }); + const customPanelQuery = await screen.findByTestId('customPanelQuery'); + expect(customPanelQuery).toHaveTextContent('field : value'); + }); + }); +}); diff --git a/src/plugins/embeddable/public/embeddable_panel/panel_actions/customize_panel_action/customize_panel_editor.tsx b/src/plugins/embeddable/public/embeddable_panel/panel_actions/customize_panel_action/customize_panel_editor.tsx index be1e7df0c105..9893e016af08 100644 --- a/src/plugins/embeddable/public/embeddable_panel/panel_actions/customize_panel_action/customize_panel_editor.tsx +++ b/src/plugins/embeddable/public/embeddable_panel/panel_actions/customize_panel_action/customize_panel_editor.tsx @@ -6,40 +6,40 @@ * Side Public License, v 1. */ -import React, { useState } from 'react'; +import React, { useEffect, useRef, useState } from 'react'; import { - EuiFormRow, - EuiFieldText, - EuiSwitch, - EuiFlyoutHeader, - EuiTitle, - EuiFlyoutBody, - EuiForm, - EuiTextArea, - EuiFlyoutFooter, - EuiButtonEmpty, EuiButton, + EuiButtonEmpty, + EuiFieldText, EuiFlexGroup, EuiFlexItem, - EuiSuperDatePicker, + EuiFlyoutBody, + EuiFlyoutFooter, + EuiFlyoutHeader, + EuiForm, + EuiFormRow, EuiSpacer, + EuiSuperDatePicker, + EuiSwitch, + EuiTextArea, + EuiTitle, } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; import { TimeRange } from '@kbn/es-query'; +import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; -import { TimeRangeInput } from './customize_panel_action'; -import { canInheritTimeRange } from './can_inherit_time_range'; -import { doesInheritTimeRange } from './does_inherit_time_range'; import { - IEmbeddable, - Embeddable, CommonlyUsedRange, - ViewMode, + Embeddable, + IEmbeddable, isFilterableEmbeddable, + ViewMode, } from '../../../lib'; +import { canInheritTimeRange } from './can_inherit_time_range'; +import { doesInheritTimeRange } from './does_inherit_time_range'; import { FiltersDetails } from './filters_details'; +import { TimeRangeInput } from './time_range_helpers'; type PanelSettings = { title?: string; @@ -55,10 +55,11 @@ interface CustomizePanelProps { commonlyUsedRanges?: CommonlyUsedRange[]; onClose: () => void; onEdit: () => void; + focusOnTitle?: boolean; } export const CustomizePanelEditor = (props: CustomizePanelProps) => { - const { onClose, embeddable, dateFormat, timeRangeCompatible, onEdit } = props; + const { onClose, embeddable, dateFormat, timeRangeCompatible, onEdit, focusOnTitle } = props; const editMode = embeddable.getInput().viewMode === ViewMode.EDIT; const [hideTitle, setHideTitle] = useState(embeddable.getInput().hidePanelTitles); const [panelDescription, setPanelDescription] = useState( @@ -75,6 +76,13 @@ export const CustomizePanelEditor = (props: CustomizePanelProps) => { ? (embeddable as Embeddable).getInput().timeRange : undefined ); + const initialFocusRef = useRef(null); + + useEffect(() => { + if (focusOnTitle && initialFocusRef.current) { + initialFocusRef.current.focus(); + } + }, [initialFocusRef, focusOnTitle]); const commonlyUsedRangesForDatePicker = props.commonlyUsedRanges ? props.commonlyUsedRanges.map( @@ -108,7 +116,7 @@ export const CustomizePanelEditor = (props: CustomizePanelProps) => { if (!editMode) return null; return ( - <> +

    { } > { )} /> - +
    ); }; @@ -292,7 +301,7 @@ export const CustomizePanelEditor = (props: CustomizePanelProps) => { - + {renderCustomTitleComponent()} {renderCustomTimeRangeComponent()} {renderFilterDetails()} diff --git a/src/plugins/embeddable/public/embeddable_panel/panel_actions/customize_panel_action/does_inherit_time_range.ts b/src/plugins/embeddable/public/embeddable_panel/panel_actions/customize_panel_action/does_inherit_time_range.ts index a14ca031c9fb..7d21a79ab942 100644 --- a/src/plugins/embeddable/public/embeddable_panel/panel_actions/customize_panel_action/does_inherit_time_range.ts +++ b/src/plugins/embeddable/public/embeddable_panel/panel_actions/customize_panel_action/does_inherit_time_range.ts @@ -6,8 +6,8 @@ * Side Public License, v 1. */ -import { Embeddable, IContainer, ContainerInput } from '../../../lib'; -import { TimeRangeInput } from './customize_panel_action'; +import { ContainerInput, Embeddable, IContainer } from '../../../lib'; +import { TimeRangeInput } from './time_range_helpers'; export function doesInheritTimeRange(embeddable: Embeddable) { if (!embeddable.parent) { diff --git a/src/plugins/embeddable/public/embeddable_panel/panel_actions/customize_panel_action/filters_details.tsx b/src/plugins/embeddable/public/embeddable_panel/panel_actions/customize_panel_action/filters_details.tsx index 2f151285fe48..300ed9253f0b 100644 --- a/src/plugins/embeddable/public/embeddable_panel/panel_actions/customize_panel_action/filters_details.tsx +++ b/src/plugins/embeddable/public/embeddable_panel/panel_actions/customize_panel_action/filters_details.tsx @@ -89,6 +89,7 @@ export function FiltersDetails({ embeddable, editMode, onEdit }: FiltersDetailsP {queryString !== '' && ( 0 && ( ; +}) => { + // send the overlay ref to the root embeddable if it is capable of tracking overlays + const rootEmbeddable = embeddable.getRoot(); + const overlayTracker = tracksOverlays(rootEmbeddable) ? rootEmbeddable : undefined; + + const commonlyUsedRanges = core.uiSettings.get(UI_SETTINGS.TIMEPICKER_QUICK_RANGES); + const dateFormat = core.uiSettings.get(UI_SETTINGS.DATE_FORMAT); + + const { Provider: KibanaReactContextProvider } = createKibanaReactContext({ + uiSettings: core.uiSettings, + }); + + const onEdit = () => { + editPanel.execute({ embeddable }); + }; + + const handle = core.overlays.openFlyout( + toMountPoint( + + { + if (overlayTracker) overlayTracker.clearOverlays(); + handle.close(); + }} + onEdit={onEdit} + /> + , + { theme: core.theme, i18n: core.i18n } + ), + { + size: 's', + 'data-test-subj': 'customizePanel', + onClose: (overlayRef) => { + if (overlayTracker) overlayTracker.clearOverlays(); + overlayRef.close(); + }, + maxWidth: true, + } + ); + overlayTracker?.openOverlay(handle); +}; diff --git a/src/plugins/embeddable/public/embeddable_panel/panel_actions/customize_panel_action/time_range_helpers.ts b/src/plugins/embeddable/public/embeddable_panel/panel_actions/customize_panel_action/time_range_helpers.ts new file mode 100644 index 000000000000..0b74809be8a0 --- /dev/null +++ b/src/plugins/embeddable/public/embeddable_panel/panel_actions/customize_panel_action/time_range_helpers.ts @@ -0,0 +1,53 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 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 { TimeRange } from '@kbn/es-query'; + +import { Embeddable, EmbeddableInput, EmbeddableOutput, IEmbeddable } from '../../../lib'; + +const VISUALIZE_EMBEDDABLE_TYPE = 'visualization'; + +type VisualizeEmbeddable = IEmbeddable<{ id: string }, EmbeddableOutput & { visTypeName: string }>; + +function isVisualizeEmbeddable( + embeddable: IEmbeddable | VisualizeEmbeddable +): embeddable is VisualizeEmbeddable { + return embeddable.type === VISUALIZE_EMBEDDABLE_TYPE; +} + +export interface TimeRangeInput extends EmbeddableInput { + timeRange: TimeRange; +} + +export function hasTimeRange( + embeddable: IEmbeddable | Embeddable +): embeddable is Embeddable { + return (embeddable as Embeddable).getInput().timeRange !== undefined; +} + +export function isTimeRangeCompatible({ embeddable }: { embeddable: IEmbeddable }): boolean { + const isInputControl = + isVisualizeEmbeddable(embeddable) && + (embeddable as VisualizeEmbeddable).getOutput().visTypeName === 'input_control_vis'; + + const isMarkdown = + isVisualizeEmbeddable(embeddable) && + (embeddable as VisualizeEmbeddable).getOutput().visTypeName === 'markdown'; + + const isImage = embeddable.type === 'image'; + const isNavigation = embeddable.type === 'navigation'; + + return Boolean( + embeddable && + hasTimeRange(embeddable) && + !isInputControl && + !isMarkdown && + !isImage && + !isNavigation + ); +} diff --git a/src/plugins/embeddable/public/embeddable_panel/panel_header/embeddable_panel_header.test.tsx b/src/plugins/embeddable/public/embeddable_panel/panel_header/embeddable_panel_header.test.tsx new file mode 100644 index 000000000000..770ca76edbc3 --- /dev/null +++ b/src/plugins/embeddable/public/embeddable_panel/panel_header/embeddable_panel_header.test.tsx @@ -0,0 +1,171 @@ +/* + * 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 '@testing-library/jest-dom'; +import { render, screen } from '@testing-library/react'; + +import { applicationServiceMock } from '@kbn/core-application-browser-mocks'; +import userEvent from '@testing-library/user-event'; +import { ViewMode } from '../../../common'; +import { + ContactCardEmbeddable, + ContactCardEmbeddableFactory, + ContactCardEmbeddableInput, +} from '../../lib/test_samples'; +import { EditPanelAction } from '../panel_actions'; +import * as openCustomizePanel from '../panel_actions/customize_panel_action/open_customize_panel'; +import { EmbeddablePanelHeader } from './embeddable_panel_header'; + +const getEmbeddableFactory = jest.fn(); +const application = applicationServiceMock.createStartContract(); + +const editPanelAction = new EditPanelAction(getEmbeddableFactory, application); +const mockEmbeddableFactory = new ContactCardEmbeddableFactory((() => null) as any, {} as any); +editPanelAction.execute = jest.fn(); + +const DEFAULT_PANEL_TITLE = 'Panel title'; + +const createEmbeddable = async ( + initialInput?: Partial +): Promise => { + return await mockEmbeddableFactory.create({ + id: '20', + firstName: 'Bilbo', + lastName: 'Baggins', + title: DEFAULT_PANEL_TITLE, + ...initialInput, + }); +}; + +describe('view mode', () => { + test('renders as expected', async () => { + const mockEmbeddable = await createEmbeddable({ viewMode: ViewMode.VIEW }); + render( + + ); + const titleComponent = await screen.findByTestId('dashboardPanelTitle'); + expect(titleComponent).toHaveTextContent(DEFAULT_PANEL_TITLE); + }); + + test('renders tooltip + icon when description provided', async () => { + const mockEmbeddable = await createEmbeddable({ viewMode: ViewMode.VIEW }); + mockEmbeddable.updateOutput({ description: 'This is a description ' }); + render( + + ); + + expect(await screen.findByTestId('embeddablePanelTooltipAnchor')).toBeInTheDocument(); + expect(await screen.findByTestId('embeddablePanelTitleDescriptionIcon')).toBeInTheDocument(); + }); + + test('blank titles are hidden in view mode', async () => { + const mockEmbeddable = await createEmbeddable({ title: '', viewMode: ViewMode.VIEW }); + render( + + ); + + const header = await screen.findByTestId('embeddablePanelHeading'); + const titleComponent = screen.queryByTestId('dashboardPanelTitle'); + expect(header).not.toContainElement(titleComponent); + }); + + test('hiding an individual panel title hides it in view mode', async () => { + const mockEmbeddable = await createEmbeddable({ + viewMode: ViewMode.VIEW, + hidePanelTitles: true, + }); + render( + + ); + + const header = await screen.findByTestId('embeddablePanelHeading'); + const titleComponent = screen.queryByTestId('dashboardPanelTitle'); + expect(header).not.toContainElement(titleComponent); + }); +}); + +describe('edit mode', () => { + test('renders as expected', async () => { + const mockEmbeddable = await createEmbeddable({ viewMode: ViewMode.EDIT }); + render( + + ); + const titleComponent = await screen.findByTestId('dashboardPanelTitle'); + expect(titleComponent).toHaveTextContent(DEFAULT_PANEL_TITLE); + }); + + test('blank titles render [No title] in edit mode', async () => { + const mockEmbeddable = await createEmbeddable({ title: '', viewMode: ViewMode.EDIT }); + render( + + ); + const titleComponent = await screen.findByTestId('embeddablePanelTitleInner'); + expect(titleComponent).toHaveTextContent('[No Title]'); + }); + + test('hiding an individual panel title renders **only** the context menu button in edit mode', async () => { + const mockEmbeddable = await createEmbeddable({ + viewMode: ViewMode.EDIT, + hidePanelTitles: true, + }); + render( + + ); + const titleComponent = await screen.findByTestId('embeddablePanelHeading-'); + const innerTitleComponent = await screen.findByTestId('embeddablePanelTitleInner'); + expect(innerTitleComponent).toBeEmptyDOMElement(); + const menuComponent = await screen.findByTestId('embeddablePanelToggleMenuIcon'); + expect(titleComponent).toContainElement(menuComponent); + }); + + test('clicking title opens customize panel flyout', async () => { + const mockEmbeddable = await createEmbeddable({ viewMode: ViewMode.EDIT }); + render( + + ); + const titleComponent = await screen.findByTestId('embeddablePanelTitleLink'); + + const spy = jest.spyOn(openCustomizePanel, 'openCustomizePanelFlyout'); + userEvent.click(titleComponent); + expect(spy).toHaveBeenCalled(); + }); +}); diff --git a/src/plugins/embeddable/public/embeddable_panel/panel_header/embeddable_panel_header.tsx b/src/plugins/embeddable/public/embeddable_panel/panel_header/embeddable_panel_header.tsx index ee27bbca0605..3de27d6ad193 100644 --- a/src/plugins/embeddable/public/embeddable_panel/panel_header/embeddable_panel_header.tsx +++ b/src/plugins/embeddable/public/embeddable_panel/panel_header/embeddable_panel_header.tsx @@ -85,7 +85,7 @@ export const EmbeddablePanelHeader = ({ if (!showPanelBar) { return ( -
    +
    {embeddablePanelContextMenu} {ariaLabelElement}
    @@ -104,7 +104,7 @@ export const EmbeddablePanelHeader = ({ hideTitle={hideTitle} embeddable={embeddable} description={description} - customizePanelAction={universalActions.customizePanel} + editPanelAction={universalActions.editPanel} /> {showBadges && badgeComponents} diff --git a/src/plugins/embeddable/public/embeddable_panel/panel_header/embeddable_panel_title.tsx b/src/plugins/embeddable/public/embeddable_panel/panel_header/embeddable_panel_title.tsx index 734b420d0405..693215a3084c 100644 --- a/src/plugins/embeddable/public/embeddable_panel/panel_header/embeddable_panel_title.tsx +++ b/src/plugins/embeddable/public/embeddable_panel/panel_header/embeddable_panel_title.tsx @@ -11,21 +11,22 @@ import React, { useMemo } from 'react'; import { EuiIcon, EuiLink, EuiToolTip } from '@elastic/eui'; import { IEmbeddable, ViewMode } from '../../lib'; -import { CustomizePanelAction } from '../panel_actions'; import { getEditTitleAriaLabel, placeholderTitle } from '../embeddable_panel_strings'; +import { EditPanelAction } from '../panel_actions'; +import { openCustomizePanelFlyout } from '../panel_actions/customize_panel_action/open_customize_panel'; export const EmbeddablePanelTitle = ({ viewMode, hideTitle, embeddable, description, - customizePanelAction, + editPanelAction, }: { hideTitle?: boolean; viewMode?: ViewMode; description?: string; embeddable: IEmbeddable; - customizePanelAction?: CustomizePanelAction; + editPanelAction?: EditPanelAction; }) => { const title = embeddable.getTitle(); @@ -39,32 +40,44 @@ export const EmbeddablePanelTitle = ({ if (viewMode === ViewMode.VIEW) { return {title}; } - if (customizePanelAction) { + if (editPanelAction) { return ( customizePanelAction.execute({ embeddable })} + onClick={() => + openCustomizePanelFlyout({ + editPanel: editPanelAction, + embeddable, + focusOnTitle: true, + }) + } > {title || placeholderTitle} ); } return null; - }, [customizePanelAction, embeddable, title, viewMode, hideTitle]); + }, [editPanelAction, embeddable, title, viewMode, hideTitle]); const titleComponentWithDescription = useMemo(() => { - if (!description) return {titleComponent}; + if (!description) + return ( + + {titleComponent} + + ); return ( - + {titleComponent}{' '} { this.appList = appList; @@ -168,13 +167,7 @@ export class EmbeddablePublicPlugin implements Plugin { - it('should not show custom time picker in flyout', async () => { - await dashboardPanelActions.removePanel(); - await PageObjects.dashboard.waitForRenderComplete(); - await dashboardAddPanel.clickMarkdownQuickButton(); - await PageObjects.visEditor.setMarkdownTxt('I am timeless!'); - await PageObjects.visEditor.clickGo(); - await PageObjects.visualize.saveVisualizationAndReturn(); - await PageObjects.dashboard.clickQuickSave(); - await dashboardPanelActions.customizePanel(); - await dashboardCustomizePanel.expectMissingCustomTimeRange(); - }); - }); }); } diff --git a/x-pack/test/functional/apps/dashboard/group2/panel_titles.ts b/x-pack/test/functional/apps/dashboard/group2/panel_titles.ts index 2c0ac33107fe..4d7950042783 100644 --- a/x-pack/test/functional/apps/dashboard/group2/panel_titles.ts +++ b/x-pack/test/functional/apps/dashboard/group2/panel_titles.ts @@ -78,44 +78,6 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { expect(panelTitle).to.equal(EMPTY_TITLE); await PageObjects.dashboard.clearUnsavedChanges(); }); - - it('blank titles are hidden in view mode', async () => { - await PageObjects.dashboard.clickCancelOutOfEditMode(); - - const titleVisibility = (await PageObjects.dashboard.getVisibilityOfPanelTitles())[0]; - expect(titleVisibility).to.be(false); - }); - - it('custom titles are visible in view mode', async () => { - await PageObjects.dashboard.switchToEditMode(); - await dashboardPanelActions.customizePanel(); - await dashboardCustomizePanel.setCustomPanelTitle(CUSTOM_TITLE); - await dashboardCustomizePanel.clickSaveButton(); - await PageObjects.dashboard.clickQuickSave(); - await PageObjects.dashboard.clickCancelOutOfEditMode(); - - const titleVisibility = (await PageObjects.dashboard.getVisibilityOfPanelTitles())[0]; - expect(titleVisibility).to.be(true); - }); - - it('hiding an individual panel title hides it in view mode', async () => { - await PageObjects.dashboard.switchToEditMode(); - await dashboardPanelActions.customizePanel(); - await dashboardCustomizePanel.clickToggleHidePanelTitle(); - await dashboardCustomizePanel.clickSaveButton(); - await PageObjects.dashboard.clickQuickSave(); - await PageObjects.dashboard.clickCancelOutOfEditMode(); - - const titleVisibility = (await PageObjects.dashboard.getVisibilityOfPanelTitles())[0]; - expect(titleVisibility).to.be(false); - - // undo the previous hide panel toggle (i.e. make the panel visible) to keep state consistent - await PageObjects.dashboard.switchToEditMode(); - await dashboardPanelActions.customizePanel(); - await dashboardCustomizePanel.clickToggleHidePanelTitle(); - await dashboardCustomizePanel.clickSaveButton(); - await PageObjects.dashboard.clickQuickSave(); - }); }); describe('by reference', () => { From 4af36fece290263c4fd86f0e06d3e12bdb05f81b Mon Sep 17 00:00:00 2001 From: Xavier Mouligneau Date: Thu, 4 Jan 2024 16:41:30 -0500 Subject: [PATCH 20/57] [SECURITY_SOLUTIONS] Only query security alerts with current user (#174216) ## Summary We just got an [SDH#814](https://github.com/elastic/sdh-security-team/issues/814) that tell us that some feature like `KPIs` and `grouping` are not acting as they should be. @PhilippeOberti is doing an investigation to check which feature has been impacted by this bug. This bug has been introduced in this https://github.com/elastic/kibana/pull/112113 since 8.0.0 I think this simple solution should not impact any features. --- .../signals/query_signals_route.test.ts | 27 ++-- .../routes/signals/query_signals_route.ts | 7 +- .../default_license/alerts/index.ts | 1 + .../default_license/alerts/query_alerts.ts | 153 ++++++++++++++++++ 4 files changed, 176 insertions(+), 12 deletions(-) create mode 100644 x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/alerts/query_alerts.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/query_signals_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/query_signals_route.test.ts index 7c88d5c9192e..8ae230d65506 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/query_signals_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/query_signals_route.test.ts @@ -17,18 +17,23 @@ import { import { requestContextMock, serverMock, requestMock } from '../__mocks__'; import { querySignalsRoute } from './query_signals_route'; import { ruleRegistryMocks } from '@kbn/rule-registry-plugin/server/mocks'; +import { elasticsearchClientMock } from '@kbn/core-elasticsearch-client-server-mocks'; describe('query for signal', () => { let server: ReturnType; let { context } = requestContextMock.createTools(); - const ruleDataClient = ruleRegistryMocks.createRuleDataClient('.alerts-security.alerts'); + context.core.elasticsearch.client.asCurrentUser.search.mockResolvedValue( + elasticsearchClientMock.createSuccessTransportRequestPromise(getEmptySignalsResponse()) + ); + const ruleDataClient = ruleRegistryMocks.createRuleDataClient('.alerts-security.alerts-'); beforeEach(() => { server = serverMock.create(); ({ context } = requestContextMock.createTools()); - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - ruleDataClient.getReader().search.mockResolvedValue(getEmptySignalsResponse() as any); + context.core.elasticsearch.client.asCurrentUser.search.mockResolvedValue( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + getEmptySignalsResponse() as any + ); querySignalsRoute(server.router, ruleDataClient); }); @@ -41,7 +46,7 @@ describe('query for signal', () => { ); expect(response.status).toEqual(200); - expect(ruleDataClient.getReader().search).toHaveBeenCalledWith( + expect(context.core.elasticsearch.client.asCurrentUser.search).toHaveBeenCalledWith( expect.objectContaining({ body: typicalSignalsQuery(), }) @@ -55,9 +60,9 @@ describe('query for signal', () => { ); expect(response.status).toEqual(200); - expect(ruleDataClient.getReader).toHaveBeenCalledWith( + expect(context.core.elasticsearch.client.asCurrentUser.search).toHaveBeenCalledWith( expect.objectContaining({ - namespace: 'default', + index: '.alerts-security.alerts-default', }) ); }); @@ -69,7 +74,7 @@ describe('query for signal', () => { ); expect(response.status).toEqual(200); - expect(ruleDataClient.getReader().search).toHaveBeenCalledWith( + expect(context.core.elasticsearch.client.asCurrentUser.search).toHaveBeenCalledWith( expect.objectContaining({ body: typicalSignalsQueryAggs(), ignore_unavailable: true }) ); }); @@ -81,7 +86,7 @@ describe('query for signal', () => { ); expect(response.status).toEqual(200); - expect(ruleDataClient.getReader().search).toHaveBeenCalledWith( + expect(context.core.elasticsearch.client.asCurrentUser.search).toHaveBeenCalledWith( expect.objectContaining({ body: { ...typicalSignalsQuery(), @@ -92,7 +97,9 @@ describe('query for signal', () => { }); test('catches error if query throws error', async () => { - ruleDataClient.getReader().search.mockRejectedValue(new Error('Test error')); + context.core.elasticsearch.client.asCurrentUser.search.mockRejectedValue( + new Error('Test error') + ); const response = await server.inject( getSignalsAggsQueryRequest(), requestContextMock.convertContext(context) diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/query_signals_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/query_signals_route.ts index 673b6c2d8581..3bd52ebdaacd 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/query_signals_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/query_signals_route.ts @@ -40,6 +40,8 @@ export const querySignalsRoute = ( }, }, async (context, request, response) => { + const esClient = (await context.core).elasticsearch.client.asCurrentUser; + // eslint-disable-next-line @typescript-eslint/naming-convention const { query, aggs, _source, fields, track_total_hits, size, runtime_mappings, sort } = request.body; @@ -58,10 +60,11 @@ export const querySignalsRoute = ( body: '"value" must have at least 1 children', }); } - try { const spaceId = (await context.securitySolution).getSpaceId(); - const result = await ruleDataClient?.getReader({ namespace: spaceId }).search({ + const indexPattern = ruleDataClient?.indexNameWithNamespace(spaceId); + const result = await esClient.search({ + index: indexPattern, body: { query, // Note: I use a spread operator to please TypeScript with aggs: { ...aggs } diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/alerts/index.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/alerts/index.ts index 85e2e602a892..81923173bf50 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/alerts/index.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/alerts/index.ts @@ -15,5 +15,6 @@ export default function ({ loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./open_close_alerts')); loadTestFile(require.resolve('./set_alert_tags')); loadTestFile(require.resolve('./assignments')); + loadTestFile(require.resolve('./query_alerts')); }); } diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/alerts/query_alerts.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/alerts/query_alerts.ts new file mode 100644 index 000000000000..6e8e312f9075 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/alerts/query_alerts.ts @@ -0,0 +1,153 @@ +/* + * 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 { DETECTION_ENGINE_QUERY_SIGNALS_URL } from '@kbn/security-solution-plugin/common/constants'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; + +const roleToAccessSecuritySolution = { + name: 'sec_all_spaces', + privileges: { + elasticsearch: { + indices: [ + { + names: ['.alerts-security.alerts-default'], + privileges: ['all'], + }, + ], + }, + kibana: [ + { + feature: { + siem: ['all'], + }, + spaces: ['*'], + }, + ], + }, +}; +const roleToAccessSecuritySolutionWithDls = { + name: 'sec_all_spaces_with_dls', + privileges: { + elasticsearch: { + indices: [ + { + names: ['.alerts-security.alerts-default'], + privileges: ['read'], + query: + '{"wildcard" : { "kibana.alert.ancestors.index" : { "value": ".ds-kibana_does_not_exist" } } }', + }, + ], + }, + kibana: [ + { + feature: { + siem: ['all'], + }, + spaces: ['*'], + }, + ], + }, +}; +const userAllSec = { + username: 'user_all_sec', + password: 'user_all_sec', + full_name: 'userAllSec', + email: 'userAllSec@elastic.co', + roles: [roleToAccessSecuritySolution.name], +}; +const userAllSecWithDls = { + username: 'user_all_sec_with_dls', + password: 'user_all_sec_with_dls', + full_name: 'userAllSecWithDls', + email: 'userAllSecWithDls@elastic.co', + roles: [roleToAccessSecuritySolutionWithDls.name], +}; + +export default ({ getService }: FtrProviderContext) => { + const supertestWithoutAuth = getService('supertestWithoutAuth'); + const esArchiver = getService('esArchiver'); + const security = getService('security'); + + describe('find alert with/without doc level security', () => { + before(async () => { + await security.role.create( + roleToAccessSecuritySolution.name, + roleToAccessSecuritySolution.privileges + ); + await security.role.create( + roleToAccessSecuritySolutionWithDls.name, + roleToAccessSecuritySolutionWithDls.privileges + ); + await security.user.create(userAllSec.username, { + password: userAllSec.password, + roles: userAllSec.roles, + full_name: userAllSec.full_name, + email: userAllSec.email, + }); + await security.user.create(userAllSecWithDls.username, { + password: userAllSecWithDls.password, + roles: userAllSecWithDls.roles, + full_name: userAllSecWithDls.full_name, + email: userAllSecWithDls.email, + }); + + await esArchiver.load( + 'x-pack/test/functional/es_archives/security_solution/alerts/8.8.0_multiple_docs', + { + useCreate: true, + docsOnly: true, + } + ); + }); + + after(async () => { + await security.user.delete(userAllSec.username); + await security.user.delete(userAllSecWithDls.username); + await security.role.delete(roleToAccessSecuritySolution.name); + await security.role.delete(roleToAccessSecuritySolutionWithDls.name); + await esArchiver.unload( + 'x-pack/test/functional/es_archives/security_solution/alerts/8.8.0_multiple_docs' + ); + }); + + it('should return alerts with user who has access to security solution privileges', async () => { + const query = { + query: { + bool: { + should: [{ match_all: {} }], + }, + }, + }; + const { body } = await supertestWithoutAuth + .post(DETECTION_ENGINE_QUERY_SIGNALS_URL) + .auth(userAllSec.username, userAllSec.password) + .set('kbn-xsrf', 'true') + .send(query) + .expect(200); + expect(body.hits.total.value).to.eql(3); + }); + + it('should filter out alerts with user who has access to security solution privileges and document level security', async () => { + const query = { + query: { + bool: { + should: [{ match_all: {} }], + }, + }, + }; + const { body } = await supertestWithoutAuth + .post(DETECTION_ENGINE_QUERY_SIGNALS_URL) + .auth(userAllSecWithDls.username, userAllSecWithDls.password) + .set('kbn-xsrf', 'true') + .send(query) + .expect(200); + expect(body.hits.total.value).to.eql(0); + }); + }); +}; From 1021f65f1cd5ac067953bf24c90f096f6fc18c73 Mon Sep 17 00:00:00 2001 From: Ryland Herrick Date: Thu, 4 Jan 2024 15:42:24 -0600 Subject: [PATCH 21/57] [SecuritySolution][EntityAnalytics] Account for Asset Criticality in Risk Scoring (#172417) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary This PR adds asset criticality to the risk scoring calculation. While previous work was done to add the resources and client to create/read asset criticality documents, this PR builds on those to retrieve relevant criticality records and apply them to the intermediate scores calculated via elasticsearch. __Note that the code in this PR that performs the actual calculation/writing of new risk fields is behind a feature flag.__ ### Performance Since this PR adds new logic to an already tight/important code path, we need to ensure that we haven't changed behavior nor performance. I've captured that as a separate task to be done next: https://github.com/elastic/security-team/issues/8223. ### Compatibility Behaviorally, without the feature flag enabled, scoring will skip the criticality workflow and not write new fields (`criticality_level`, `criticality_modifier`). ~~I still have an outstanding task to validate whether this will be an issue until criticality is enabled, and do some smarter short-circuiting.~~ This task uncovered our need for the above feature flag. The one behavioral change introduced in this PR _not_ behind a feature flag is the normalization of our risk category scores. ### Summary of Changes - Adds an `AssetCriticalityService` which provides the API used by risk scoring to retrieve criticality records - Adds new `search` method to the `AssetCriticalityDataClient`: used to generally retrieve multiple criticality records at once - Adds functions to calculate a (currently hard-coded) modifier from a criticality level, and apply it to the risk score via bayesian update - Moves risk score level calculation into javascript (necessary because we need the level to account for criticality) - Moves some risk level code out of threat hunting code and into the `common/entity_analytics` folder - Tests and comments throughout ### TODO - [x] Add new criticality fields to risk score, address upgrade workflow - [x] Validate that code works without criticality being enabled. - [x] Bump task version to invalidate old tasks from being picked up in customer env Outcome: All three of the above are addressed with: 1. Moving the code responsible for adding new fields behind a feature flag ([71f1158](https://github.com/elastic/kibana/pull/172417/commits/71f115800b9ecca21d1c2e0e9014163f2858ece3)) 2. Addressing the upgrade path in a subsequent issue (https://github.com/elastic/security-team/issues/8012) ## How to Review 1. Enable our asset criticality feature flag: > ``` > xpack.securitySolution.enableExperimental: > - entityAnalyticsAssetCriticalityEnabled > ``` 2. Create asset criticality records (see API documentation, or follow [this test](https://github.com/elastic/kibana/pull/172417/files#diff-43f9f394fb7c8eb0f0ace3f5e75482c56a7233ae7d11d5fdb98a89e6404412c3R276) as a setup guide 3. Enable risk engine 4. Observe that new fields are written to risk scores' `_source`, but not mapped/searchable 5. (optional) Observe that the transform subsequently fails 😢 ### Checklist - [ ] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md) - [ ] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [ ] [Flaky Test Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was used on any tests changed --------- Co-authored-by: Jared Burgett and Ryland Herrick --- .../common/api/entity_analytics/index.ts | 9 + .../entity_analytics/risk_engine/common.yml | 24 +- .../entity_analytics/risk_engine/index.ts | 1 + .../risk_engine/risk_levels.ts | 30 +++ .../entity_analytics/risk_engine/types.ts | 17 ++ .../security_solution/risk_score/all/index.ts | 15 +- .../public/entity_analytics/common/utils.ts | 9 +- .../asset_criticality_data_client.mock.ts | 1 + .../asset_criticality_data_client.test.ts | 64 ++++++ .../asset_criticality_data_client.ts | 33 ++- .../asset_criticality_service.mock.ts | 17 ++ .../asset_criticality_service.test.ts | 206 ++++++++++++++++++ .../asset_criticality_service.ts | 101 +++++++++ .../{configurations.ts => constants.ts} | 11 + .../asset_criticality/helpers.test.ts | 102 +++++++++ .../asset_criticality/helpers.ts | 88 ++++++++ .../asset_criticality/index.ts | 9 + .../calculate_and_persist_risk_scores.ts | 2 + .../risk_score/calculate_risk_scores.mock.ts | 5 +- .../risk_score/calculate_risk_scores.test.ts | 42 +++- .../risk_score/calculate_risk_scores.ts | 187 +++++++++++----- .../entity_analytics/risk_score/constants.ts | 27 +++ .../risk_engine_data_writer.test.ts | 28 +++ .../risk_score/risk_score_service.mock.ts | 4 + .../risk_score/risk_score_service.ts | 15 +- .../risk_score/risk_weights.ts | 2 +- .../risk_score/routes/calculation.test.ts | 3 +- .../risk_score/routes/calculation.ts | 14 +- .../risk_score/routes/preview.test.ts | 3 +- .../risk_score/routes/preview.ts | 14 +- .../tasks/risk_scoring_task.test.ts | 3 + .../risk_score/tasks/risk_scoring_task.ts | 26 ++- .../server/lib/entity_analytics/types.ts | 1 - .../security_solution/server/plugin.ts | 1 + .../server/request_context_factory.ts | 2 +- .../security_solution/server/routes/index.ts | 4 +- .../plugins/security_solution/server/types.ts | 2 +- .../risk_engine/risk_score_calculation.ts | 79 ++++++- .../risk_engine/risk_score_preview.ts | 114 +++++++--- .../risk_scoring_task/task_execution.ts | 67 +++++- .../utils/asset_criticality.ts | 51 ++++- .../entity_analytics/utils/index.ts | 1 + .../entity_analytics/utils/risk_engine.ts | 14 +- 43 files changed, 1303 insertions(+), 145 deletions(-) create mode 100644 x-pack/plugins/security_solution/common/api/entity_analytics/index.ts create mode 100644 x-pack/plugins/security_solution/common/entity_analytics/risk_engine/risk_levels.ts create mode 100644 x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/asset_criticality_service.mock.ts create mode 100644 x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/asset_criticality_service.test.ts create mode 100644 x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/asset_criticality_service.ts rename x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/{configurations.ts => constants.ts} (67%) create mode 100644 x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/helpers.test.ts create mode 100644 x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/helpers.ts create mode 100644 x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/index.ts create mode 100644 x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/constants.ts diff --git a/x-pack/plugins/security_solution/common/api/entity_analytics/index.ts b/x-pack/plugins/security_solution/common/api/entity_analytics/index.ts new file mode 100644 index 000000000000..2dbb228a91f8 --- /dev/null +++ b/x-pack/plugins/security_solution/common/api/entity_analytics/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 './asset_criticality'; +export * from './risk_score'; diff --git a/x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/common.yml b/x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/common.yml index ea4bd4bd8632..4e73c51b9087 100644 --- a/x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/common.yml +++ b/x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/common.yml @@ -1,4 +1,10 @@ openapi: 3.0.0 +info: + title: Risk Engine Common Schema + description: Common schema for Risk Engine APIs + version: 1.0.0 + +paths: { } components: schemas: @@ -103,11 +109,27 @@ components: category_1_score: type: number format: double - description: The contribution of Category 1 to the overall risk score (`calculated_score`). Category 1 contains Detection Engine Alerts. + description: The contribution of Category 1 to the overall risk score (`calculated_score_norm`). Category 1 contains Detection Engine Alerts. category_1_count: type: number format: integer description: The number of risk input documents that contributed to the Category 1 score (`category_1_score`). + category_2_score: + type: number + format: double + description: The contribution of Category 2 to the overall risk score (`calculated_score_norm`). Category 2 contains context from external sources. + category_2_count: + type: number + format: integer + description: The number of risk input documents that contributed to the Category 2 score (`category_2_score`). + criticality_level: + type: string + example: very_important + description: The designated criticality level of the entity. Possible values are `not_important`, `normal`, `important`, and `very_important`. + criticality_modifier: + type: number + format: double + description: The numeric modifier corresponding to the criticality level of the entity, which is used as an input to the risk score calculation. inputs: type: array description: A list of the highest-risk documents contributing to this risk score. Useful for investigative purposes. diff --git a/x-pack/plugins/security_solution/common/entity_analytics/risk_engine/index.ts b/x-pack/plugins/security_solution/common/entity_analytics/risk_engine/index.ts index 3da0d8be4f0b..bb75e496f386 100644 --- a/x-pack/plugins/security_solution/common/entity_analytics/risk_engine/index.ts +++ b/x-pack/plugins/security_solution/common/entity_analytics/risk_engine/index.ts @@ -9,6 +9,7 @@ export * from './after_keys'; export * from './risk_weights'; export * from './identifier_types'; export * from './range'; +export * from './risk_levels'; export * from './types'; export * from './indices'; export * from './constants'; diff --git a/x-pack/plugins/security_solution/common/entity_analytics/risk_engine/risk_levels.ts b/x-pack/plugins/security_solution/common/entity_analytics/risk_engine/risk_levels.ts new file mode 100644 index 000000000000..d2e777ad710a --- /dev/null +++ b/x-pack/plugins/security_solution/common/entity_analytics/risk_engine/risk_levels.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 { RiskLevels } from './types'; + +export const RISK_LEVEL_RANGES = { + [RiskLevels.unknown]: { start: 0, stop: 20 }, + [RiskLevels.low]: { start: 20, stop: 40 }, + [RiskLevels.moderate]: { start: 40, stop: 70 }, + [RiskLevels.high]: { start: 70, stop: 90 }, + [RiskLevels.critical]: { start: 90, stop: 100 }, +}; + +export const getRiskLevel = (riskScore: number): RiskLevels => { + if (riskScore >= RISK_LEVEL_RANGES[RiskLevels.critical].start) { + return RiskLevels.critical; + } else if (riskScore >= RISK_LEVEL_RANGES[RiskLevels.high].start) { + return RiskLevels.high; + } else if (riskScore >= RISK_LEVEL_RANGES[RiskLevels.moderate].start) { + return RiskLevels.moderate; + } else if (riskScore >= RISK_LEVEL_RANGES[RiskLevels.low].start) { + return RiskLevels.low; + } else { + return RiskLevels.unknown; + } +}; diff --git a/x-pack/plugins/security_solution/common/entity_analytics/risk_engine/types.ts b/x-pack/plugins/security_solution/common/entity_analytics/risk_engine/types.ts index deed9767ed2c..f803ec0ed671 100644 --- a/x-pack/plugins/security_solution/common/entity_analytics/risk_engine/types.ts +++ b/x-pack/plugins/security_solution/common/entity_analytics/risk_engine/types.ts @@ -38,24 +38,41 @@ export interface SimpleRiskInput { export interface EcsRiskScore { '@timestamp': string; host?: { + name: string; risk: Omit; }; user?: { + name: string; risk: Omit; }; } export type RiskInputs = SimpleRiskInput[]; +/** + * The API response object representing a risk score + */ export interface RiskScore { '@timestamp': string; id_field: string; id_value: string; + criticality_level?: string | undefined; + criticality_modifier?: number | undefined; calculated_level: string; calculated_score: number; calculated_score_norm: number; category_1_score: number; category_1_count: number; + category_2_score?: number; + category_2_count?: number; notes: string[]; inputs: RiskInputs; } + +export enum RiskLevels { + unknown = 'Unknown', + low = 'Low', + moderate = 'Moderate', + high = 'High', + critical = 'Critical', +} diff --git a/x-pack/plugins/security_solution/common/search_strategy/security_solution/risk_score/all/index.ts b/x-pack/plugins/security_solution/common/search_strategy/security_solution/risk_score/all/index.ts index f33eb664628a..7810c29fbfbf 100644 --- a/x-pack/plugins/security_solution/common/search_strategy/security_solution/risk_score/all/index.ts +++ b/x-pack/plugins/security_solution/common/search_strategy/security_solution/risk_score/all/index.ts @@ -8,7 +8,10 @@ import type { IEsSearchResponse } from '@kbn/data-plugin/common'; import type { Inspect, Maybe, SortField } from '../../../common'; -import type { RiskInputs } from '../../../../entity_analytics/risk_engine'; +import { + type RiskInputs, + RiskLevels as RiskSeverity, +} from '../../../../entity_analytics/risk_engine'; export interface HostsRiskScoreStrategyResponse extends IEsSearchResponse { inspect?: Maybe; @@ -30,6 +33,8 @@ export interface RiskStats { inputs?: RiskInputs; } +export { RiskSeverity }; + export interface HostRiskScore { '@timestamp': string; host: { @@ -85,14 +90,6 @@ export interface RiskScoreItem { [RiskScoreFields.alertsCount]: Maybe; } -export enum RiskSeverity { - unknown = 'Unknown', - low = 'Low', - moderate = 'Moderate', - high = 'High', - critical = 'Critical', -} - export const isUserRiskScore = (risk: HostRiskScore | UserRiskScore): risk is UserRiskScore => 'user' in risk; diff --git a/x-pack/plugins/security_solution/public/entity_analytics/common/utils.ts b/x-pack/plugins/security_solution/public/entity_analytics/common/utils.ts index f6009c85dbd4..b8735c2e7b6f 100644 --- a/x-pack/plugins/security_solution/public/entity_analytics/common/utils.ts +++ b/x-pack/plugins/security_solution/public/entity_analytics/common/utils.ts @@ -8,6 +8,7 @@ import { euiLightVars } from '@kbn/ui-theme'; import { RiskSeverity } from '../../../common/search_strategy'; import { SEVERITY_COLOR } from '../../overview/components/detection_response/utils'; +export { RISK_LEVEL_RANGES as RISK_SCORE_RANGES } from '../../../common/entity_analytics/risk_engine'; export const SEVERITY_UI_SORT_ORDER = [ RiskSeverity.unknown, @@ -25,14 +26,6 @@ export const RISK_SEVERITY_COLOUR: { [k in RiskSeverity]: string } = { [RiskSeverity.critical]: SEVERITY_COLOR.critical, }; -export const RISK_SCORE_RANGES = { - [RiskSeverity.unknown]: { start: 0, stop: 20 }, - [RiskSeverity.low]: { start: 20, stop: 40 }, - [RiskSeverity.moderate]: { start: 40, stop: 70 }, - [RiskSeverity.high]: { start: 70, stop: 90 }, - [RiskSeverity.critical]: { start: 90, stop: 100 }, -}; - type SnakeToCamelCaseString = S extends `${infer T}_${infer U}` ? `${T}${Capitalize>}` : S; diff --git a/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/asset_criticality_data_client.mock.ts b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/asset_criticality_data_client.mock.ts index eaf3e9a3ec22..6b98e880ea6a 100644 --- a/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/asset_criticality_data_client.mock.ts +++ b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/asset_criticality_data_client.mock.ts @@ -12,6 +12,7 @@ const createAssetCriticalityDataClientMock = () => doesIndexExist: jest.fn(), getStatus: jest.fn(), init: jest.fn(), + search: jest.fn(), } as unknown as jest.Mocked); export const assetCriticalityDataClientMock = { create: createAssetCriticalityDataClientMock }; diff --git a/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/asset_criticality_data_client.test.ts b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/asset_criticality_data_client.test.ts index c06586516d68..83d197123303 100644 --- a/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/asset_criticality_data_client.test.ts +++ b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/asset_criticality_data_client.test.ts @@ -57,4 +57,68 @@ describe('AssetCriticalityDataClient', () => { }); }); }); + + describe('#search()', () => { + let esClientMock: ReturnType< + typeof elasticsearchServiceMock.createScopedClusterClient + >['asInternalUser']; + let loggerMock: ReturnType; + let subject: AssetCriticalityDataClient; + + beforeEach(() => { + esClientMock = elasticsearchServiceMock.createScopedClusterClient().asInternalUser; + loggerMock = loggingSystemMock.createLogger(); + subject = new AssetCriticalityDataClient({ + esClient: esClientMock, + logger: loggerMock, + namespace: 'default', + }); + }); + + it('searches in the asset criticality index', async () => { + subject.search({ query: { match_all: {} } }); + + expect(esClientMock.search).toHaveBeenCalledWith( + expect.objectContaining({ index: '.asset-criticality.asset-criticality-default' }) + ); + }); + + it('requires a query parameter', async () => { + subject.search({ query: { match_all: {} } }); + + expect(esClientMock.search).toHaveBeenCalledWith( + expect.objectContaining({ body: { query: { match_all: {} } } }) + ); + }); + + it('accepts a size parameter', async () => { + subject.search({ query: { match_all: {} }, size: 100 }); + + expect(esClientMock.search).toHaveBeenCalledWith(expect.objectContaining({ size: 100 })); + }); + + it('defaults to the default query size', async () => { + subject.search({ query: { match_all: {} } }); + const defaultSize = 1_000; + + expect(esClientMock.search).toHaveBeenCalledWith( + expect.objectContaining({ size: defaultSize }) + ); + }); + + it('caps the size to the maximum query size', async () => { + subject.search({ query: { match_all: {} }, size: 999999 }); + const maxSize = 100_000; + + expect(esClientMock.search).toHaveBeenCalledWith(expect.objectContaining({ size: maxSize })); + }); + + it('ignores an index_not_found_exception if the criticality index does not exist', async () => { + subject.search({ query: { match_all: {} } }); + + expect(esClientMock.search).toHaveBeenCalledWith( + expect.objectContaining({ ignore_unavailable: true }) + ); + }); + }); }); diff --git a/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/asset_criticality_data_client.ts b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/asset_criticality_data_client.ts index afddfd689324..3ac20360bcae 100644 --- a/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/asset_criticality_data_client.ts +++ b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/asset_criticality_data_client.ts @@ -4,12 +4,14 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ +import type { ESFilter } from '@kbn/es-types'; +import type { SearchResponse } from '@elastic/elasticsearch/lib/api/types'; import type { Logger, ElasticsearchClient } from '@kbn/core/server'; import { mappingFromFieldMap } from '@kbn/alerting-plugin/common'; -import type { AssetCriticalityRecord } from '../../../../common/api/entity_analytics/asset_criticality'; +import type { AssetCriticalityRecord } from '../../../../common/api/entity_analytics'; import { createOrUpdateIndex } from '../utils/create_or_update_index'; import { getAssetCriticalityIndex } from '../../../../common/entity_analytics/asset_criticality'; -import { assetCriticalityFieldMap } from './configurations'; +import { assetCriticalityFieldMap } from './constants'; interface AssetCriticalityClientOpts { logger: Logger; @@ -25,7 +27,11 @@ interface AssetCriticalityUpsert { type AssetCriticalityIdParts = Pick; +const MAX_CRITICALITY_RESPONSE_SIZE = 100_000; +const DEFAULT_CRITICALITY_RESPONSE_SIZE = 1_000; + const createId = ({ idField, idValue }: AssetCriticalityIdParts) => `${idField}:${idValue}`; + export class AssetCriticalityDataClient { constructor(private readonly options: AssetCriticalityClientOpts) {} /** @@ -43,6 +49,29 @@ export class AssetCriticalityDataClient { }); } + /** + * + * A general method for searching asset criticality records. + * @param query an ESL query to filter criticality results + * @param size the maximum number of records to return. Cannot exceed {@link MAX_CRITICALITY_RESPONSE_SIZE}. If unspecified, will default to {@link DEFAULT_CRITICALITY_RESPONSE_SIZE}. + * @returns criticality records matching the query + */ + public async search({ + query, + size, + }: { + query: ESFilter; + size?: number; + }): Promise> { + const response = await this.options.esClient.search({ + index: this.getIndex(), + ignore_unavailable: true, + body: { query }, + size: Math.min(size ?? DEFAULT_CRITICALITY_RESPONSE_SIZE, MAX_CRITICALITY_RESPONSE_SIZE), + }); + return response; + } + private getIndex() { return getAssetCriticalityIndex(this.options.namespace); } diff --git a/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/asset_criticality_service.mock.ts b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/asset_criticality_service.mock.ts new file mode 100644 index 000000000000..9de2d8c6bae2 --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/asset_criticality_service.mock.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { AssetCriticalityService } from './asset_criticality_service'; + +const buildMockAssetCriticalityService = (): jest.Mocked => ({ + getCriticalitiesByIdentifiers: jest.fn().mockResolvedValue([]), + isEnabled: jest.fn().mockReturnValue(true), +}); + +export const assetCriticalityServiceMock = { + create: buildMockAssetCriticalityService, +}; diff --git a/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/asset_criticality_service.test.ts b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/asset_criticality_service.test.ts new file mode 100644 index 000000000000..7075aacfcb31 --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/asset_criticality_service.test.ts @@ -0,0 +1,206 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { SearchHit } from '@elastic/elasticsearch/lib/api/types'; + +import type { ExperimentalFeatures } from '../../../../common'; +import type { AssetCriticalityRecord } from '../../../../common/api/entity_analytics'; +import type { AssetCriticalityDataClient } from './asset_criticality_data_client'; +import { assetCriticalityDataClientMock } from './asset_criticality_data_client.mock'; +import { + type AssetCriticalityService, + assetCriticalityServiceFactory, +} from './asset_criticality_service'; + +const buildMockCriticalityHit = ( + overrides: Partial = {} +): SearchHit => ({ + _id: 'host.name:not-found', + _index: '.asset-criticality-default', + _source: { + '@timestamp': '2021-09-16T15:00:00.000Z', + id_field: 'host.name', + id_value: 'hostname', + criticality_level: 'normal', + ...overrides, + }, +}); + +describe('AssetCriticalityService', () => { + describe('#getCriticalitiesByIdentifiers()', () => { + let baseIdentifier: { id_field: string; id_value: string }; + let mockAssetCriticalityDataClient: AssetCriticalityDataClient; + let service: AssetCriticalityService; + + beforeEach(() => { + mockAssetCriticalityDataClient = assetCriticalityDataClientMock.create(); + baseIdentifier = { id_field: 'host.name', id_value: 'not-found' }; + + (mockAssetCriticalityDataClient.search as jest.Mock).mockResolvedValueOnce({ + hits: { hits: [] }, + }); + service = assetCriticalityServiceFactory({ + assetCriticalityDataClient: mockAssetCriticalityDataClient, + experimentalFeatures: {} as ExperimentalFeatures, + }); + }); + + describe('specifying a single identifier', () => { + it('returns an empty response if identifier is not found', async () => { + const result = await service.getCriticalitiesByIdentifiers([baseIdentifier]); + + expect(result).toEqual([]); + }); + + it('returns a single criticality if identifier is found', async () => { + const hits = [buildMockCriticalityHit()]; + (mockAssetCriticalityDataClient.search as jest.Mock).mockReset().mockResolvedValueOnce({ + hits: { hits }, + }); + + const result = await service.getCriticalitiesByIdentifiers([baseIdentifier]); + + expect(result).toEqual(hits.map((hit) => hit._source)); + }); + }); + + describe('specifying multiple identifiers', () => { + it('returns an empty response if identifier is not found', async () => { + const result = await service.getCriticalitiesByIdentifiers([baseIdentifier]); + + expect(result).toEqual([]); + }); + + it('generates a single terms clause for multiple identifier values on the same field', async () => { + const multipleIdentifiers = [ + { id_field: 'user.name', id_value: 'one' }, + { id_field: 'user.name', id_value: 'other' }, + ]; + + await service.getCriticalitiesByIdentifiers(multipleIdentifiers); + + expect(mockAssetCriticalityDataClient.search).toHaveBeenCalledTimes(1); + const query = (mockAssetCriticalityDataClient.search as jest.Mock).mock.calls[0][0].query; + expect(query).toMatchObject({ + bool: { + filter: { + bool: { + should: [ + { + bool: { + must: [ + { term: { id_field: 'user.name' } }, + { terms: { id_value: ['one', 'other'] } }, + ], + }, + }, + ], + }, + }, + }, + }); + }); + + it('deduplicates identifiers', async () => { + const duplicateIdentifiers = [ + { id_field: 'user.name', id_value: 'same' }, + { id_field: 'user.name', id_value: 'same' }, + ]; + await service.getCriticalitiesByIdentifiers(duplicateIdentifiers); + + expect(mockAssetCriticalityDataClient.search).toHaveBeenCalledTimes(1); + const query = (mockAssetCriticalityDataClient.search as jest.Mock).mock.calls[0][0].query; + expect(query).toMatchObject({ + bool: { + filter: { + bool: { + should: [ + { + bool: { + must: [ + { term: { id_field: 'user.name' } }, + { terms: { id_value: ['same'] } }, + ], + }, + }, + ], + }, + }, + }, + }); + }); + + it('returns multiple criticalities if identifiers are found', async () => { + const hits = [ + buildMockCriticalityHit(), + buildMockCriticalityHit({ + id_field: 'user.name', + id_value: 'username', + criticality_level: 'very_important', + }), + ]; + + (mockAssetCriticalityDataClient.search as jest.Mock).mockReset().mockResolvedValueOnce({ + hits: { + hits, + }, + }); + const result = await service.getCriticalitiesByIdentifiers([baseIdentifier]); + expect(result).toEqual(hits.map((hit) => hit._source)); + }); + }); + + describe('arguments', () => { + it('accepts a single identifier as an array', async () => { + const identifier = { id_field: 'host.name', id_value: 'foo' }; + + expect(() => service.getCriticalitiesByIdentifiers([identifier])).not.toThrow(); + }); + + it('accepts multiple identifiers', async () => { + const identifiers = [ + { id_field: 'host.name', id_value: 'foo' }, + { id_field: 'user.name', id_value: 'bar' }, + ]; + expect(() => service.getCriticalitiesByIdentifiers(identifiers)).not.toThrow(); + }); + + it('throws an error if an empty array is provided', async () => { + await expect(() => service.getCriticalitiesByIdentifiers([])).rejects.toThrowError( + 'At least one identifier must be provided' + ); + }); + + it('throws an error if no identifier values are provided', async () => { + await expect(() => + service.getCriticalitiesByIdentifiers([{ id_field: 'host.name', id_value: '' }]) + ).rejects.toThrowError('At least one identifier must contain a valid field and value'); + }); + + it('throws an error if no valid identifier field/value pair is provided', async () => { + const identifiers = [ + { id_field: '', id_value: 'foo' }, + { id_field: 'user.name', id_value: '' }, + ]; + await expect(() => service.getCriticalitiesByIdentifiers(identifiers)).rejects.toThrowError( + 'At least one identifier must contain a valid field and value' + ); + }); + }); + + describe('error conditions', () => { + it('throws an error if the client does', async () => { + (mockAssetCriticalityDataClient.search as jest.Mock) + .mockReset() + .mockRejectedValueOnce(new Error('foo')); + await expect(() => + service.getCriticalitiesByIdentifiers([baseIdentifier]) + ).rejects.toThrowError('foo'); + }); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/asset_criticality_service.ts b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/asset_criticality_service.ts new file mode 100644 index 000000000000..f5320ea39600 --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/asset_criticality_service.ts @@ -0,0 +1,101 @@ +/* + * 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 { isEmpty } from 'lodash/fp'; +import type { ExperimentalFeatures } from '../../../../common'; +import type { AssetCriticalityRecord } from '../../../../common/api/entity_analytics'; +import type { AssetCriticalityDataClient } from './asset_criticality_data_client'; + +interface CriticalityIdentifier { + id_field: string; + id_value: string; +} + +interface IdentifierValuesByField { + [idField: string]: string[]; +} + +export interface AssetCriticalityService { + getCriticalitiesByIdentifiers: ( + identifiers: CriticalityIdentifier[] + ) => Promise; + isEnabled: () => boolean; +} + +const isCriticalityIdentifierValid = (identifier: CriticalityIdentifier): boolean => + !isEmpty(identifier.id_field) && !isEmpty(identifier.id_value); + +const groupIdentifierValuesByField = ( + identifiers: CriticalityIdentifier[] +): IdentifierValuesByField => + identifiers.reduce((acc, id) => { + acc[id.id_field] ??= []; + if (!acc[id.id_field].includes(id.id_value)) { + acc[id.id_field].push(id.id_value); + } + return acc; + }, {} as IdentifierValuesByField); + +const buildCriticalitiesQuery = (identifierValuesByField: IdentifierValuesByField) => ({ + bool: { + filter: { + bool: { + should: Object.keys(identifierValuesByField).map((idField) => ({ + bool: { + must: [ + { term: { id_field: idField } }, + { terms: { id_value: identifierValuesByField[idField] } }, + ], + }, + })), + }, + }, + }, +}); + +const getCriticalitiesByIdentifiers = async ({ + assetCriticalityDataClient, + identifiers, +}: { + assetCriticalityDataClient: AssetCriticalityDataClient; + identifiers: CriticalityIdentifier[]; +}): Promise => { + if (identifiers.length === 0) { + throw new Error('At least one identifier must be provided'); + } + const validIdentifiers = identifiers.filter((id) => isCriticalityIdentifierValid(id)); + + if (validIdentifiers.length === 0) { + throw new Error('At least one identifier must contain a valid field and value'); + } + + const identifierCount = validIdentifiers.length; + const identifierValuesByField = groupIdentifierValuesByField(validIdentifiers); + const criticalitiesQuery = buildCriticalitiesQuery(identifierValuesByField); + + const criticalitySearchResponse = await assetCriticalityDataClient.search({ + query: criticalitiesQuery, + size: identifierCount, + }); + + // @ts-expect-error @elastic/elasticsearch _source is optional + return criticalitySearchResponse.hits.hits.map((hit) => hit._source); +}; + +interface AssetCriticalityServiceFactoryOptions { + assetCriticalityDataClient: AssetCriticalityDataClient; + experimentalFeatures: ExperimentalFeatures; +} + +export const assetCriticalityServiceFactory = ({ + assetCriticalityDataClient, + experimentalFeatures, +}: AssetCriticalityServiceFactoryOptions): AssetCriticalityService => ({ + getCriticalitiesByIdentifiers: (identifiers: CriticalityIdentifier[]) => + getCriticalitiesByIdentifiers({ assetCriticalityDataClient, identifiers }), + isEnabled: () => experimentalFeatures.entityAnalyticsAssetCriticalityEnabled, +}); diff --git a/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/configurations.ts b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/constants.ts similarity index 67% rename from x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/configurations.ts rename to x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/constants.ts index c1b309c3a2f4..536230b865a8 100644 --- a/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/configurations.ts +++ b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/constants.ts @@ -5,6 +5,7 @@ * 2.0. */ import type { FieldMap } from '@kbn/alerts-as-data-utils'; +import type { AssetCriticalityRecord } from '../../../../common/api/entity_analytics'; export const assetCriticalityFieldMap: FieldMap = { '@timestamp': { @@ -33,3 +34,13 @@ export const assetCriticalityFieldMap: FieldMap = { required: false, }, } as const; + +/** + * CriticalityModifiers are used to adjust the risk score based on the criticality of the asset. + */ +export const CriticalityModifiers: Record = { + very_important: 2, + important: 1.5, + normal: 1, + not_important: 0.5, +}; diff --git a/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/helpers.test.ts b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/helpers.test.ts new file mode 100644 index 000000000000..9ec395223c93 --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/helpers.test.ts @@ -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 { applyCriticalityToScore, normalize } from './helpers'; + +describe('applyCriticalityToScore', () => { + describe('integer scores', () => { + it('returns the original score if the modifier is undefined', () => { + const result = applyCriticalityToScore({ modifier: undefined, score: 90 }); + expect(result).toEqual(90); + }); + + it('returns the original score if the modifier is 1', () => { + const result = applyCriticalityToScore({ modifier: 1, score: 90 }); + expect(result).toEqual(90); + }); + + it('returns an increased score if the modifier is greater than 1', () => { + const result = applyCriticalityToScore({ modifier: 1.5, score: 90 }); + expect(result).toEqual(93.10344827586206); + }); + + it('returns a decreased score if the modifier is less than 1', () => { + const result = applyCriticalityToScore({ modifier: 0.5, score: 90 }); + expect(result).toEqual(81.81818181818181); + }); + + it('does not exceed a score of 100 with a previous score of 99 and a large modifier', () => { + const result = applyCriticalityToScore({ modifier: 200, score: 99 }); + expect(result).toEqual(99.99494975001262); + }); + }); + + describe('non-integer scores', () => { + it('returns the original score if the modifier is undefined', () => { + const result = applyCriticalityToScore({ modifier: undefined, score: 90.5 }); + expect(result).toEqual(90.5); + }); + + it('returns the original score if the modifier is 1', () => { + const result = applyCriticalityToScore({ modifier: 1, score: 91.84 }); + expect(result).toEqual(91.84); + }); + it('returns an increased score if the modifier is greater than 1', () => { + const result = applyCriticalityToScore({ modifier: 1.5, score: 75.98 }); + expect(result).toEqual(82.59294151750127); + }); + + it('returns a decreased score if the modifier is less than 1', () => { + const result = applyCriticalityToScore({ modifier: 0.5, score: 44.12 }); + expect(result).toEqual(28.303823453938925); + }); + + it('does not exceed a score of 100 with a high previous score and a large modifier', () => { + const result = applyCriticalityToScore({ modifier: 200, score: 99.88 }); + expect(result).toEqual(99.9993992827436); + }); + }); +}); + +describe('normalize', () => { + it('returns 0 if the number is equal to the min', () => { + const result = normalize({ number: 0, min: 0, max: 100 }); + expect(result).toEqual(0); + }); + + it('returns 100 if the number is equal to the max', () => { + const result = normalize({ number: 100, min: 0, max: 100 }); + expect(result).toEqual(100); + }); + + it('returns 50 if the number is halfway between the min and max', () => { + const result = normalize({ number: 50, min: 0, max: 100 }); + expect(result).toEqual(50); + }); + + it('defaults to a min of 0', () => { + const result = normalize({ number: 50, max: 100 }); + expect(result).toEqual(50); + }); + + describe('when the domain is diffrent than the range', () => { + it('returns 0 if the number is equal to the min', () => { + const result = normalize({ number: 20, min: 20, max: 200 }); + expect(result).toEqual(0); + }); + + it('returns 100 if the number is equal to the max', () => { + const result = normalize({ number: 40, min: 30, max: 40 }); + expect(result).toEqual(100); + }); + + it('returns 50 if the number is halfway between the min and max', () => { + const result = normalize({ number: 20, min: 0, max: 40 }); + expect(result).toEqual(50); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/helpers.ts b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/helpers.ts new file mode 100644 index 000000000000..3c12fbc89b82 --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/helpers.ts @@ -0,0 +1,88 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { AssetCriticalityRecord } from '../../../../common/api/entity_analytics'; +import { RISK_SCORING_NORMALIZATION_MAX } from '../risk_score/constants'; +import { CriticalityModifiers } from './constants'; + +/** + * Retrieves the criticality modifier for a given criticality level. + * + * @param criticalityLevel The criticality level for which to get the modifier. + * @returns The associated criticality modifier for the given criticality level. + */ +export const getCriticalityModifier = ( + criticalityLevel?: AssetCriticalityRecord['criticality_level'] +): number | undefined => { + if (criticalityLevel == null) { + return; + } + + return CriticalityModifiers[criticalityLevel]; +}; + +/** + * Applies asset criticality to a normalized risk score using bayesian inference. + * @param modifier - The criticality modifier to apply to the score. + * @param score - The normalized risk score to which the criticality modifier is applied + * + * @returns The risk score with the criticality modifier applied. + */ +export const applyCriticalityToScore = ({ + modifier, + score, +}: { + modifier: number | undefined; + score: number; +}): number => { + if (modifier == null) { + return score; + } + + return bayesianUpdate({ max: RISK_SCORING_NORMALIZATION_MAX, modifier, score }); +}; + +/** + * Updates a score with the given modifier using bayesian inference. + * @param modifier - The modifier to be applied to the score. + * @param score - The score to modifiers are applied + * @param max - The maximum value of the score. + * + * @returns The updated score with modifiers applied + */ +export const bayesianUpdate = ({ + max, + modifier, + score, +}: { + max: number; + modifier: number; + score: number; +}) => { + const priorProbability = score / (max - score); + const newProbability = priorProbability * modifier; + return (max * newProbability) / (1 + newProbability); +}; + +/** + * Normalizes a number to the range [0, 100] + * + * @param number - The number to be normalized + * @param min - The minimum possible value of the number. Defaults to 0. + * @param max - The maximum possible value of the number + * + * @returns The updated score with modifiers applied + */ +export const normalize = ({ + number, + min = 0, + max, +}: { + number: number; + min?: number; + max: number; +}) => ((number - min) / (max - min)) * 100; diff --git a/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/index.ts b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/index.ts new file mode 100644 index 000000000000..7b8b38945dae --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/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 './asset_criticality_service'; +export * from './asset_criticality_data_client'; diff --git a/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/calculate_and_persist_risk_scores.ts b/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/calculate_and_persist_risk_scores.ts index 77258d313034..25bc1bddd99f 100644 --- a/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/calculate_and_persist_risk_scores.ts +++ b/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/calculate_and_persist_risk_scores.ts @@ -9,10 +9,12 @@ import type { ElasticsearchClient, Logger } from '@kbn/core/server'; import type { RiskScoreDataClient } from './risk_score_data_client'; import type { CalculateAndPersistScoresParams, CalculateAndPersistScoresResponse } from '../types'; +import type { AssetCriticalityService } from '../asset_criticality/asset_criticality_service'; import { calculateRiskScores } from './calculate_risk_scores'; export const calculateAndPersistRiskScores = async ( params: CalculateAndPersistScoresParams & { + assetCriticalityService: AssetCriticalityService; esClient: ElasticsearchClient; logger: Logger; spaceId: string; diff --git a/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/calculate_risk_scores.mock.ts b/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/calculate_risk_scores.mock.ts index 20db1f8d6173..fbfaaf11140d 100644 --- a/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/calculate_risk_scores.mock.ts +++ b/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/calculate_risk_scores.mock.ts @@ -23,7 +23,6 @@ const buildRiskScoreBucketMock = (overrides: Partial = {}): Ris value: { score: 20, normalized_score: 30.0, - level: 'Unknown', notes: [], category_1_score: 30, category_1_count: 1, @@ -88,11 +87,15 @@ const buildResponseMock = ( '@timestamp': '2021-08-19T20:55:59.000Z', id_field: 'host.name', id_value: 'hostname', + criticality_level: 'important', + criticality_modifier: 1.5, calculated_level: 'Unknown', calculated_score: 20, calculated_score_norm: 30, category_1_score: 30, category_1_count: 12, + category_2_score: 0, + category_2_count: 0, notes: [], inputs: [ { diff --git a/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/calculate_risk_scores.test.ts b/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/calculate_risk_scores.test.ts index f75fd94c42d3..30d3d2f0566e 100644 --- a/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/calculate_risk_scores.test.ts +++ b/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/calculate_risk_scores.test.ts @@ -7,6 +7,7 @@ import type { ElasticsearchClient, Logger } from '@kbn/core/server'; import { elasticsearchServiceMock, loggingSystemMock } from '@kbn/core/server/mocks'; +import { assetCriticalityServiceMock } from '../asset_criticality/asset_criticality_service.mock'; import { calculateRiskScores } from './calculate_risk_scores'; import { calculateRiskScoresMock } from './calculate_risk_scores.mock'; @@ -21,6 +22,7 @@ describe('calculateRiskScores()', () => { logger = loggingSystemMock.createLogger(); params = { afterKeys: {}, + assetCriticalityService: assetCriticalityServiceMock.create(), esClient, logger, index: 'index', @@ -184,7 +186,7 @@ describe('calculateRiskScores()', () => { '@timestamp': expect.any(String), id_field: expect.any(String), id_value: expect.any(String), - calculated_level: 'Unknown', + calculated_level: 'Low', calculated_score: expect.any(Number), calculated_score_norm: expect.any(Number), category_1_score: expect.any(Number), @@ -217,18 +219,44 @@ describe('calculateRiskScores()', () => { }); describe('error conditions', () => { - beforeEach(() => { - // stub out a rejected response + it('raises an error if elasticsearch client rejects', async () => { (esClient.search as jest.Mock).mockRejectedValueOnce({ aggregations: calculateRiskScoresMock.buildAggregationResponse(), }); - }); - it('raises an error if elasticsearch client rejects', () => { - expect.assertions(1); - expect(() => calculateRiskScores(params)).rejects.toEqual({ + await expect(() => calculateRiskScores(params)).rejects.toEqual({ aggregations: calculateRiskScoresMock.buildAggregationResponse(), }); }); + + describe('when the asset criticality service throws an error', () => { + beforeEach(() => { + (esClient.search as jest.Mock).mockResolvedValueOnce({ + aggregations: calculateRiskScoresMock.buildAggregationResponse(), + }); + ( + params.assetCriticalityService.getCriticalitiesByIdentifiers as jest.Mock + ).mockRejectedValueOnce(new Error('foo')); + }); + + it('logs the error but proceeds if asset criticality service throws', async () => { + await expect(calculateRiskScores(params)).resolves.toEqual( + expect.objectContaining({ + scores: expect.objectContaining({ + host: expect.arrayContaining([ + expect.objectContaining({ + calculated_level: expect.any(String), + id_field: expect.any(String), + id_value: expect.any(String), + }), + ]), + }), + }) + ); + expect(logger.warn).toHaveBeenCalledWith( + 'Error retrieving criticality: Error: foo. Scoring will proceed without criticality information.' + ); + }); + }); }); }); diff --git a/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/calculate_risk_scores.ts b/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/calculate_risk_scores.ts index a877bfd0f8e6..d9af3457d691 100644 --- a/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/calculate_risk_scores.ts +++ b/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/calculate_risk_scores.ts @@ -17,14 +17,22 @@ import { ALERT_WORKFLOW_STATUS, EVENT_KIND, } from '@kbn/rule-registry-plugin/common/technical_rule_data_field_names'; -import type { - AfterKeys, - IdentifierType, - RiskWeights, - RiskScore, +import { + type AfterKeys, + type IdentifierType, + type RiskWeights, + type RiskScore, + getRiskLevel, + RiskCategories, } from '../../../../common/entity_analytics/risk_engine'; -import { RiskCategories } from '../../../../common/entity_analytics/risk_engine'; import { withSecuritySpan } from '../../../utils/with_security_span'; +import type { AssetCriticalityRecord } from '../../../../common/api/entity_analytics'; +import type { AssetCriticalityService } from '../asset_criticality/asset_criticality_service'; +import { + applyCriticalityToScore, + getCriticalityModifier, + normalize, +} from '../asset_criticality/helpers'; import { getAfterKeyForIdentifierType, getFieldForIdentifierAgg } from './helpers'; import { buildCategoryCountDeclarations, @@ -39,34 +47,68 @@ import type { CalculateScoresResponse, RiskScoreBucket, } from '../types'; +import { + RISK_SCORING_INPUTS_COUNT_MAX, + RISK_SCORING_SUM_MAX, + RISK_SCORING_SUM_VALUE, +} from './constants'; -const bucketToResponse = ({ +const formatForResponse = ({ bucket, + criticality, now, identifierField, + includeNewFields, }: { bucket: RiskScoreBucket; + criticality?: AssetCriticalityRecord; now: string; identifierField: string; -}): RiskScore => ({ - '@timestamp': now, - id_field: identifierField, - id_value: bucket.key[identifierField], - calculated_level: bucket.risk_details.value.level, - calculated_score: bucket.risk_details.value.score, - calculated_score_norm: bucket.risk_details.value.normalized_score, - category_1_score: bucket.risk_details.value.category_1_score, - category_1_count: bucket.risk_details.value.category_1_count, - notes: bucket.risk_details.value.notes, - inputs: bucket.inputs.hits.hits.map((riskInput) => ({ - id: riskInput._id, - index: riskInput._index, - description: `Alert from Rule: ${riskInput.fields?.[ALERT_RULE_NAME]?.[0] ?? 'RULE_NOT_FOUND'}`, - category: RiskCategories.category_1, - risk_score: riskInput.fields?.[ALERT_RISK_SCORE]?.[0] ?? undefined, - timestamp: riskInput.fields?.['@timestamp']?.[0] ?? undefined, - })), -}); + includeNewFields: boolean; +}): RiskScore => { + const criticalityModifier = getCriticalityModifier(criticality?.criticality_level); + const normalizedScoreWithCriticality = applyCriticalityToScore({ + score: bucket.risk_details.value.normalized_score, + modifier: criticalityModifier, + }); + const calculatedLevel = getRiskLevel(normalizedScoreWithCriticality); + const categoryTwoScore = + normalizedScoreWithCriticality - bucket.risk_details.value.normalized_score; + const categoryTwoCount = criticalityModifier ? 1 : 0; + + const newFields = { + category_2_score: categoryTwoScore, + category_2_count: categoryTwoCount, + criticality_level: criticality?.criticality_level, + criticality_modifier: criticalityModifier, + }; + + return { + '@timestamp': now, + id_field: identifierField, + id_value: bucket.key[identifierField], + calculated_level: calculatedLevel, + calculated_score: bucket.risk_details.value.score, + calculated_score_norm: normalizedScoreWithCriticality, + category_1_score: normalize({ + number: bucket.risk_details.value.category_1_score, + max: RISK_SCORING_SUM_MAX, + }), + category_1_count: bucket.risk_details.value.category_1_count, + notes: bucket.risk_details.value.notes, + inputs: bucket.inputs.hits.hits.map((riskInput) => ({ + id: riskInput._id, + index: riskInput._index, + description: `Alert from Rule: ${ + riskInput.fields?.[ALERT_RULE_NAME]?.[0] ?? 'RULE_NOT_FOUND' + }`, + category: RiskCategories.category_1, + risk_score: riskInput.fields?.[ALERT_RISK_SCORE]?.[0] ?? undefined, + timestamp: riskInput.fields?.['@timestamp']?.[0] ?? undefined, + })), + ...(includeNewFields ? newFields : {}), + }; +}; const filterFromRange = (range: CalculateScoresParams['range']): QueryDslQueryContainer => ({ range: { '@timestamp': { lt: range.end, gte: range.start } }, @@ -108,22 +150,6 @@ const buildReduceScript = ({ results['score'] = total_score; results['normalized_score'] = score_norm; - if (score_norm < 20) { - results['level'] = 'Unknown' - } - else if (score_norm >= 20 && score_norm < 40) { - results['level'] = 'Low' - } - else if (score_norm >= 40 && score_norm < 70) { - results['level'] = 'Moderate' - } - else if (score_norm >= 70 && score_norm < 90) { - results['level'] = 'High' - } - else if (score_norm >= 90) { - results['level'] = 'Critical' - } - return results; `; }; @@ -184,9 +210,9 @@ const buildIdentifierTypeAggregation = ({ `, combine_script: 'return state;', params: { - max_risk_inputs_per_identity: 999999, - p: 1.5, - risk_cap: 261.2, + max_risk_inputs_per_identity: RISK_SCORING_INPUTS_COUNT_MAX, + p: RISK_SCORING_SUM_VALUE, + risk_cap: RISK_SCORING_SUM_MAX, }, reduce_script: buildReduceScript({ globalIdentifierTypeWeight }), }, @@ -195,8 +221,55 @@ const buildIdentifierTypeAggregation = ({ }; }; +const processScores = async ({ + assetCriticalityService, + buckets, + identifierField, + logger, + now, +}: { + assetCriticalityService: AssetCriticalityService; + buckets: RiskScoreBucket[]; + identifierField: string; + logger: Logger; + now: string; +}): Promise => { + if (buckets.length === 0) { + return []; + } + + if (!assetCriticalityService.isEnabled()) { + return buckets.map((bucket) => + formatForResponse({ bucket, now, identifierField, includeNewFields: false }) + ); + } + + const identifiers = buckets.map((bucket) => ({ + id_field: identifierField, + id_value: bucket.key[identifierField], + })); + + let criticalities: AssetCriticalityRecord[] = []; + try { + criticalities = await assetCriticalityService.getCriticalitiesByIdentifiers(identifiers); + } catch (e) { + logger.warn( + `Error retrieving criticality: ${e}. Scoring will proceed without criticality information.` + ); + } + + return buckets.map((bucket) => { + const criticality = criticalities.find( + (c) => c.id_field === identifierField && c.id_value === bucket.key[identifierField] + ); + + return formatForResponse({ bucket, criticality, identifierField, now, includeNewFields: true }); + }); +}; + export const calculateRiskScores = async ({ afterKeys: userAfterKeys, + assetCriticalityService, debug, esClient, filter: userFilter, @@ -208,6 +281,7 @@ export const calculateRiskScores = async ({ runtimeMappings, weights, }: { + assetCriticalityService: AssetCriticalityService; esClient: ElasticsearchClient; logger: Logger; } & CalculateScoresParams): Promise => @@ -274,16 +348,27 @@ export const calculateRiskScores = async ({ user: response.aggregations.user?.after_key, }; + const hostScores = await processScores({ + assetCriticalityService, + buckets: hostBuckets, + identifierField: 'host.name', + logger, + now, + }); + const userScores = await processScores({ + assetCriticalityService, + buckets: userBuckets, + identifierField: 'user.name', + logger, + now, + }); + return { ...(debug ? { request, response } : {}), after_keys: afterKeys, scores: { - host: hostBuckets.map((bucket) => - bucketToResponse({ bucket, identifierField: 'host.name', now }) - ), - user: userBuckets.map((bucket) => - bucketToResponse({ bucket, identifierField: 'user.name', now }) - ), + host: hostScores, + user: userScores, }, }; }); diff --git a/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/constants.ts b/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/constants.ts new file mode 100644 index 000000000000..57e67960f96e --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/constants.ts @@ -0,0 +1,27 @@ +/* + * 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. + */ + +/** + * The risk scoring algorithm uses a Riemann zeta function to sum an entity's risk inputs to a known, finite value (@see RISK_SCORING_SUM_MAX). It does so by assigning each input a weight based on its position in the list (ordered by score) of inputs. This value represents the complex variable s of Re(s) in traditional Riemann zeta function notation. + */ +export const RISK_SCORING_SUM_VALUE = 1.5; + +/** + * Represents the maximum possible risk score sum. This value is derived from RISK_SCORING_SUM_VALUE, but we store the precomputed value here to be used more conveniently in normalization. + * @see RISK_SCORING_SUM_VALUE + */ +export const RISK_SCORING_SUM_MAX = 261.2; + +/** + * The risk scoring algorithm can only process a finite number of risk inputs per identity; this value represents the maximum number of inputs that will be processed. + */ +export const RISK_SCORING_INPUTS_COUNT_MAX = 999999; + +/** + * This value represents the maximum possible risk score after normalization. + */ +export const RISK_SCORING_NORMALIZATION_MAX = 100; diff --git a/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/risk_engine_data_writer.test.ts b/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/risk_engine_data_writer.test.ts index ca2ad354320a..271d5511e6b7 100644 --- a/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/risk_engine_data_writer.test.ts +++ b/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/risk_engine_data_writer.test.ts @@ -51,6 +51,10 @@ describe('RiskEngineDataWriter', () => { "calculated_score_norm": 85.332, "category_1_count": 12, "category_1_score": 85, + "category_2_count": 0, + "category_2_score": 0, + "criticality_level": "very_important", + "criticality_modifier": 2, "id_field": "host.name", "id_value": "hostname", "inputs": Array [], @@ -73,6 +77,10 @@ describe('RiskEngineDataWriter', () => { "calculated_score_norm": 85.332, "category_1_count": 12, "category_1_score": 85, + "category_2_count": 0, + "category_2_score": 0, + "criticality_level": "very_important", + "criticality_modifier": 2, "id_field": "host.name", "id_value": "hostname", "inputs": Array [], @@ -117,6 +125,10 @@ describe('RiskEngineDataWriter', () => { "calculated_score_norm": 85.332, "category_1_count": 12, "category_1_score": 85, + "category_2_count": 0, + "category_2_score": 0, + "criticality_level": "very_important", + "criticality_modifier": 2, "id_field": "user.name", "id_value": "username_1", "inputs": Array [], @@ -139,6 +151,10 @@ describe('RiskEngineDataWriter', () => { "calculated_score_norm": 85.332, "category_1_count": 12, "category_1_score": 85, + "category_2_count": 0, + "category_2_score": 0, + "criticality_level": "very_important", + "criticality_modifier": 2, "id_field": "user.name", "id_value": "username_2", "inputs": Array [], @@ -189,6 +205,10 @@ describe('RiskEngineDataWriter', () => { "calculated_score_norm": 85.332, "category_1_count": 12, "category_1_score": 85, + "category_2_count": 0, + "category_2_score": 0, + "criticality_level": "very_important", + "criticality_modifier": 2, "id_field": "host.name", "id_value": "hostname_1", "inputs": Array [], @@ -211,6 +231,10 @@ describe('RiskEngineDataWriter', () => { "calculated_score_norm": 85.332, "category_1_count": 12, "category_1_score": 85, + "category_2_count": 0, + "category_2_score": 0, + "criticality_level": "very_important", + "criticality_modifier": 2, "id_field": "user.name", "id_value": "username_1", "inputs": Array [], @@ -233,6 +257,10 @@ describe('RiskEngineDataWriter', () => { "calculated_score_norm": 85.332, "category_1_count": 12, "category_1_score": 85, + "category_2_count": 0, + "category_2_score": 0, + "criticality_level": "very_important", + "criticality_modifier": 2, "id_field": "user.name", "id_value": "username_2", "inputs": Array [], diff --git a/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/risk_score_service.mock.ts b/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/risk_score_service.mock.ts index e72852f6ea47..5353d38fcaef 100644 --- a/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/risk_score_service.mock.ts +++ b/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/risk_score_service.mock.ts @@ -17,6 +17,10 @@ const createRiskScoreMock = (overrides: Partial = {}): RiskScore => ( calculated_score_norm: 85.332, category_1_score: 85, category_1_count: 12, + category_2_count: 0, + category_2_score: 0, + criticality_level: 'very_important', + criticality_modifier: 2, notes: [], inputs: [], ...overrides, diff --git a/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/risk_score_service.ts b/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/risk_score_service.ts index a89835c6c732..c62e4c3ead82 100644 --- a/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/risk_score_service.ts +++ b/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/risk_score_service.ts @@ -16,6 +16,7 @@ import type { import { calculateRiskScores } from './calculate_risk_scores'; import { calculateAndPersistRiskScores } from './calculate_and_persist_risk_scores'; import type { RiskEngineDataClient } from '../risk_engine/risk_engine_data_client'; +import type { AssetCriticalityService } from '../asset_criticality/asset_criticality_service'; import type { RiskScoreDataClient } from './risk_score_data_client'; import type { RiskInputsIndexResponse } from './get_risk_inputs_index'; import { scheduleLatestTransformNow } from '../utils/transforms'; @@ -31,6 +32,7 @@ export interface RiskScoreService { } export interface RiskScoreServiceFactoryParams { + assetCriticalityService: AssetCriticalityService; esClient: ElasticsearchClient; logger: Logger; riskEngineDataClient: RiskEngineDataClient; @@ -39,15 +41,24 @@ export interface RiskScoreServiceFactoryParams { } export const riskScoreServiceFactory = ({ + assetCriticalityService, esClient, logger, riskEngineDataClient, riskScoreDataClient, spaceId, }: RiskScoreServiceFactoryParams): RiskScoreService => ({ - calculateScores: (params) => calculateRiskScores({ ...params, esClient, logger }), + calculateScores: (params) => + calculateRiskScores({ ...params, assetCriticalityService, esClient, logger }), calculateAndPersistScores: (params) => - calculateAndPersistRiskScores({ ...params, esClient, logger, riskScoreDataClient, spaceId }), + calculateAndPersistRiskScores({ + ...params, + assetCriticalityService, + esClient, + logger, + riskScoreDataClient, + spaceId, + }), getConfiguration: async () => riskEngineDataClient.getConfiguration(), getRiskInputsIndex: async (params) => riskScoreDataClient.getRiskInputsIndex(params), scheduleLatestTransformNow: () => scheduleLatestTransformNow({ namespace: spaceId, esClient }), diff --git a/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/risk_weights.ts b/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/risk_weights.ts index f0af4360b863..de1754ba3de2 100644 --- a/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/risk_weights.ts +++ b/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/risk_weights.ts @@ -54,7 +54,7 @@ const getWeightForIdentifierType = (weight: RiskWeight, identifierType: Identifi }; export const buildCategoryScoreDeclarations = (): string => { - return RISK_CATEGORIES.map((riskCategory) => `results['${riskCategory}_score'] = 0;`).join(''); + return RISK_CATEGORIES.map((riskCategory) => `results['${riskCategory}_score'] = 0.0;`).join(''); }; export const buildCategoryCountDeclarations = (): string => { diff --git a/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/routes/calculation.test.ts b/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/routes/calculation.test.ts index 0a62695dfd68..fb5c366193cb 100644 --- a/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/routes/calculation.test.ts +++ b/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/routes/calculation.test.ts @@ -9,6 +9,7 @@ import { riskScoreCalculationRoute } from './calculation'; import { loggerMock } from '@kbn/logging-mocks'; +import type { ExperimentalFeatures } from '../../../../../common'; import { RISK_SCORE_CALCULATION_URL } from '../../../../../common/constants'; import { serverMock, @@ -44,7 +45,7 @@ describe('risk score calculation route', () => { clients.appClient.getAlertsIndex.mockReturnValue('default-alerts-index'); (riskScoreServiceFactory as jest.Mock).mockReturnValue(mockRiskScoreService); - riskScoreCalculationRoute(server.router, logger); + riskScoreCalculationRoute(server.router, logger, {} as ExperimentalFeatures); }); const buildRequest = (overrides: object = {}) => { diff --git a/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/routes/calculation.ts b/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/routes/calculation.ts index 1822c038b7d1..71f4d05712d6 100644 --- a/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/routes/calculation.ts +++ b/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/routes/calculation.ts @@ -14,12 +14,18 @@ import { RISK_SCORE_CALCULATION_URL, } from '../../../../../common/constants'; import { riskScoreCalculationRequestSchema } from '../../../../../common/entity_analytics/risk_engine/risk_score_calculation/request_schema'; +import type { ExperimentalFeatures } from '../../../../../common'; import type { SecuritySolutionPluginRouter } from '../../../../types'; import { buildRouteValidation } from '../../../../utils/build_validation/route_validation'; +import { assetCriticalityServiceFactory } from '../../asset_criticality'; import { riskScoreServiceFactory } from '../risk_score_service'; import { getRiskInputsIndex } from '../get_risk_inputs_index'; -export const riskScoreCalculationRoute = (router: SecuritySolutionPluginRouter, logger: Logger) => { +export const riskScoreCalculationRoute = ( + router: SecuritySolutionPluginRouter, + logger: Logger, + experimentalFeatures: ExperimentalFeatures +) => { router.versioned .post({ path: RISK_SCORE_CALCULATION_URL, @@ -42,8 +48,14 @@ export const riskScoreCalculationRoute = (router: SecuritySolutionPluginRouter, const spaceId = securityContext.getSpaceId(); const riskEngineDataClient = securityContext.getRiskEngineDataClient(); const riskScoreDataClient = securityContext.getRiskScoreDataClient(); + const assetCriticalityDataClient = securityContext.getAssetCriticalityDataClient(); + const assetCriticalityService = assetCriticalityServiceFactory({ + assetCriticalityDataClient, + experimentalFeatures, + }); const riskScoreService = riskScoreServiceFactory({ + assetCriticalityService, esClient, logger, riskEngineDataClient, diff --git a/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/routes/preview.test.ts b/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/routes/preview.test.ts index 9a525a5bae0d..71d108058a10 100644 --- a/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/routes/preview.test.ts +++ b/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/routes/preview.test.ts @@ -7,6 +7,7 @@ import { loggerMock } from '@kbn/logging-mocks'; +import type { ExperimentalFeatures } from '../../../../../common'; import { RISK_SCORE_PREVIEW_URL } from '../../../../../common/constants'; import { RiskCategories, @@ -48,7 +49,7 @@ describe('POST risk_engine/preview route', () => { clients.appClient.getAlertsIndex.mockReturnValue('default-alerts-index'); (riskScoreServiceFactory as jest.Mock).mockReturnValue(mockRiskScoreService); - riskScorePreviewRoute(server.router, logger); + riskScorePreviewRoute(server.router, logger, {} as ExperimentalFeatures); }); const buildRequest = (body: object = {}) => diff --git a/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/routes/preview.ts b/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/routes/preview.ts index 13f3ee8a9df0..db11cf84e904 100644 --- a/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/routes/preview.ts +++ b/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/routes/preview.ts @@ -15,12 +15,18 @@ import { RISK_SCORE_PREVIEW_URL, } from '../../../../../common/constants'; import { riskScorePreviewRequestSchema } from '../../../../../common/entity_analytics/risk_engine/risk_score_preview/request_schema'; +import type { ExperimentalFeatures } from '../../../../../common'; import type { SecuritySolutionPluginRouter } from '../../../../types'; import { buildRouteValidation } from '../../../../utils/build_validation/route_validation'; +import { assetCriticalityServiceFactory } from '../../asset_criticality'; import { riskScoreServiceFactory } from '../risk_score_service'; import { getRiskInputsIndex } from '../get_risk_inputs_index'; -export const riskScorePreviewRoute = (router: SecuritySolutionPluginRouter, logger: Logger) => { +export const riskScorePreviewRoute = ( + router: SecuritySolutionPluginRouter, + logger: Logger, + experimentalFeatures: ExperimentalFeatures +) => { router.versioned .post({ access: 'internal', @@ -43,8 +49,14 @@ export const riskScorePreviewRoute = (router: SecuritySolutionPluginRouter, logg const spaceId = securityContext.getSpaceId(); const riskEngineDataClient = securityContext.getRiskEngineDataClient(); const riskScoreDataClient = securityContext.getRiskScoreDataClient(); + const assetCriticalityDataClient = securityContext.getAssetCriticalityDataClient(); + const assetCriticalityService = assetCriticalityServiceFactory({ + assetCriticalityDataClient, + experimentalFeatures, + }); const riskScoreService = riskScoreServiceFactory({ + assetCriticalityService, esClient, logger, riskEngineDataClient, diff --git a/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/tasks/risk_scoring_task.test.ts b/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/tasks/risk_scoring_task.test.ts index 45562ac8d38a..bc3d5054980d 100644 --- a/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/tasks/risk_scoring_task.test.ts +++ b/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/tasks/risk_scoring_task.test.ts @@ -11,6 +11,7 @@ import { taskManagerMock } from '@kbn/task-manager-plugin/server/mocks'; import { loggerMock } from '@kbn/logging-mocks'; import type { AnalyticsServiceSetup } from '@kbn/core/public'; +import type { ExperimentalFeatures } from '../../../../../common'; import type { RiskScoreService } from '../risk_score_service'; import { riskScoreServiceMock } from '../risk_score_service.mock'; import { riskScoringTaskMock } from './risk_scoring_task.mock'; @@ -47,6 +48,7 @@ describe('Risk Scoring Task', () => { it('registers the task with TaskManager', () => { expect(mockTaskManagerSetup.registerTaskDefinitions).not.toHaveBeenCalled(); registerRiskScoringTask({ + experimentalFeatures: {} as ExperimentalFeatures, getStartServices: mockCore.getStartServices, kibanaVersion: '8.10.0', taskManager: mockTaskManagerSetup, @@ -59,6 +61,7 @@ describe('Risk Scoring Task', () => { it('does nothing if TaskManager is not available', () => { expect(mockTaskManagerSetup.registerTaskDefinitions).not.toHaveBeenCalled(); registerRiskScoringTask({ + experimentalFeatures: {} as ExperimentalFeatures, getStartServices: mockCore.getStartServices, kibanaVersion: '8.10.0', taskManager: undefined, diff --git a/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/tasks/risk_scoring_task.ts b/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/tasks/risk_scoring_task.ts index a1539167bbaf..421fb4092b92 100644 --- a/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/tasks/risk_scoring_task.ts +++ b/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_score/tasks/risk_scoring_task.ts @@ -18,7 +18,11 @@ import type { TaskManagerStartContract, } from '@kbn/task-manager-plugin/server'; import type { AnalyticsServiceSetup } from '@kbn/core-analytics-server'; -import type { AfterKeys, IdentifierType } from '../../../../../common/entity_analytics/risk_engine'; +import { + type AfterKeys, + type IdentifierType, + RiskScoreEntity, +} from '../../../../../common/entity_analytics/risk_engine'; import type { StartPlugins } from '../../../../plugin'; import { type RiskScoreService, riskScoreServiceFactory } from '../risk_score_service'; import { RiskEngineDataClient } from '../../risk_engine/risk_engine_data_client'; @@ -31,12 +35,16 @@ import { } from './state'; import { INTERVAL, SCOPE, TIMEOUT, TYPE, VERSION } from './constants'; import { buildScopedInternalSavedObjectsClientUnsafe, convertRangeToISO } from './helpers'; -import { RiskScoreEntity } from '../../../../../common/entity_analytics/risk_engine/types'; +import type { ExperimentalFeatures } from '../../../../../common'; import { RISK_SCORE_EXECUTION_SUCCESS_EVENT, RISK_SCORE_EXECUTION_ERROR_EVENT, RISK_SCORE_EXECUTION_CANCELLATION_EVENT, } from '../../../telemetry/event_based/events'; +import { + AssetCriticalityDataClient, + assetCriticalityServiceFactory, +} from '../../asset_criticality'; const logFactory = (logger: Logger, taskId: string) => @@ -50,12 +58,14 @@ const getTaskId = (namespace: string): string => `${TYPE}:${namespace}:${VERSION type GetRiskScoreService = (namespace: string) => Promise; export const registerRiskScoringTask = ({ + experimentalFeatures, getStartServices, kibanaVersion, logger, taskManager, telemetry, }: { + experimentalFeatures: ExperimentalFeatures; getStartServices: StartServicesAccessor; kibanaVersion: string; logger: Logger; @@ -71,6 +81,17 @@ export const registerRiskScoringTask = ({ getStartServices().then(([coreStart, _]) => { const esClient = coreStart.elasticsearch.client.asInternalUser; const soClient = buildScopedInternalSavedObjectsClientUnsafe({ coreStart, namespace }); + + const assetCriticalityDataClient = new AssetCriticalityDataClient({ + esClient, + logger, + namespace, + }); + const assetCriticalityService = assetCriticalityServiceFactory({ + assetCriticalityDataClient, + experimentalFeatures, + }); + const riskEngineDataClient = new RiskEngineDataClient({ logger, kibanaVersion, @@ -87,6 +108,7 @@ export const registerRiskScoringTask = ({ }); return riskScoreServiceFactory({ + assetCriticalityService, esClient, logger, riskEngineDataClient, diff --git a/x-pack/plugins/security_solution/server/lib/entity_analytics/types.ts b/x-pack/plugins/security_solution/server/lib/entity_analytics/types.ts index acdb1982011d..ea2464b8058a 100644 --- a/x-pack/plugins/security_solution/server/lib/entity_analytics/types.ts +++ b/x-pack/plugins/security_solution/server/lib/entity_analytics/types.ts @@ -117,7 +117,6 @@ export interface RiskScoreBucket { score: number; normalized_score: number; notes: string[]; - level: string; category_1_score: number; category_1_count: number; }; diff --git a/x-pack/plugins/security_solution/server/plugin.ts b/x-pack/plugins/security_solution/server/plugin.ts index 53141fc1751c..01154dc06f5f 100644 --- a/x-pack/plugins/security_solution/server/plugin.ts +++ b/x-pack/plugins/security_solution/server/plugin.ts @@ -183,6 +183,7 @@ export class Plugin implements ISecuritySolutionPlugin { if (experimentalFeatures.riskScoringPersistence) { registerRiskScoringTask({ + experimentalFeatures, getStartServices: core.getStartServices, kibanaVersion: pluginContext.env.packageInfo.version, logger: this.logger, 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 3deaaa103caa..3f1d9f818e43 100644 --- a/x-pack/plugins/security_solution/server/request_context_factory.ts +++ b/x-pack/plugins/security_solution/server/request_context_factory.ts @@ -27,7 +27,7 @@ import type { EndpointAuthz } from '../common/endpoint/types/authz'; import type { EndpointAppContextService } from './endpoint/endpoint_app_context_services'; import { RiskEngineDataClient } from './lib/entity_analytics/risk_engine/risk_engine_data_client'; import { RiskScoreDataClient } from './lib/entity_analytics/risk_score/risk_score_data_client'; -import { AssetCriticalityDataClient } from './lib/entity_analytics/asset_criticality/asset_criticality_data_client'; +import { AssetCriticalityDataClient } from './lib/entity_analytics/asset_criticality'; export interface IRequestContextFactory { create( diff --git a/x-pack/plugins/security_solution/server/routes/index.ts b/x-pack/plugins/security_solution/server/routes/index.ts index ce863fb86107..b32543ad7612 100644 --- a/x-pack/plugins/security_solution/server/routes/index.ts +++ b/x-pack/plugins/security_solution/server/routes/index.ts @@ -159,8 +159,8 @@ export const initRoutes = ( } if (config.experimentalFeatures.riskScoringRoutesEnabled) { - riskScorePreviewRoute(router, logger); - riskScoreCalculationRoute(router, logger); + riskScorePreviewRoute(router, logger, config.experimentalFeatures); + riskScoreCalculationRoute(router, logger, config.experimentalFeatures); riskEngineStatusRoute(router); riskEngineInitRoute(router, getStartServices); riskEngineEnableRoute(router, getStartServices); diff --git a/x-pack/plugins/security_solution/server/types.ts b/x-pack/plugins/security_solution/server/types.ts index a44572ae07ea..7833c1dff6b8 100644 --- a/x-pack/plugins/security_solution/server/types.ts +++ b/x-pack/plugins/security_solution/server/types.ts @@ -31,7 +31,7 @@ import type { EndpointAuthz } from '../common/endpoint/types/authz'; import type { EndpointInternalFleetServicesInterface } from './endpoint/services/fleet'; import type { RiskEngineDataClient } from './lib/entity_analytics/risk_engine/risk_engine_data_client'; import type { RiskScoreDataClient } from './lib/entity_analytics/risk_score/risk_score_data_client'; -import type { AssetCriticalityDataClient } from './lib/entity_analytics/asset_criticality/asset_criticality_data_client'; +import type { AssetCriticalityDataClient } from './lib/entity_analytics/asset_criticality'; export { AppClient }; export interface SecuritySolutionApiRequestHandlerContext { diff --git a/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/default_license/risk_engine/risk_score_calculation.ts b/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/default_license/risk_engine/risk_score_calculation.ts index 03f7734e4262..d4f5be1eff22 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/default_license/risk_engine/risk_score_calculation.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/default_license/risk_engine/risk_score_calculation.ts @@ -23,6 +23,9 @@ import { readRiskScores, normalizeScores, waitForRiskScoresToBePresent, + assetCriticalityRouteHelpersFactory, + cleanAssetCriticality, + waitForAssetCriticalityToBePresent, } from '../../utils'; import { FtrProviderContext } from '../../../../ftr_provider_context'; @@ -116,17 +119,17 @@ export default ({ getService }: FtrProviderContext): void => { const scores = await readRiskScores(es); expect(scores.length).to.eql(1); - expect(normalizeScores(scores)).to.eql([ - { - calculated_level: 'Unknown', - calculated_score: 21, - calculated_score_norm: 8.039816232771823, - category_1_score: 21, - category_1_count: 1, - id_field: 'host.name', - id_value: 'host-1', - }, - ]); + const [score] = normalizeScores(scores); + + expect(score).to.eql({ + calculated_level: 'Unknown', + calculated_score: 21, + calculated_score_norm: 8.039816232771823, + category_1_score: 8.039816232771821, + category_1_count: 1, + id_field: 'host.name', + id_value: 'host-1', + }); }); describe('paging through calculations', () => { @@ -269,6 +272,60 @@ export default ({ getService }: FtrProviderContext): void => { expect(scores.length).to.eql(10); }); }); + + describe('@skipInServerless with asset criticality data', () => { + const assetCriticalityRoutes = assetCriticalityRouteHelpersFactory(supertest); + + beforeEach(async () => { + await assetCriticalityRoutes.upsert({ + id_field: 'host.name', + id_value: 'host-1', + criticality_level: 'important', + }); + }); + + afterEach(async () => { + await cleanAssetCriticality({ log, es }); + }); + + it('calculates and persists risk scores with additional criticality metadata and modifiers', async () => { + const documentId = uuidv4(); + await indexListOfDocuments([buildDocument({ host: { name: 'host-1' } }, documentId)]); + await waitForAssetCriticalityToBePresent({ es, log }); + + const results = await calculateRiskScoreAfterRuleCreationAndExecution(documentId); + expect(results).to.eql({ + after_keys: { host: { 'host.name': 'host-1' } }, + errors: [], + scores_written: 1, + }); + + await waitForRiskScoresToBePresent({ es, log }); + const scores = await readRiskScores(es); + expect(scores.length).to.eql(1); + + const [score] = normalizeScores(scores); + expect(score).to.eql({ + criticality_level: 'important', + criticality_modifier: 1.5, + calculated_level: 'Unknown', + calculated_score: 21, + calculated_score_norm: 11.59366948840633, + category_1_score: 8.039816232771821, + category_1_count: 1, + id_field: 'host.name', + id_value: 'host-1', + }); + const [rawScore] = scores; + + expect( + rawScore.host?.risk.category_1_score! + rawScore.host?.risk.category_2_score! + ).to.be.within( + score.calculated_score_norm! - 0.000000000000001, + score.calculated_score_norm! + 0.000000000000001 + ); + }); + }); }); }); }; diff --git a/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/default_license/risk_engine/risk_score_preview.ts b/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/default_license/risk_engine/risk_score_preview.ts index e4284cdb5b83..bfb415bac02a 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/default_license/risk_engine/risk_score_preview.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/default_license/risk_engine/risk_score_preview.ts @@ -18,10 +18,13 @@ import { dataGeneratorFactory, } from '../../../detections_response/utils'; import { + assetCriticalityRouteHelpersFactory, buildDocument, + cleanAssetCriticality, createAndSyncRuleAndAlertsFactory, deleteAllRiskScores, sanitizeScores, + waitForAssetCriticalityToBePresent, } from '../../utils'; import { FtrProviderContext } from '../../../../ftr_provider_context'; @@ -99,18 +102,23 @@ export default ({ getService }: FtrProviderContext): void => { await indexListOfDocuments([buildDocument({ host: { name: 'host-1' } }, documentId)]); const body = await getRiskScoreAfterRuleCreationAndExecution(documentId); + const [score] = sanitizeScores(body.scores.host!); + const [rawScore] = body.scores.host!; + + expect(score).to.eql({ + calculated_level: 'Unknown', + calculated_score: 21, + calculated_score_norm: 8.039816232771823, + category_1_count: 1, + category_1_score: 8.039816232771821, + id_field: 'host.name', + id_value: 'host-1', + }); - expect(sanitizeScores(body.scores.host!)).to.eql([ - { - calculated_level: 'Unknown', - calculated_score: 21, - calculated_score_norm: 8.039816232771823, - category_1_count: 1, - category_1_score: 21, - id_field: 'host.name', - id_value: 'host-1', - }, - ]); + expect(rawScore.category_1_score! + rawScore.category_2_score!).to.be.within( + score.calculated_score_norm! - 0.000000000000001, + score.calculated_score_norm! + 0.000000000000001 + ); }); it('calculates risk from two alerts, each representing a unique host', async () => { @@ -130,7 +138,7 @@ export default ({ getService }: FtrProviderContext): void => { calculated_score: 21, calculated_score_norm: 8.039816232771823, category_1_count: 1, - category_1_score: 21, + category_1_score: 8.039816232771821, id_field: 'host.name', id_value: 'host-1', }, @@ -139,7 +147,7 @@ export default ({ getService }: FtrProviderContext): void => { calculated_score: 21, calculated_score_norm: 8.039816232771823, category_1_count: 1, - category_1_score: 21, + category_1_score: 8.039816232771821, id_field: 'host.name', id_value: 'host-2', }, @@ -163,7 +171,7 @@ export default ({ getService }: FtrProviderContext): void => { calculated_score: 28.42462120245875, calculated_score_norm: 10.88232052161514, category_1_count: 2, - category_1_score: 28, + category_1_score: 10.882320521615142, id_field: 'host.name', id_value: 'host-1', }, @@ -185,7 +193,7 @@ export default ({ getService }: FtrProviderContext): void => { calculated_score: 47.25513506055279, calculated_score_norm: 18.091552473412246, category_1_count: 30, - category_1_score: 37, + category_1_score: 18.091552473412246, id_field: 'host.name', id_value: 'host-1', }, @@ -210,7 +218,7 @@ export default ({ getService }: FtrProviderContext): void => { calculated_score: 47.25513506055279, calculated_score_norm: 18.091552473412246, category_1_count: 30, - category_1_score: 37, + category_1_score: 18.091552473412246, id_field: 'host.name', id_value: 'host-1', }, @@ -219,7 +227,7 @@ export default ({ getService }: FtrProviderContext): void => { calculated_score: 21, calculated_score_norm: 8.039816232771823, category_1_count: 1, - category_1_score: 21, + category_1_score: 8.039816232771821, id_field: 'host.name', id_value: 'host-2', }, @@ -241,7 +249,7 @@ export default ({ getService }: FtrProviderContext): void => { calculated_score: 50.67035607277805, calculated_score_norm: 19.399064346392823, category_1_count: 100, - category_1_score: 37, + category_1_score: 19.399064346392823, id_field: 'host.name', id_value: 'host-1', }, @@ -266,7 +274,7 @@ export default ({ getService }: FtrProviderContext): void => { calculated_score: 241.2874098703716, calculated_score_norm: 92.37649688758484, category_1_count: 100, - category_1_score: 209, + category_1_score: 92.37649688758484, id_field: 'host.name', id_value: 'host-1', }, @@ -297,7 +305,7 @@ export default ({ getService }: FtrProviderContext): void => { calculated_score: 254.91456029175757, calculated_score_norm: 97.59362951445543, category_1_count: 1000, - category_1_score: 209, + category_1_score: 97.59362951445543, id_field: 'host.name', id_value: 'host-1', }, @@ -393,7 +401,7 @@ export default ({ getService }: FtrProviderContext): void => { calculated_score: 225.1106801442913, calculated_score_norm: 86.18326192354185, category_1_count: 100, - category_1_score: 203, + category_1_score: 86.18326192354185, id_field: 'host.name', id_value: 'host-1', }, @@ -422,7 +430,7 @@ export default ({ getService }: FtrProviderContext): void => { calculated_score: 120.6437049351858, calculated_score_norm: 46.18824844379242, category_1_count: 100, - category_1_score: 209, + category_1_score: 92.37649688758484, id_field: 'host.name', id_value: 'host-1', }, @@ -449,7 +457,7 @@ export default ({ getService }: FtrProviderContext): void => { calculated_score: 168.9011869092601, calculated_score_norm: 64.66354782130938, category_1_count: 100, - category_1_score: 209, + category_1_score: 92.37649688758484, id_field: 'user.name', id_value: 'user-1', }, @@ -478,7 +486,7 @@ export default ({ getService }: FtrProviderContext): void => { calculated_score: 93.23759116471251, calculated_score_norm: 35.695861854790394, category_1_count: 50, - category_1_score: 209, + category_1_score: 89.23965463697598, id_field: 'host.name', id_value: 'host-1', }, @@ -490,7 +498,7 @@ export default ({ getService }: FtrProviderContext): void => { calculated_score: 186.47518232942502, calculated_score_norm: 71.39172370958079, category_1_count: 50, - category_1_score: 209, + category_1_score: 89.23965463697598, id_field: 'user.name', id_value: 'user-1', }, @@ -527,7 +535,7 @@ export default ({ getService }: FtrProviderContext): void => { calculated_level: 'Low', calculated_score: 93.2375911647125, calculated_score_norm: 35.695861854790394, - category_1_score: 77, + category_1_score: 35.69586185479039, category_1_count: 50, id_field: 'host.name', id_value: 'host-1', @@ -539,7 +547,7 @@ export default ({ getService }: FtrProviderContext): void => { calculated_level: 'High', calculated_score: 186.475182329425, calculated_score_norm: 71.39172370958079, - category_1_score: 165, + category_1_score: 71.39172370958077, category_1_count: 50, id_field: 'user.name', id_value: 'user-1', @@ -547,6 +555,58 @@ export default ({ getService }: FtrProviderContext): void => { ]); }); }); + + describe('@skipInServerless with asset criticality data', () => { + const assetCriticalityRoutes = assetCriticalityRouteHelpersFactory(supertest); + + beforeEach(async () => { + await assetCriticalityRoutes.upsert({ + id_field: 'host.name', + id_value: 'host-1', + criticality_level: 'very_important', + }); + }); + + afterEach(async () => { + await cleanAssetCriticality({ log, es }); + }); + + it('calculates and persists risk scores with additional criticality metadata and modifiers', async () => { + const documentId = uuidv4(); + await indexListOfDocuments([ + buildDocument({ host: { name: 'host-1' } }, documentId), + buildDocument({ host: { name: 'host-2' } }, documentId), + ]); + await waitForAssetCriticalityToBePresent({ es, log }); + + const body = await getRiskScoreAfterRuleCreationAndExecution(documentId, { + alerts: 2, + }); + + expect(sanitizeScores(body.scores.host!)).to.eql([ + { + criticality_level: 'very_important', + criticality_modifier: 2.0, + calculated_level: 'Unknown', + calculated_score: 21, + calculated_score_norm: 14.8830616583983, + category_1_count: 1, + category_1_score: 8.039816232771821, + id_field: 'host.name', + id_value: 'host-1', + }, + { + calculated_level: 'Unknown', + calculated_score: 21, + calculated_score_norm: 8.039816232771823, + category_1_count: 1, + category_1_score: 8.039816232771821, + id_field: 'host.name', + id_value: 'host-2', + }, + ]); + }); + }); }); }); }; diff --git a/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/default_license/risk_engine/risk_scoring_task/task_execution.ts b/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/default_license/risk_engine/risk_scoring_task/task_execution.ts index 7ebfb568e8cd..1f9c886b932f 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/default_license/risk_engine/risk_scoring_task/task_execution.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/default_license/risk_engine/risk_scoring_task/task_execution.ts @@ -23,6 +23,9 @@ import { getRiskEngineTask, waitForRiskEngineTaskToBeGone, cleanRiskEngine, + assetCriticalityRouteHelpersFactory, + cleanAssetCriticality, + waitForAssetCriticalityToBePresent, } from '../../../utils'; import { FtrProviderContext } from '../../../../../ftr_provider_context'; @@ -157,7 +160,8 @@ export default ({ getService }: FtrProviderContext): void => { await riskEngineRoutes.disable(); }); - describe('when task interval is modified', () => { + // Temporary, expected failure: See https://github.com/elastic/security-team/issues/8012 + describe.skip('when task interval is modified', () => { beforeEach(async () => { await updateRiskEngineConfigSO({ attributes: { @@ -179,8 +183,7 @@ export default ({ getService }: FtrProviderContext): void => { }); }); - // FLAKY: https://github.com/elastic/kibana/issues/171132 - describe.skip('with some alerts containing hosts and others containing users', () => { + describe('with some alerts containing hosts and others containing users', () => { let hostId: string; let userId: string; @@ -212,20 +215,68 @@ export default ({ getService }: FtrProviderContext): void => { alerts: 20, riskScore: 40, }); - - await riskEngineRoutes.init(); }); it('@skipInQA calculates and persists risk scores for both types of entities', async () => { + await riskEngineRoutes.init(); await waitForRiskScoresToBePresent({ es, log, scoreCount: 20 }); const riskScores = await readRiskScores(es); - expect(riskScores.length).to.eql(20); + expect(riskScores.length).to.be.greaterThan(0); const scoredIdentifiers = normalizeScores(riskScores).map( ({ id_field: idField }) => idField ); - expect(scoredIdentifiers.includes('host.name')).to.be(true); - expect(scoredIdentifiers.includes('user.name')).to.be(true); + expect(scoredIdentifiers).to.contain('host.name'); + expect(scoredIdentifiers).to.contain('user.name'); + }); + + context('@skipInServerless with asset criticality data', () => { + const assetCriticalityRoutes = assetCriticalityRouteHelpersFactory(supertest); + + beforeEach(async () => { + await assetCriticalityRoutes.upsert({ + id_field: 'host.name', + id_value: 'host-1', + criticality_level: 'very_important', + }); + }); + + afterEach(async () => { + await cleanAssetCriticality({ log, es }); + }); + + it('calculates risk scores with asset criticality data', async () => { + await waitForAssetCriticalityToBePresent({ es, log }); + await riskEngineRoutes.init(); + await waitForRiskScoresToBePresent({ es, log, scoreCount: 20 }); + const riskScores = await readRiskScores(es); + + expect(riskScores.length).to.be.greaterThan(0); + const assetCriticalityLevels = riskScores.map( + (riskScore) => riskScore.host?.risk.criticality_level + ); + const assetCriticalityModifiers = riskScores.map( + (riskScore) => riskScore.host?.risk.criticality_modifier + ); + + expect(assetCriticalityLevels).to.contain('very_important'); + expect(assetCriticalityModifiers).to.contain(2); + + const scoreWithCriticality = riskScores.find((score) => score.host?.name === 'host-1'); + expect(normalizeScores([scoreWithCriticality!])).to.eql([ + { + id_field: 'host.name', + id_value: 'host-1', + criticality_level: 'very_important', + criticality_modifier: 2, + calculated_level: 'Moderate', + calculated_score: 79.81345973382406, + calculated_score_norm: 46.809565696393314, + category_1_count: 10, + category_1_score: 30.55645472198471, + }, + ]); + }); }); }); }); diff --git a/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/utils/asset_criticality.ts b/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/utils/asset_criticality.ts index b745d1d0f705..6abcb908f608 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/utils/asset_criticality.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/utils/asset_criticality.ts @@ -15,10 +15,11 @@ import { ASSET_CRITICALITY_URL, ASSET_CRITICALITY_PRIVILEGES_URL, } from '@kbn/security-solution-plugin/common/constants'; +import type { AssetCriticalityRecord } from '@kbn/security-solution-plugin/common/api/entity_analytics'; import type { Client } from '@elastic/elasticsearch'; import type { ToolingLog } from '@kbn/tooling-log'; import querystring from 'querystring'; -import { routeWithNamespace } from '../../detections_response/utils'; +import { routeWithNamespace, waitFor } from '../../detections_response/utils'; export const getAssetCriticalityIndex = (namespace?: string) => `.asset-criticality.asset-criticality-${namespace ?? 'default'}`; @@ -123,3 +124,51 @@ export const assetCriticalityRouteHelpersFactoryNoAuth = ( .send() .expect(200), }); + +/** + * Function to read asset criticality records from ES. By default, it reads from the asset criticality index in the default space, but this can be overridden with the + * `index` parameter. + * + * @param {string[]} index - the index or indices to read criticality from. + * @param {number} size - the size parameter of the query + */ +export const readAssetCriticality = async ( + es: Client, + index: string[] = [getAssetCriticalityIndex()], + size: number = 1000 +): Promise => { + const results = await es.search({ + index, + size, + }); + return results.hits.hits.map((hit) => hit._source as AssetCriticalityRecord); +}; + +/** + * Function to read asset criticality from ES and wait for them to be + * present/readable. By default, it reads from the asset criticality index in the + * default space, but this can be overridden with the `index` parameter. + * + * @param {string[]} index - the index or indices to read asset criticality from. + * @param {number} docCount - the number of asset criticality docs to wait for. Defaults to 1. + */ +export const waitForAssetCriticalityToBePresent = async ({ + es, + log, + index = [getAssetCriticalityIndex()], + docCount = 1, +}: { + es: Client; + log: ToolingLog; + index?: string[]; + docCount?: number; +}): Promise => { + await waitFor( + async () => { + const criticalities = await readAssetCriticality(es, index, docCount + 10); + return criticalities.length >= docCount; + }, + 'waitForAssetCriticalityToBePresent', + log + ); +}; diff --git a/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/utils/index.ts b/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/utils/index.ts index dacdf5052c91..7ff049a997da 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/utils/index.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/utils/index.ts @@ -4,6 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ + export * from './risk_engine'; export * from './get_risk_engine_stats'; export * from './asset_criticality'; diff --git a/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/utils/risk_engine.ts b/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/utils/risk_engine.ts index 5a29900f5e8d..fb242e72bc89 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/utils/risk_engine.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/utils/risk_engine.ts @@ -37,11 +37,15 @@ import { } from '../../detections_response/utils'; const sanitizeScore = (score: Partial): Partial => { - delete score['@timestamp']; - delete score.inputs; - delete score.notes; - // delete score.category_1_score; - return score; + const { + '@timestamp': timestamp, + inputs, + notes, + category_2_count: cat2Count, + category_2_score: cat2Score, + ...rest + } = score; + return rest; }; export const sanitizeScores = (scores: Array>): Array> => From 94bdc0d5212412e41e8281a5235654546e2102cb Mon Sep 17 00:00:00 2001 From: Kevin Qualters <56408403+kqualters-elastic@users.noreply.github.com> Date: Thu, 4 Jan 2024 17:26:32 -0500 Subject: [PATCH 22/57] [Security Solution] [Timelines] Fix FilterManager being undefined when opening timeline from url (#171443) ## Summary Filter manager is not populated within redux if a user navigates to a url with timeline opened as the first step of entering the app. InitializeTimeline action is called, but the reducer just ignores any params at all if the initialize flag is set to true. Since this is only used in 2 places, and only 1 of which has an argument other than timelineId, I think this solution is fine. Should only ever result in fixing this bug it seems, as filterManager is either created anew or comes directly from the model. Issue: https://github.com/elastic/kibana/issues/171437 ### Checklist - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios --- .../public/timelines/store/helpers.ts | 8 ++- .../investigations/timelines/filters.cy.ts | 52 +++++++++++++++++++ .../cypress/screens/timeline.ts | 6 +++ 3 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/filters.cy.ts diff --git a/x-pack/plugins/security_solution/public/timelines/store/helpers.ts b/x-pack/plugins/security_solution/public/timelines/store/helpers.ts index 3206bb96e89a..456d716f529f 100644 --- a/x-pack/plugins/security_solution/public/timelines/store/helpers.ts +++ b/x-pack/plugins/security_solution/public/timelines/store/helpers.ts @@ -1475,7 +1475,13 @@ export const setInitializeTimelineSettings = ({ initialized: true, }, } - : timelineById; + : { + ...timelineById, + [id]: { + ...timeline, + ...timelineSettingsProps, + }, + }; }; interface ApplyDeltaToTableColumnWidth { diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/filters.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/filters.cy.ts new file mode 100644 index 000000000000..d87639a231f5 --- /dev/null +++ b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/filters.cy.ts @@ -0,0 +1,52 @@ +/* + * 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 { login } from '../../../tasks/login'; +import { visitWithTimeRange } from '../../../tasks/navigation'; +import { + createNewTimeline, + addNameAndDescriptionToTimeline, + populateTimeline, +} from '../../../tasks/timeline'; +import { openTimelineUsingToggle } from '../../../tasks/security_main'; +import { ALERTS_URL } from '../../../urls/navigation'; +import { getTimeline } from '../../../objects/timeline'; +import { + GET_TIMELINE_GRID_CELL, + TIMELINE_FILTER_FOR, + TIMELINE_FILTER_OUT, + TIMELINE_EVENT, + TIMELINE_FILTER_BADGE_ENABLED, +} from '../../../screens/timeline'; + +describe( + `timleine cell actions`, + { + tags: ['@ess'], + }, + () => { + beforeEach(() => { + login(); + visitWithTimeRange(ALERTS_URL); + openTimelineUsingToggle(); + createNewTimeline(); + addNameAndDescriptionToTimeline(getTimeline()); + populateTimeline(); + }); + it('filter in', () => { + cy.get(GET_TIMELINE_GRID_CELL('event.category')).trigger('mouseover'); + cy.get(TIMELINE_FILTER_FOR).should('be.visible').click(); + cy.get(TIMELINE_FILTER_BADGE_ENABLED).should('be.visible'); + }); + + it('filter out', () => { + cy.get(GET_TIMELINE_GRID_CELL('event.category')).trigger('mouseover'); + cy.get(TIMELINE_FILTER_OUT).should('be.visible').click(); + cy.get(TIMELINE_EVENT).should('not.exist'); + }); + } +); diff --git a/x-pack/test/security_solution_cypress/cypress/screens/timeline.ts b/x-pack/test/security_solution_cypress/cypress/screens/timeline.ts index b498d3d6bc32..2794a111e94c 100644 --- a/x-pack/test/security_solution_cypress/cypress/screens/timeline.ts +++ b/x-pack/test/security_solution_cypress/cypress/screens/timeline.ts @@ -284,6 +284,12 @@ export const HOVER_ACTIONS = { SHOW_TOP: '[data-test-subj=show-top-field]', }; +export const TIMELINE_FILTER_OUT = '[data-test-subj="filter-out-value"]'; + +export const TIMELINE_FILTER_FOR = '[data-test-subj="filter-for-value"]'; + +export const TIMELINE_FILTER_BADGE_ENABLED = '[data-test-subj~="filter-enabled"]'; + export const GET_TIMELINE_HEADER = (fieldName: string) => { return `[data-test-subj="timeline"] [data-test-subj="header-text-${fieldName}"]`; }; From 2fcbea2d7cff47e0911096c311bb63ce43036ad7 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Thu, 4 Jan 2024 15:30:17 -0700 Subject: [PATCH 23/57] [geo_containment alert] replace alertFactory with alertsClient (#173867) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes https://github.com/elastic/kibana/issues/167321 PR does not provide any custom fields for payload because geo containment alert has very little usage and will be [disabled in serverless](https://github.com/elastic/kibana/pull/174121), with the goal of deprecating and removing geo containment alert in the future. --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Mike Côté --- .../geo_containment/executor.test.ts | 86 ++++++-------- .../rule_types/geo_containment/executor.ts | 18 ++- .../get_entities_and_generate_alerts.test.ts | 107 +++++++----------- .../lib/get_entities_and_generate_alerts.ts | 12 +- .../rule_types/geo_containment/rule_type.ts | 3 + 5 files changed, 97 insertions(+), 129 deletions(-) diff --git a/x-pack/plugins/stack_alerts/server/rule_types/geo_containment/executor.test.ts b/x-pack/plugins/stack_alerts/server/rule_types/geo_containment/executor.test.ts index cec83d2cf9e7..cb0606594c09 100644 --- a/x-pack/plugins/stack_alerts/server/rule_types/geo_containment/executor.test.ts +++ b/x-pack/plugins/stack_alerts/server/rule_types/geo_containment/executor.test.ts @@ -5,50 +5,16 @@ * 2.0. */ -import _ from 'lodash'; import { elasticsearchServiceMock } from '@kbn/core/server/mocks'; import { RuleExecutorServicesMock, alertsMock } from '@kbn/alerting-plugin/server/mocks'; import sampleAggsJsonResponse from './tests/es_sample_response.json'; import sampleShapesJsonResponse from './tests/es_sample_response_shapes.json'; import { executor } from './executor'; -import type { - GeoContainmentRuleParams, - GeoContainmentAlertInstanceState, - GeoContainmentAlertInstanceContext, -} from './types'; +import type { GeoContainmentRuleParams, GeoContainmentAlertInstanceContext } from './types'; -const alertFactory = (contextKeys: unknown[], testAlertActionArr: unknown[]) => ({ - create: (instanceId: string) => { - const alertInstance = alertsMock.createAlertFactory.create< - GeoContainmentAlertInstanceState, - GeoContainmentAlertInstanceContext - >(); - (alertInstance.scheduleActions as jest.Mock).mockImplementation( - (actionGroupId: string, context?: GeoContainmentAlertInstanceContext) => { - // Check subset of alert for comparison to expected results - // @ts-ignore - const contextSubset = _.pickBy(context, (v, k) => contextKeys.includes(k)); - testAlertActionArr.push({ - actionGroupId, - instanceId, - context: contextSubset, - }); - } - ); - return alertInstance; - }, - alertLimit: { - getValue: () => 1000, - setLimitReached: () => {}, - }, - done: () => ({ getRecoveredAlerts: () => [] }), -}); - -describe('getGeoContainmentExecutor', () => { - // Params needed for all tests - const expectedAlertResults = [ +describe('executor', () => { + const expectedAlerts = [ { - actionGroupId: 'Tracked entity contained', context: { containingBoundaryId: 'kFATGXkBsFLYN2Tj6AAk', entityDocumentId: 'ZVBoGXkBsFLYN2Tj1wmV', @@ -58,7 +24,6 @@ describe('getGeoContainmentExecutor', () => { instanceId: '0-kFATGXkBsFLYN2Tj6AAk', }, { - actionGroupId: 'Tracked entity contained', context: { containingBoundaryId: 'kFATGXkBsFLYN2Tj6AAk', entityDocumentId: 'ZlBoGXkBsFLYN2Tj1wmV', @@ -68,7 +33,7 @@ describe('getGeoContainmentExecutor', () => { instanceId: '1-kFATGXkBsFLYN2Tj6AAk', }, ]; - const testAlertActionArr: unknown[] = []; + const previousStartedAt = new Date('2021-04-27T16:56:11.923Z'); const startedAt = new Date('2021-04-29T16:56:11.923Z'); const geoContainmentParams: GeoContainmentRuleParams = { @@ -99,7 +64,6 @@ describe('getGeoContainmentExecutor', () => { // Boundary test mocks const boundaryCall = jest.fn(); const esAggCall = jest.fn(); - const contextKeys = Object.keys(expectedAlertResults[0].context); const esClient = elasticsearchServiceMock.createElasticsearchClient(); // @ts-ignore incomplete return type esClient.search.mockResponseImplementation(({ index }) => { @@ -112,10 +76,26 @@ describe('getGeoContainmentExecutor', () => { } }); - const alertServicesWithSearchMock: RuleExecutorServicesMock = { + const alerts: unknown[] = []; + const servicesMock: RuleExecutorServicesMock = { ...alertsMock.createRuleExecutorServices(), // @ts-ignore - alertFactory: alertFactory(contextKeys, testAlertActionArr), + alertsClient: { + getRecoveredAlerts: () => { + return []; + }, + report: ({ id, context }: { id: string; context: GeoContainmentAlertInstanceContext }) => { + alerts.push({ + context: { + containingBoundaryId: context.containingBoundaryId, + entityDocumentId: context.entityDocumentId, + entityId: context.entityId, + entityLocation: context.entityLocation, + }, + instanceId: id, + }); + }, + }, // @ts-ignore scopedClusterClient: { asCurrentUser: esClient, @@ -124,7 +104,7 @@ describe('getGeoContainmentExecutor', () => { beforeEach(() => { jest.clearAllMocks(); - testAlertActionArr.length = 0; + alerts.length = 0; }); test('should query for shapes if state does not contain shapes', async () => { @@ -132,7 +112,7 @@ describe('getGeoContainmentExecutor', () => { previousStartedAt, startedAt, // @ts-ignore - services: alertServicesWithSearchMock, + services: servicesMock, params: geoContainmentParams, // @ts-ignore rule: { @@ -145,7 +125,7 @@ describe('getGeoContainmentExecutor', () => { expect(boundaryCall.mock.calls.length).toBe(1); expect(esAggCall.mock.calls.length).toBe(1); } - expect(testAlertActionArr).toMatchObject(expectedAlertResults); + expect(alerts).toMatchObject(expectedAlerts); }); test('should query for shapes if boundaries request meta changes', async () => { @@ -153,7 +133,7 @@ describe('getGeoContainmentExecutor', () => { previousStartedAt, startedAt, // @ts-ignore - services: alertServicesWithSearchMock, + services: servicesMock, params: geoContainmentParams, // @ts-ignore rule: { @@ -172,7 +152,7 @@ describe('getGeoContainmentExecutor', () => { expect(boundaryCall.mock.calls.length).toBe(1); expect(esAggCall.mock.calls.length).toBe(1); } - expect(testAlertActionArr).toMatchObject(expectedAlertResults); + expect(alerts).toMatchObject(expectedAlerts); }); test('should not query for shapes if state contains shapes', async () => { @@ -180,7 +160,7 @@ describe('getGeoContainmentExecutor', () => { previousStartedAt, startedAt, // @ts-ignore - services: alertServicesWithSearchMock, + services: servicesMock, params: geoContainmentParams, // @ts-ignore rule: { @@ -192,7 +172,7 @@ describe('getGeoContainmentExecutor', () => { expect(boundaryCall.mock.calls.length).toBe(0); expect(esAggCall.mock.calls.length).toBe(1); } - expect(testAlertActionArr).toMatchObject(expectedAlertResults); + expect(alerts).toMatchObject(expectedAlerts); }); test('should carry through shapes filters in state to next call unmodified', async () => { @@ -200,7 +180,7 @@ describe('getGeoContainmentExecutor', () => { previousStartedAt, startedAt, // @ts-ignore - services: alertServicesWithSearchMock, + services: servicesMock, params: geoContainmentParams, // @ts-ignore rule: { @@ -211,7 +191,7 @@ describe('getGeoContainmentExecutor', () => { if (executionResult && executionResult.state.shapesFilters) { expect(executionResult.state.shapesFilters).toEqual(geoContainmentState.shapesFilters); } - expect(testAlertActionArr).toMatchObject(expectedAlertResults); + expect(alerts).toMatchObject(expectedAlerts); }); test('should return previous locations map', async () => { @@ -239,7 +219,7 @@ describe('getGeoContainmentExecutor', () => { previousStartedAt, startedAt, // @ts-ignore - services: alertServicesWithSearchMock, + services: servicesMock, params: geoContainmentParams, // @ts-ignore rule: { @@ -250,6 +230,6 @@ describe('getGeoContainmentExecutor', () => { if (executionResult && executionResult.state.prevLocationMap) { expect(executionResult.state.prevLocationMap).toEqual(expectedPrevLocationMap); } - expect(testAlertActionArr).toMatchObject(expectedAlertResults); + expect(alerts).toMatchObject(expectedAlerts); }); }); diff --git a/x-pack/plugins/stack_alerts/server/rule_types/geo_containment/executor.ts b/x-pack/plugins/stack_alerts/server/rule_types/geo_containment/executor.ts index e7681eb4dee2..b6462aec3249 100644 --- a/x-pack/plugins/stack_alerts/server/rule_types/geo_containment/executor.ts +++ b/x-pack/plugins/stack_alerts/server/rule_types/geo_containment/executor.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { AlertsClientError } from '@kbn/alerting-plugin/server'; import { RuleExecutorOptions } from '../../types'; import { canSkipBoundariesFetch, @@ -45,6 +46,11 @@ export async function executor({ boundaryNameField: params.boundaryNameField, boundaryIndexQuery: params.boundaryIndexQuery, }; + + if (!services.alertsClient) { + throw new AlertsClientError(); + } + const { shapesFilters, shapesIdsNamesMap } = state.shapesFilters && canSkipBoundariesFetch(boundariesRequestMeta, state.boundariesRequestMeta) @@ -82,14 +88,13 @@ export async function executor({ const { activeEntities, inactiveEntities } = getEntitiesAndGenerateAlerts( prevLocationMap, currLocationMap, - services.alertFactory, + services.alertsClient, shapesIdsNamesMap, windowEnd ); - const { getRecoveredAlerts } = services.alertFactory.done(); - for (const recoveredAlert of getRecoveredAlerts()) { - const recoveredAlertId = recoveredAlert.getId(); + for (const recoveredAlert of services.alertsClient.getRecoveredAlerts()) { + const recoveredAlertId = recoveredAlert.alert.getId(); try { const context = getRecoveredAlertContext({ alertId: recoveredAlertId, @@ -98,7 +103,10 @@ export async function executor({ windowEnd, }); if (context) { - recoveredAlert.setContext(context); + services.alertsClient?.setAlertData({ + id: recoveredAlertId, + context, + }); } } catch (e) { logger.warn(`Unable to set alert context for recovered alert, error: ${e.message}`); diff --git a/x-pack/plugins/stack_alerts/server/rule_types/geo_containment/lib/get_entities_and_generate_alerts.test.ts b/x-pack/plugins/stack_alerts/server/rule_types/geo_containment/lib/get_entities_and_generate_alerts.test.ts index 339e53b03056..c8e8dd8faa4d 100644 --- a/x-pack/plugins/stack_alerts/server/rule_types/geo_containment/lib/get_entities_and_generate_alerts.test.ts +++ b/x-pack/plugins/stack_alerts/server/rule_types/geo_containment/lib/get_entities_and_generate_alerts.test.ts @@ -5,47 +5,28 @@ * 2.0. */ -import _ from 'lodash'; -import { alertsMock } from '@kbn/alerting-plugin/server/mocks'; import { getEntitiesAndGenerateAlerts } from './get_entities_and_generate_alerts'; import { OTHER_CATEGORY } from '../constants'; -import type { - GeoContainmentAlertInstanceState, - GeoContainmentAlertInstanceContext, -} from '../types'; - -const alertFactory = (contextKeys: unknown[], testAlertActionArr: unknown[]) => ({ - create: (instanceId: string) => { - const alertInstance = alertsMock.createAlertFactory.create< - GeoContainmentAlertInstanceState, - GeoContainmentAlertInstanceContext - >(); - (alertInstance.scheduleActions as jest.Mock).mockImplementation( - (actionGroupId: string, context?: GeoContainmentAlertInstanceContext) => { - // Check subset of alert for comparison to expected results - // @ts-ignore - const contextSubset = _.pickBy(context, (v, k) => contextKeys.includes(k)); - testAlertActionArr.push({ - actionGroupId, - instanceId, - context: contextSubset, - }); - } - ); - return alertInstance; - }, - alertLimit: { - getValue: () => 1000, - setLimitReached: () => {}, - }, - done: () => ({ getRecoveredAlerts: () => [] }), -}); +import type { GeoContainmentAlertInstanceContext } from '../types'; describe('getEntitiesAndGenerateAlerts', () => { - const testAlertActionArr: unknown[] = []; + const alerts: unknown[] = []; + const mockAlertsClient = { + report: ({ id, context }: { id: string; context: GeoContainmentAlertInstanceContext }) => { + alerts.push({ + context: { + containingBoundaryId: context.containingBoundaryId, + entityDocumentId: context.entityDocumentId, + entityId: context.entityId, + entityLocation: context.entityLocation, + }, + instanceId: id, + }); + }, + } as any; // eslint-disable-line @typescript-eslint/no-explicit-any + beforeEach(() => { - jest.clearAllMocks(); - testAlertActionArr.length = 0; + alerts.length = 0; }); const currLocationMap = new Map([ @@ -87,9 +68,8 @@ describe('getEntitiesAndGenerateAlerts', () => { ], ]); - const expectedAlertResults = [ + const expectedAlerts = [ { - actionGroupId: 'Tracked entity contained', context: { containingBoundaryId: '123', entityDocumentId: 'docId1', @@ -99,7 +79,6 @@ describe('getEntitiesAndGenerateAlerts', () => { instanceId: 'a-123', }, { - actionGroupId: 'Tracked entity contained', context: { containingBoundaryId: '456', entityDocumentId: 'docId2', @@ -109,7 +88,6 @@ describe('getEntitiesAndGenerateAlerts', () => { instanceId: 'b-456', }, { - actionGroupId: 'Tracked entity contained', context: { containingBoundaryId: '789', entityDocumentId: 'docId3', @@ -119,7 +97,6 @@ describe('getEntitiesAndGenerateAlerts', () => { instanceId: 'c-789', }, ]; - const contextKeys = Object.keys(expectedAlertResults[0].context); const emptyShapesIdsNamesMap = {}; const currentDateTime = new Date(); @@ -129,12 +106,12 @@ describe('getEntitiesAndGenerateAlerts', () => { const { activeEntities } = getEntitiesAndGenerateAlerts( emptyPrevLocationMap, currLocationMap, - alertFactory(contextKeys, testAlertActionArr), + mockAlertsClient, emptyShapesIdsNamesMap, currentDateTime ); expect(activeEntities).toEqual(currLocationMap); - expect(testAlertActionArr).toMatchObject(expectedAlertResults); + expect(alerts).toMatchObject(expectedAlerts); }); test('should overwrite older identical entity entries', () => { @@ -155,12 +132,12 @@ describe('getEntitiesAndGenerateAlerts', () => { const { activeEntities } = getEntitiesAndGenerateAlerts( prevLocationMapWithIdenticalEntityEntry, currLocationMap, - alertFactory(contextKeys, testAlertActionArr), + mockAlertsClient, emptyShapesIdsNamesMap, currentDateTime ); expect(activeEntities).toEqual(currLocationMap); - expect(testAlertActionArr).toMatchObject(expectedAlertResults); + expect(alerts).toMatchObject(expectedAlerts); }); test('should preserve older non-identical entity entries', () => { @@ -178,30 +155,28 @@ describe('getEntitiesAndGenerateAlerts', () => { ], ], ]); - const expectedAlertResultsPlusD = [ - { - actionGroupId: 'Tracked entity contained', - context: { - containingBoundaryId: '999', - entityDocumentId: 'docId7', - entityId: 'd', - entityLocation: 'POINT (0 0)', - }, - instanceId: 'd-999', - }, - ...expectedAlertResults, - ]; const { activeEntities } = getEntitiesAndGenerateAlerts( prevLocationMapWithNonIdenticalEntityEntry, currLocationMap, - alertFactory(contextKeys, testAlertActionArr), + mockAlertsClient, emptyShapesIdsNamesMap, currentDateTime ); expect(activeEntities).not.toEqual(currLocationMap); expect(activeEntities.has('d')).toBeTruthy(); - expect(testAlertActionArr).toMatchObject(expectedAlertResultsPlusD); + expect(alerts).toMatchObject([ + { + context: { + containingBoundaryId: '999', + entityDocumentId: 'docId7', + entityId: 'd', + entityLocation: 'POINT (0 0)', + }, + instanceId: 'd-999', + }, + ...expectedAlerts, + ]); }); test('should remove "other" entries and schedule the expected number of actions', () => { @@ -219,7 +194,7 @@ describe('getEntitiesAndGenerateAlerts', () => { const { activeEntities, inactiveEntities } = getEntitiesAndGenerateAlerts( emptyPrevLocationMap, currLocationMapWithOther, - alertFactory(contextKeys, testAlertActionArr), + mockAlertsClient, emptyShapesIdsNamesMap, currentDateTime ); @@ -240,7 +215,7 @@ describe('getEntitiesAndGenerateAlerts', () => { ], ]) ); - expect(testAlertActionArr).toMatchObject(expectedAlertResults); + expect(alerts).toMatchObject(expectedAlerts); }); test('should generate multiple alerts per entity if found in multiple shapes in interval', () => { @@ -271,7 +246,7 @@ describe('getEntitiesAndGenerateAlerts', () => { getEntitiesAndGenerateAlerts( emptyPrevLocationMap, currLocationMapWithThreeMore, - alertFactory(contextKeys, testAlertActionArr), + mockAlertsClient, emptyShapesIdsNamesMap, currentDateTime ); @@ -279,7 +254,7 @@ describe('getEntitiesAndGenerateAlerts', () => { currLocationMapWithThreeMore.forEach((v) => { numEntitiesInShapes += v.length; }); - expect(testAlertActionArr.length).toEqual(numEntitiesInShapes); + expect(alerts.length).toEqual(numEntitiesInShapes); }); test('should not return entity as active entry if most recent location is "other"', () => { @@ -311,7 +286,7 @@ describe('getEntitiesAndGenerateAlerts', () => { const { activeEntities } = getEntitiesAndGenerateAlerts( emptyPrevLocationMap, currLocationMapWithOther, - alertFactory(contextKeys, testAlertActionArr), + mockAlertsClient, emptyShapesIdsNamesMap, currentDateTime ); @@ -346,7 +321,7 @@ describe('getEntitiesAndGenerateAlerts', () => { const { activeEntities } = getEntitiesAndGenerateAlerts( emptyPrevLocationMap, currLocationMapWithOther, - alertFactory(contextKeys, testAlertActionArr), + mockAlertsClient, emptyShapesIdsNamesMap, currentDateTime ); diff --git a/x-pack/plugins/stack_alerts/server/rule_types/geo_containment/lib/get_entities_and_generate_alerts.ts b/x-pack/plugins/stack_alerts/server/rule_types/geo_containment/lib/get_entities_and_generate_alerts.ts index c0d372e08dce..5ec7fcedb5ee 100644 --- a/x-pack/plugins/stack_alerts/server/rule_types/geo_containment/lib/get_entities_and_generate_alerts.ts +++ b/x-pack/plugins/stack_alerts/server/rule_types/geo_containment/lib/get_entities_and_generate_alerts.ts @@ -17,11 +17,11 @@ import { getAlertId, getContainedAlertContext } from './alert_context'; export function getEntitiesAndGenerateAlerts( prevLocationMap: Map, currLocationMap: Map, - alertFactory: RuleExecutorServices< + alertsClient: RuleExecutorServices< GeoContainmentAlertInstanceState, GeoContainmentAlertInstanceContext, typeof ActionGroupId - >['alertFactory'], + >['alertsClient'], shapesIdsNamesMap: Record, windowEnd: Date ): { @@ -43,9 +43,11 @@ export function getEntitiesAndGenerateAlerts( shapesIdsNamesMap, windowEnd, }); - alertFactory - .create(getAlertId(entityName, context.containingBoundaryName)) - .scheduleActions(ActionGroupId, context); + alertsClient!.report({ + id: getAlertId(entityName, context.containingBoundaryName), + actionGroup: ActionGroupId, + context, + }); } }); diff --git a/x-pack/plugins/stack_alerts/server/rule_types/geo_containment/rule_type.ts b/x-pack/plugins/stack_alerts/server/rule_types/geo_containment/rule_type.ts index 832e6499dc02..f7ea3b360145 100644 --- a/x-pack/plugins/stack_alerts/server/rule_types/geo_containment/rule_type.ts +++ b/x-pack/plugins/stack_alerts/server/rule_types/geo_containment/rule_type.ts @@ -17,6 +17,7 @@ import type { } from './types'; import { executor } from './executor'; import { ActionGroupId, RecoveryActionGroupId, GEO_CONTAINMENT_ID } from './constants'; +import { STACK_ALERTS_AAD_CONFIG } from '../constants'; const actionVariables = { context: [ @@ -200,5 +201,7 @@ export function getRuleType(): GeoContainmentRuleType { return injectEntityAndBoundaryIds(params, references); }, }, + // @ts-ignore + alerts: STACK_ALERTS_AAD_CONFIG, }; } From 178583c11dcdbb5dbe0a09db4060fdbe92b8dd6a Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Fri, 5 Jan 2024 01:00:18 -0500 Subject: [PATCH 24/57] [api-docs] 2024-01-05 Daily api_docs build (#174318) Generated by https://buildkite.com/elastic/kibana-api-docs-daily/builds/573 --- api_docs/actions.mdx | 2 +- api_docs/advanced_settings.mdx | 2 +- .../ai_assistant_management_observability.mdx | 2 +- .../ai_assistant_management_selection.mdx | 2 +- api_docs/aiops.mdx | 2 +- api_docs/alerting.devdocs.json | 12 - api_docs/alerting.mdx | 2 +- api_docs/apm.mdx | 2 +- api_docs/apm_data_access.mdx | 2 +- api_docs/asset_manager.mdx | 2 +- api_docs/banners.mdx | 2 +- api_docs/bfetch.mdx | 2 +- api_docs/canvas.mdx | 2 +- api_docs/cases.mdx | 2 +- api_docs/charts.mdx | 2 +- api_docs/cloud.mdx | 2 +- api_docs/cloud_data_migration.mdx | 2 +- api_docs/cloud_defend.mdx | 2 +- api_docs/cloud_experiments.mdx | 2 +- api_docs/cloud_security_posture.mdx | 2 +- api_docs/console.mdx | 2 +- api_docs/content_management.mdx | 2 +- api_docs/controls.mdx | 2 +- api_docs/custom_integrations.mdx | 2 +- api_docs/dashboard.mdx | 2 +- api_docs/dashboard_enhanced.mdx | 2 +- api_docs/data.mdx | 2 +- api_docs/data_query.mdx | 2 +- api_docs/data_search.mdx | 2 +- api_docs/data_view_editor.mdx | 2 +- api_docs/data_view_field_editor.mdx | 2 +- api_docs/data_view_management.mdx | 2 +- api_docs/data_views.mdx | 2 +- api_docs/data_visualizer.mdx | 2 +- api_docs/dataset_quality.mdx | 2 +- api_docs/deprecations_by_api.mdx | 4 +- api_docs/deprecations_by_plugin.mdx | 3 +- api_docs/deprecations_by_team.mdx | 2 +- api_docs/dev_tools.mdx | 2 +- api_docs/discover.mdx | 2 +- api_docs/discover_enhanced.mdx | 2 +- api_docs/ecs_data_quality_dashboard.mdx | 2 +- api_docs/elastic_assistant.mdx | 2 +- api_docs/embeddable.devdocs.json | 107 - api_docs/embeddable.mdx | 4 +- api_docs/embeddable_enhanced.mdx | 2 +- api_docs/encrypted_saved_objects.mdx | 2 +- api_docs/enterprise_search.mdx | 2 +- api_docs/es_ui_shared.mdx | 2 +- api_docs/event_annotation.mdx | 2 +- api_docs/event_annotation_listing.mdx | 2 +- api_docs/event_log.mdx | 2 +- api_docs/exploratory_view.mdx | 2 +- api_docs/expression_error.mdx | 2 +- api_docs/expression_gauge.mdx | 2 +- api_docs/expression_heatmap.mdx | 2 +- api_docs/expression_image.mdx | 2 +- api_docs/expression_legacy_metric_vis.mdx | 2 +- api_docs/expression_metric.mdx | 2 +- api_docs/expression_metric_vis.mdx | 2 +- api_docs/expression_partition_vis.mdx | 2 +- api_docs/expression_repeat_image.mdx | 2 +- api_docs/expression_reveal_image.mdx | 2 +- api_docs/expression_shape.mdx | 2 +- api_docs/expression_tagcloud.mdx | 2 +- api_docs/expression_x_y.mdx | 2 +- api_docs/expressions.mdx | 2 +- api_docs/features.mdx | 2 +- api_docs/field_formats.mdx | 2 +- api_docs/file_upload.mdx | 2 +- api_docs/files.mdx | 2 +- api_docs/files_management.mdx | 2 +- api_docs/fleet.mdx | 2 +- api_docs/global_search.mdx | 2 +- api_docs/guided_onboarding.mdx | 2 +- api_docs/home.mdx | 2 +- api_docs/image_embeddable.mdx | 2 +- api_docs/index_lifecycle_management.mdx | 2 +- api_docs/index_management.mdx | 2 +- api_docs/infra.mdx | 2 +- api_docs/ingest_pipelines.mdx | 2 +- api_docs/inspector.mdx | 2 +- api_docs/interactive_setup.mdx | 2 +- api_docs/kbn_ace.mdx | 2 +- api_docs/kbn_actions_types.mdx | 2 +- api_docs/kbn_aiops_components.mdx | 2 +- api_docs/kbn_aiops_utils.mdx | 2 +- .../kbn_alerting_api_integration_helpers.mdx | 2 +- api_docs/kbn_alerting_state_types.mdx | 2 +- api_docs/kbn_alerting_types.mdx | 2 +- api_docs/kbn_alerts_as_data_utils.mdx | 2 +- api_docs/kbn_alerts_ui_shared.mdx | 2 +- api_docs/kbn_analytics.mdx | 2 +- api_docs/kbn_analytics_client.mdx | 2 +- api_docs/kbn_analytics_collection_utils.mdx | 2 +- ..._analytics_shippers_elastic_v3_browser.mdx | 2 +- ...n_analytics_shippers_elastic_v3_common.mdx | 2 +- ...n_analytics_shippers_elastic_v3_server.mdx | 2 +- api_docs/kbn_analytics_shippers_fullstory.mdx | 2 +- api_docs/kbn_analytics_shippers_gainsight.mdx | 2 +- api_docs/kbn_apm_config_loader.mdx | 2 +- api_docs/kbn_apm_synthtrace.mdx | 2 +- api_docs/kbn_apm_synthtrace_client.mdx | 2 +- api_docs/kbn_apm_utils.mdx | 2 +- api_docs/kbn_axe_config.mdx | 2 +- api_docs/kbn_bfetch_error.mdx | 2 +- api_docs/kbn_calculate_auto.mdx | 2 +- .../kbn_calculate_width_from_char_count.mdx | 2 +- api_docs/kbn_cases_components.mdx | 2 +- api_docs/kbn_cell_actions.mdx | 2 +- api_docs/kbn_chart_expressions_common.mdx | 2 +- api_docs/kbn_chart_icons.mdx | 2 +- api_docs/kbn_ci_stats_core.mdx | 2 +- api_docs/kbn_ci_stats_performance_metrics.mdx | 2 +- api_docs/kbn_ci_stats_reporter.mdx | 2 +- api_docs/kbn_cli_dev_mode.mdx | 2 +- api_docs/kbn_code_editor.mdx | 2 +- api_docs/kbn_code_owners.mdx | 2 +- api_docs/kbn_coloring.mdx | 2 +- api_docs/kbn_config.mdx | 2 +- api_docs/kbn_config_mocks.mdx | 2 +- api_docs/kbn_config_schema.mdx | 2 +- .../kbn_content_management_content_editor.mdx | 2 +- ...tent_management_tabbed_table_list_view.mdx | 2 +- ...kbn_content_management_table_list_view.mdx | 2 +- ...tent_management_table_list_view_common.mdx | 2 +- ...ntent_management_table_list_view_table.mdx | 2 +- api_docs/kbn_content_management_utils.mdx | 2 +- api_docs/kbn_core_analytics_browser.mdx | 2 +- .../kbn_core_analytics_browser_internal.mdx | 2 +- api_docs/kbn_core_analytics_browser_mocks.mdx | 2 +- api_docs/kbn_core_analytics_server.mdx | 2 +- .../kbn_core_analytics_server_internal.mdx | 2 +- api_docs/kbn_core_analytics_server_mocks.mdx | 2 +- api_docs/kbn_core_application_browser.mdx | 2 +- .../kbn_core_application_browser_internal.mdx | 2 +- .../kbn_core_application_browser_mocks.mdx | 2 +- api_docs/kbn_core_application_common.mdx | 2 +- api_docs/kbn_core_apps_browser_internal.mdx | 2 +- api_docs/kbn_core_apps_browser_mocks.mdx | 2 +- api_docs/kbn_core_apps_server_internal.mdx | 2 +- api_docs/kbn_core_base_browser_mocks.mdx | 2 +- api_docs/kbn_core_base_common.mdx | 2 +- api_docs/kbn_core_base_server_internal.mdx | 2 +- api_docs/kbn_core_base_server_mocks.mdx | 2 +- .../kbn_core_capabilities_browser_mocks.mdx | 2 +- api_docs/kbn_core_capabilities_common.mdx | 2 +- api_docs/kbn_core_capabilities_server.mdx | 2 +- .../kbn_core_capabilities_server_mocks.mdx | 2 +- api_docs/kbn_core_chrome_browser.mdx | 2 +- api_docs/kbn_core_chrome_browser_mocks.mdx | 2 +- api_docs/kbn_core_config_server_internal.mdx | 2 +- api_docs/kbn_core_custom_branding_browser.mdx | 2 +- ..._core_custom_branding_browser_internal.mdx | 2 +- ...kbn_core_custom_branding_browser_mocks.mdx | 2 +- api_docs/kbn_core_custom_branding_common.mdx | 2 +- api_docs/kbn_core_custom_branding_server.mdx | 2 +- ...n_core_custom_branding_server_internal.mdx | 2 +- .../kbn_core_custom_branding_server_mocks.mdx | 2 +- api_docs/kbn_core_deprecations_browser.mdx | 2 +- ...kbn_core_deprecations_browser_internal.mdx | 2 +- .../kbn_core_deprecations_browser_mocks.mdx | 2 +- api_docs/kbn_core_deprecations_common.mdx | 2 +- api_docs/kbn_core_deprecations_server.mdx | 2 +- .../kbn_core_deprecations_server_internal.mdx | 2 +- .../kbn_core_deprecations_server_mocks.mdx | 2 +- api_docs/kbn_core_doc_links_browser.mdx | 2 +- api_docs/kbn_core_doc_links_browser_mocks.mdx | 2 +- api_docs/kbn_core_doc_links_server.mdx | 2 +- api_docs/kbn_core_doc_links_server_mocks.mdx | 2 +- ...e_elasticsearch_client_server_internal.mdx | 2 +- ...core_elasticsearch_client_server_mocks.mdx | 2 +- api_docs/kbn_core_elasticsearch_server.mdx | 2 +- ...kbn_core_elasticsearch_server_internal.mdx | 2 +- .../kbn_core_elasticsearch_server_mocks.mdx | 2 +- .../kbn_core_environment_server_internal.mdx | 2 +- .../kbn_core_environment_server_mocks.mdx | 2 +- .../kbn_core_execution_context_browser.mdx | 2 +- ...ore_execution_context_browser_internal.mdx | 2 +- ...n_core_execution_context_browser_mocks.mdx | 2 +- .../kbn_core_execution_context_common.mdx | 2 +- .../kbn_core_execution_context_server.mdx | 2 +- ...core_execution_context_server_internal.mdx | 2 +- ...bn_core_execution_context_server_mocks.mdx | 2 +- api_docs/kbn_core_fatal_errors_browser.mdx | 2 +- .../kbn_core_fatal_errors_browser_mocks.mdx | 2 +- api_docs/kbn_core_http_browser.mdx | 2 +- api_docs/kbn_core_http_browser_internal.mdx | 2 +- api_docs/kbn_core_http_browser_mocks.mdx | 2 +- api_docs/kbn_core_http_common.mdx | 2 +- .../kbn_core_http_context_server_mocks.mdx | 2 +- ...re_http_request_handler_context_server.mdx | 2 +- api_docs/kbn_core_http_resources_server.mdx | 2 +- ...bn_core_http_resources_server_internal.mdx | 2 +- .../kbn_core_http_resources_server_mocks.mdx | 2 +- .../kbn_core_http_router_server_internal.mdx | 2 +- .../kbn_core_http_router_server_mocks.mdx | 2 +- api_docs/kbn_core_http_server.mdx | 2 +- api_docs/kbn_core_http_server_internal.mdx | 2 +- api_docs/kbn_core_http_server_mocks.mdx | 2 +- api_docs/kbn_core_i18n_browser.mdx | 2 +- api_docs/kbn_core_i18n_browser_mocks.mdx | 2 +- api_docs/kbn_core_i18n_server.mdx | 2 +- api_docs/kbn_core_i18n_server_internal.mdx | 2 +- api_docs/kbn_core_i18n_server_mocks.mdx | 2 +- ...n_core_injected_metadata_browser_mocks.mdx | 2 +- ...kbn_core_integrations_browser_internal.mdx | 2 +- .../kbn_core_integrations_browser_mocks.mdx | 2 +- api_docs/kbn_core_lifecycle_browser.mdx | 2 +- api_docs/kbn_core_lifecycle_browser_mocks.mdx | 2 +- api_docs/kbn_core_lifecycle_server.mdx | 2 +- api_docs/kbn_core_lifecycle_server_mocks.mdx | 2 +- api_docs/kbn_core_logging_browser_mocks.mdx | 2 +- api_docs/kbn_core_logging_common_internal.mdx | 2 +- api_docs/kbn_core_logging_server.mdx | 2 +- api_docs/kbn_core_logging_server_internal.mdx | 2 +- api_docs/kbn_core_logging_server_mocks.mdx | 2 +- ...ore_metrics_collectors_server_internal.mdx | 2 +- ...n_core_metrics_collectors_server_mocks.mdx | 2 +- api_docs/kbn_core_metrics_server.mdx | 2 +- api_docs/kbn_core_metrics_server_internal.mdx | 2 +- api_docs/kbn_core_metrics_server_mocks.mdx | 2 +- api_docs/kbn_core_mount_utils_browser.mdx | 2 +- api_docs/kbn_core_node_server.mdx | 2 +- api_docs/kbn_core_node_server_internal.mdx | 2 +- api_docs/kbn_core_node_server_mocks.mdx | 2 +- api_docs/kbn_core_notifications_browser.mdx | 2 +- ...bn_core_notifications_browser_internal.mdx | 2 +- .../kbn_core_notifications_browser_mocks.mdx | 2 +- api_docs/kbn_core_overlays_browser.mdx | 2 +- .../kbn_core_overlays_browser_internal.mdx | 2 +- api_docs/kbn_core_overlays_browser_mocks.mdx | 2 +- api_docs/kbn_core_plugins_browser.mdx | 2 +- api_docs/kbn_core_plugins_browser_mocks.mdx | 2 +- .../kbn_core_plugins_contracts_browser.mdx | 2 +- .../kbn_core_plugins_contracts_server.mdx | 2 +- api_docs/kbn_core_plugins_server.mdx | 2 +- api_docs/kbn_core_plugins_server_mocks.mdx | 2 +- api_docs/kbn_core_preboot_server.mdx | 2 +- api_docs/kbn_core_preboot_server_mocks.mdx | 2 +- api_docs/kbn_core_rendering_browser_mocks.mdx | 2 +- .../kbn_core_rendering_server_internal.mdx | 2 +- api_docs/kbn_core_rendering_server_mocks.mdx | 2 +- api_docs/kbn_core_root_server_internal.mdx | 2 +- .../kbn_core_saved_objects_api_browser.mdx | 2 +- .../kbn_core_saved_objects_api_server.mdx | 2 +- ...bn_core_saved_objects_api_server_mocks.mdx | 2 +- ...ore_saved_objects_base_server_internal.mdx | 2 +- ...n_core_saved_objects_base_server_mocks.mdx | 2 +- api_docs/kbn_core_saved_objects_browser.mdx | 2 +- ...bn_core_saved_objects_browser_internal.mdx | 2 +- .../kbn_core_saved_objects_browser_mocks.mdx | 2 +- api_docs/kbn_core_saved_objects_common.mdx | 2 +- ..._objects_import_export_server_internal.mdx | 2 +- ...ved_objects_import_export_server_mocks.mdx | 2 +- ...aved_objects_migration_server_internal.mdx | 2 +- ...e_saved_objects_migration_server_mocks.mdx | 2 +- api_docs/kbn_core_saved_objects_server.mdx | 2 +- ...kbn_core_saved_objects_server_internal.mdx | 2 +- .../kbn_core_saved_objects_server_mocks.mdx | 2 +- .../kbn_core_saved_objects_utils_server.mdx | 2 +- api_docs/kbn_core_status_common.mdx | 2 +- api_docs/kbn_core_status_common_internal.mdx | 2 +- api_docs/kbn_core_status_server.mdx | 2 +- api_docs/kbn_core_status_server_internal.mdx | 2 +- api_docs/kbn_core_status_server_mocks.mdx | 2 +- ...core_test_helpers_deprecations_getters.mdx | 2 +- ...n_core_test_helpers_http_setup_browser.mdx | 2 +- api_docs/kbn_core_test_helpers_kbn_server.mdx | 2 +- .../kbn_core_test_helpers_model_versions.mdx | 2 +- ...n_core_test_helpers_so_type_serializer.mdx | 2 +- api_docs/kbn_core_test_helpers_test_utils.mdx | 2 +- api_docs/kbn_core_theme_browser.mdx | 2 +- api_docs/kbn_core_theme_browser_mocks.mdx | 2 +- api_docs/kbn_core_ui_settings_browser.mdx | 2 +- .../kbn_core_ui_settings_browser_internal.mdx | 2 +- .../kbn_core_ui_settings_browser_mocks.mdx | 2 +- api_docs/kbn_core_ui_settings_common.mdx | 2 +- api_docs/kbn_core_ui_settings_server.mdx | 2 +- .../kbn_core_ui_settings_server_internal.mdx | 2 +- .../kbn_core_ui_settings_server_mocks.mdx | 2 +- api_docs/kbn_core_usage_data_server.mdx | 2 +- .../kbn_core_usage_data_server_internal.mdx | 2 +- api_docs/kbn_core_usage_data_server_mocks.mdx | 2 +- api_docs/kbn_core_user_settings_server.mdx | 2 +- ...kbn_core_user_settings_server_internal.mdx | 2 +- .../kbn_core_user_settings_server_mocks.mdx | 2 +- api_docs/kbn_crypto.mdx | 2 +- api_docs/kbn_crypto_browser.mdx | 2 +- api_docs/kbn_custom_icons.mdx | 2 +- api_docs/kbn_custom_integrations.mdx | 2 +- api_docs/kbn_cypress_config.mdx | 2 +- api_docs/kbn_data_service.mdx | 2 +- api_docs/kbn_datemath.mdx | 2 +- api_docs/kbn_deeplinks_analytics.mdx | 2 +- api_docs/kbn_deeplinks_devtools.mdx | 2 +- api_docs/kbn_deeplinks_management.mdx | 2 +- api_docs/kbn_deeplinks_ml.mdx | 2 +- api_docs/kbn_deeplinks_observability.mdx | 2 +- api_docs/kbn_deeplinks_search.mdx | 2 +- api_docs/kbn_default_nav_analytics.mdx | 2 +- api_docs/kbn_default_nav_devtools.mdx | 2 +- api_docs/kbn_default_nav_management.mdx | 2 +- api_docs/kbn_default_nav_ml.mdx | 2 +- api_docs/kbn_dev_cli_errors.mdx | 2 +- api_docs/kbn_dev_cli_runner.mdx | 2 +- api_docs/kbn_dev_proc_runner.mdx | 2 +- api_docs/kbn_dev_utils.mdx | 2 +- api_docs/kbn_discover_utils.mdx | 2 +- api_docs/kbn_doc_links.mdx | 2 +- api_docs/kbn_docs_utils.mdx | 2 +- api_docs/kbn_dom_drag_drop.mdx | 2 +- api_docs/kbn_ebt_tools.mdx | 2 +- api_docs/kbn_ecs.mdx | 2 +- api_docs/kbn_ecs_data_quality_dashboard.mdx | 2 +- api_docs/kbn_elastic_agent_utils.mdx | 2 +- api_docs/kbn_elastic_assistant.mdx | 2 +- api_docs/kbn_elastic_assistant_common.mdx | 2 +- api_docs/kbn_es.mdx | 2 +- api_docs/kbn_es_archiver.mdx | 2 +- api_docs/kbn_es_errors.mdx | 2 +- api_docs/kbn_es_query.mdx | 2 +- api_docs/kbn_es_types.mdx | 2 +- api_docs/kbn_eslint_plugin_imports.mdx | 2 +- api_docs/kbn_event_annotation_common.mdx | 2 +- api_docs/kbn_event_annotation_components.mdx | 2 +- api_docs/kbn_expandable_flyout.mdx | 2 +- api_docs/kbn_field_types.mdx | 2 +- api_docs/kbn_field_utils.mdx | 2 +- api_docs/kbn_find_used_node_modules.mdx | 2 +- .../kbn_ftr_common_functional_services.mdx | 2 +- ...common_functional_ui_services.devdocs.json | 10780 +++++++++++++++- .../kbn_ftr_common_functional_ui_services.mdx | 13 +- api_docs/kbn_generate.mdx | 2 +- api_docs/kbn_generate_console_definitions.mdx | 2 +- api_docs/kbn_generate_csv.mdx | 2 +- api_docs/kbn_guided_onboarding.mdx | 2 +- api_docs/kbn_handlebars.mdx | 2 +- api_docs/kbn_hapi_mocks.mdx | 2 +- api_docs/kbn_health_gateway_server.mdx | 2 +- api_docs/kbn_home_sample_data_card.mdx | 2 +- api_docs/kbn_home_sample_data_tab.mdx | 2 +- api_docs/kbn_i18n.mdx | 2 +- api_docs/kbn_i18n_react.mdx | 2 +- api_docs/kbn_import_resolver.mdx | 2 +- api_docs/kbn_infra_forge.mdx | 2 +- api_docs/kbn_interpreter.mdx | 2 +- api_docs/kbn_io_ts_utils.mdx | 2 +- api_docs/kbn_jest_serializers.mdx | 2 +- api_docs/kbn_journeys.mdx | 2 +- api_docs/kbn_json_ast.mdx | 2 +- api_docs/kbn_kibana_manifest_schema.mdx | 2 +- .../kbn_language_documentation_popover.mdx | 2 +- api_docs/kbn_lens_embeddable_utils.mdx | 2 +- api_docs/kbn_lens_formula_docs.mdx | 2 +- api_docs/kbn_logging.mdx | 2 +- api_docs/kbn_logging_mocks.mdx | 2 +- api_docs/kbn_managed_vscode_config.mdx | 2 +- api_docs/kbn_management_cards_navigation.mdx | 2 +- .../kbn_management_settings_application.mdx | 2 +- ...ent_settings_components_field_category.mdx | 2 +- ...gement_settings_components_field_input.mdx | 2 +- ...nagement_settings_components_field_row.mdx | 2 +- ...bn_management_settings_components_form.mdx | 2 +- ...n_management_settings_field_definition.mdx | 2 +- api_docs/kbn_management_settings_ids.mdx | 2 +- ...n_management_settings_section_registry.mdx | 2 +- api_docs/kbn_management_settings_types.mdx | 2 +- .../kbn_management_settings_utilities.mdx | 2 +- api_docs/kbn_management_storybook_config.mdx | 2 +- api_docs/kbn_mapbox_gl.mdx | 2 +- api_docs/kbn_maps_vector_tile_utils.mdx | 2 +- api_docs/kbn_ml_agg_utils.mdx | 2 +- api_docs/kbn_ml_anomaly_utils.mdx | 2 +- api_docs/kbn_ml_category_validator.mdx | 2 +- api_docs/kbn_ml_chi2test.mdx | 2 +- .../kbn_ml_data_frame_analytics_utils.mdx | 2 +- api_docs/kbn_ml_data_grid.mdx | 2 +- api_docs/kbn_ml_date_picker.mdx | 2 +- api_docs/kbn_ml_date_utils.mdx | 2 +- api_docs/kbn_ml_error_utils.mdx | 2 +- api_docs/kbn_ml_in_memory_table.mdx | 2 +- api_docs/kbn_ml_is_defined.mdx | 2 +- api_docs/kbn_ml_is_populated_object.mdx | 2 +- api_docs/kbn_ml_kibana_theme.mdx | 2 +- api_docs/kbn_ml_local_storage.mdx | 2 +- api_docs/kbn_ml_nested_property.mdx | 2 +- api_docs/kbn_ml_number_utils.mdx | 2 +- api_docs/kbn_ml_query_utils.mdx | 2 +- api_docs/kbn_ml_random_sampler_utils.mdx | 2 +- api_docs/kbn_ml_route_utils.mdx | 2 +- api_docs/kbn_ml_runtime_field_utils.mdx | 2 +- api_docs/kbn_ml_string_hash.mdx | 2 +- api_docs/kbn_ml_trained_models_utils.mdx | 2 +- api_docs/kbn_ml_ui_actions.mdx | 2 +- api_docs/kbn_ml_url_state.mdx | 2 +- api_docs/kbn_monaco.mdx | 2 +- api_docs/kbn_object_versioning.mdx | 2 +- api_docs/kbn_observability_alert_details.mdx | 2 +- .../kbn_observability_alerting_test_data.mdx | 2 +- ...ility_get_padded_alert_time_range_util.mdx | 2 +- api_docs/kbn_openapi_bundler.mdx | 2 +- api_docs/kbn_openapi_generator.mdx | 2 +- api_docs/kbn_optimizer.mdx | 2 +- api_docs/kbn_optimizer_webpack_helpers.mdx | 2 +- api_docs/kbn_osquery_io_ts_types.mdx | 2 +- api_docs/kbn_panel_loader.mdx | 2 +- ..._performance_testing_dataset_extractor.mdx | 2 +- api_docs/kbn_plugin_generator.mdx | 2 +- api_docs/kbn_plugin_helpers.mdx | 2 +- api_docs/kbn_profiling_utils.mdx | 2 +- api_docs/kbn_random_sampling.mdx | 2 +- api_docs/kbn_react_field.mdx | 2 +- api_docs/kbn_react_kibana_context_common.mdx | 2 +- api_docs/kbn_react_kibana_context_render.mdx | 2 +- api_docs/kbn_react_kibana_context_root.mdx | 2 +- api_docs/kbn_react_kibana_context_styled.mdx | 2 +- api_docs/kbn_react_kibana_context_theme.mdx | 2 +- api_docs/kbn_react_kibana_mount.mdx | 2 +- api_docs/kbn_repo_file_maps.mdx | 2 +- api_docs/kbn_repo_linter.mdx | 2 +- api_docs/kbn_repo_path.mdx | 2 +- api_docs/kbn_repo_source_classifier.mdx | 2 +- api_docs/kbn_reporting_common.mdx | 2 +- api_docs/kbn_reporting_export_types_csv.mdx | 2 +- .../kbn_reporting_export_types_csv_common.mdx | 2 +- api_docs/kbn_reporting_export_types_pdf.mdx | 2 +- .../kbn_reporting_export_types_pdf_common.mdx | 2 +- api_docs/kbn_reporting_export_types_png.mdx | 2 +- .../kbn_reporting_export_types_png_common.mdx | 2 +- api_docs/kbn_reporting_mocks_server.mdx | 2 +- api_docs/kbn_reporting_public.mdx | 2 +- api_docs/kbn_reporting_server.mdx | 2 +- api_docs/kbn_resizable_layout.mdx | 2 +- api_docs/kbn_rison.mdx | 2 +- api_docs/kbn_router_utils.mdx | 2 +- api_docs/kbn_rrule.mdx | 2 +- api_docs/kbn_rule_data_utils.mdx | 2 +- api_docs/kbn_saved_objects_settings.mdx | 2 +- api_docs/kbn_search_api_panels.mdx | 2 +- api_docs/kbn_search_connectors.mdx | 2 +- api_docs/kbn_search_errors.mdx | 2 +- api_docs/kbn_search_index_documents.mdx | 2 +- api_docs/kbn_search_response_warnings.mdx | 2 +- api_docs/kbn_security_plugin_types_common.mdx | 2 +- api_docs/kbn_security_plugin_types_public.mdx | 2 +- api_docs/kbn_security_plugin_types_server.mdx | 2 +- api_docs/kbn_security_solution_features.mdx | 2 +- api_docs/kbn_security_solution_navigation.mdx | 2 +- api_docs/kbn_security_solution_side_nav.mdx | 2 +- ...kbn_security_solution_storybook_config.mdx | 2 +- .../kbn_securitysolution_autocomplete.mdx | 2 +- api_docs/kbn_securitysolution_data_table.mdx | 2 +- api_docs/kbn_securitysolution_ecs.mdx | 2 +- api_docs/kbn_securitysolution_es_utils.mdx | 2 +- ...ritysolution_exception_list_components.mdx | 2 +- api_docs/kbn_securitysolution_grouping.mdx | 2 +- api_docs/kbn_securitysolution_hook_utils.mdx | 2 +- ..._securitysolution_io_ts_alerting_types.mdx | 2 +- .../kbn_securitysolution_io_ts_list_types.mdx | 2 +- api_docs/kbn_securitysolution_io_ts_types.mdx | 2 +- api_docs/kbn_securitysolution_io_ts_utils.mdx | 2 +- api_docs/kbn_securitysolution_list_api.mdx | 2 +- .../kbn_securitysolution_list_constants.mdx | 2 +- api_docs/kbn_securitysolution_list_hooks.mdx | 2 +- api_docs/kbn_securitysolution_list_utils.mdx | 2 +- api_docs/kbn_securitysolution_rules.mdx | 2 +- api_docs/kbn_securitysolution_t_grid.mdx | 2 +- api_docs/kbn_securitysolution_utils.mdx | 2 +- api_docs/kbn_server_http_tools.mdx | 2 +- api_docs/kbn_server_route_repository.mdx | 2 +- api_docs/kbn_serverless_common_settings.mdx | 2 +- .../kbn_serverless_observability_settings.mdx | 2 +- api_docs/kbn_serverless_project_switcher.mdx | 2 +- api_docs/kbn_serverless_search_settings.mdx | 2 +- api_docs/kbn_serverless_security_settings.mdx | 2 +- api_docs/kbn_serverless_storybook_config.mdx | 2 +- api_docs/kbn_shared_svg.mdx | 2 +- api_docs/kbn_shared_ux_avatar_solution.mdx | 2 +- .../kbn_shared_ux_button_exit_full_screen.mdx | 2 +- api_docs/kbn_shared_ux_button_toolbar.mdx | 2 +- api_docs/kbn_shared_ux_card_no_data.mdx | 2 +- api_docs/kbn_shared_ux_card_no_data_mocks.mdx | 2 +- api_docs/kbn_shared_ux_chrome_navigation.mdx | 2 +- api_docs/kbn_shared_ux_error_boundary.mdx | 2 +- api_docs/kbn_shared_ux_file_context.mdx | 2 +- api_docs/kbn_shared_ux_file_image.mdx | 2 +- api_docs/kbn_shared_ux_file_image_mocks.mdx | 2 +- api_docs/kbn_shared_ux_file_mocks.mdx | 2 +- api_docs/kbn_shared_ux_file_picker.mdx | 2 +- api_docs/kbn_shared_ux_file_types.mdx | 2 +- api_docs/kbn_shared_ux_file_upload.mdx | 2 +- api_docs/kbn_shared_ux_file_util.mdx | 2 +- api_docs/kbn_shared_ux_link_redirect_app.mdx | 2 +- .../kbn_shared_ux_link_redirect_app_mocks.mdx | 2 +- api_docs/kbn_shared_ux_markdown.mdx | 2 +- api_docs/kbn_shared_ux_markdown_mocks.mdx | 2 +- .../kbn_shared_ux_page_analytics_no_data.mdx | 2 +- ...shared_ux_page_analytics_no_data_mocks.mdx | 2 +- .../kbn_shared_ux_page_kibana_no_data.mdx | 2 +- ...bn_shared_ux_page_kibana_no_data_mocks.mdx | 2 +- .../kbn_shared_ux_page_kibana_template.mdx | 2 +- ...n_shared_ux_page_kibana_template_mocks.mdx | 2 +- api_docs/kbn_shared_ux_page_no_data.mdx | 2 +- .../kbn_shared_ux_page_no_data_config.mdx | 2 +- ...bn_shared_ux_page_no_data_config_mocks.mdx | 2 +- api_docs/kbn_shared_ux_page_no_data_mocks.mdx | 2 +- api_docs/kbn_shared_ux_page_solution_nav.mdx | 2 +- .../kbn_shared_ux_prompt_no_data_views.mdx | 2 +- ...n_shared_ux_prompt_no_data_views_mocks.mdx | 2 +- api_docs/kbn_shared_ux_prompt_not_found.mdx | 2 +- api_docs/kbn_shared_ux_router.mdx | 2 +- api_docs/kbn_shared_ux_router_mocks.mdx | 2 +- api_docs/kbn_shared_ux_storybook_config.mdx | 2 +- api_docs/kbn_shared_ux_storybook_mock.mdx | 2 +- api_docs/kbn_shared_ux_utility.mdx | 2 +- api_docs/kbn_slo_schema.mdx | 2 +- api_docs/kbn_some_dev_log.mdx | 2 +- api_docs/kbn_std.mdx | 2 +- api_docs/kbn_stdio_dev_helpers.mdx | 2 +- api_docs/kbn_storybook.mdx | 2 +- api_docs/kbn_telemetry_tools.mdx | 2 +- api_docs/kbn_test.mdx | 2 +- api_docs/kbn_test_jest_helpers.mdx | 2 +- api_docs/kbn_test_subj_selector.mdx | 2 +- api_docs/kbn_text_based_editor.mdx | 2 +- api_docs/kbn_tooling_log.mdx | 2 +- api_docs/kbn_triggers_actions_ui_types.mdx | 2 +- api_docs/kbn_ts_projects.mdx | 2 +- api_docs/kbn_typed_react_router_config.mdx | 2 +- api_docs/kbn_ui_actions_browser.mdx | 2 +- api_docs/kbn_ui_shared_deps_src.mdx | 2 +- api_docs/kbn_ui_theme.mdx | 2 +- api_docs/kbn_unified_data_table.mdx | 2 +- api_docs/kbn_unified_doc_viewer.mdx | 2 +- api_docs/kbn_unified_field_list.mdx | 2 +- api_docs/kbn_unsaved_changes_badge.mdx | 2 +- api_docs/kbn_url_state.mdx | 2 +- api_docs/kbn_use_tracked_promise.mdx | 2 +- api_docs/kbn_user_profile_components.mdx | 2 +- api_docs/kbn_utility_types.mdx | 2 +- api_docs/kbn_utility_types_jest.mdx | 2 +- api_docs/kbn_utils.mdx | 2 +- api_docs/kbn_visualization_ui_components.mdx | 2 +- api_docs/kbn_visualization_utils.mdx | 2 +- api_docs/kbn_xstate_utils.mdx | 2 +- api_docs/kbn_yarn_lock_validator.mdx | 2 +- api_docs/kbn_zod_helpers.mdx | 2 +- api_docs/kibana_overview.mdx | 2 +- api_docs/kibana_react.mdx | 2 +- api_docs/kibana_utils.mdx | 2 +- api_docs/kubernetes_security.mdx | 2 +- api_docs/lens.mdx | 2 +- api_docs/license_api_guard.mdx | 2 +- api_docs/license_management.mdx | 2 +- api_docs/licensing.mdx | 2 +- api_docs/links.mdx | 2 +- api_docs/lists.mdx | 2 +- api_docs/log_explorer.mdx | 2 +- api_docs/logs_shared.mdx | 2 +- api_docs/management.mdx | 2 +- api_docs/maps.mdx | 2 +- api_docs/maps_ems.mdx | 2 +- api_docs/metrics_data_access.mdx | 2 +- api_docs/ml.mdx | 2 +- api_docs/mock_idp_plugin.mdx | 2 +- api_docs/monitoring.mdx | 2 +- api_docs/monitoring_collection.mdx | 2 +- api_docs/navigation.mdx | 2 +- api_docs/newsfeed.mdx | 2 +- api_docs/no_data_page.mdx | 2 +- api_docs/notifications.mdx | 2 +- api_docs/observability.mdx | 2 +- api_docs/observability_a_i_assistant.mdx | 2 +- api_docs/observability_log_explorer.mdx | 2 +- api_docs/observability_onboarding.mdx | 2 +- api_docs/observability_shared.mdx | 2 +- api_docs/osquery.mdx | 2 +- api_docs/painless_lab.mdx | 2 +- api_docs/plugin_directory.mdx | 8 +- api_docs/presentation_util.mdx | 2 +- api_docs/profiling.mdx | 2 +- api_docs/profiling_data_access.mdx | 2 +- api_docs/remote_clusters.mdx | 2 +- api_docs/reporting.mdx | 2 +- api_docs/rollup.mdx | 2 +- api_docs/rule_registry.mdx | 2 +- api_docs/runtime_fields.mdx | 2 +- api_docs/saved_objects.mdx | 2 +- api_docs/saved_objects_finder.mdx | 2 +- api_docs/saved_objects_management.mdx | 2 +- api_docs/saved_objects_tagging.mdx | 2 +- api_docs/saved_objects_tagging_oss.mdx | 2 +- api_docs/saved_search.mdx | 2 +- api_docs/screenshot_mode.mdx | 2 +- api_docs/screenshotting.mdx | 2 +- api_docs/security.mdx | 2 +- api_docs/security_solution.devdocs.json | 14 +- api_docs/security_solution.mdx | 2 +- api_docs/security_solution_ess.mdx | 2 +- api_docs/security_solution_serverless.mdx | 2 +- api_docs/serverless.mdx | 2 +- api_docs/serverless_observability.mdx | 2 +- api_docs/serverless_search.mdx | 2 +- api_docs/session_view.mdx | 2 +- api_docs/share.mdx | 2 +- api_docs/snapshot_restore.mdx | 2 +- api_docs/spaces.mdx | 2 +- api_docs/stack_alerts.mdx | 2 +- api_docs/stack_connectors.mdx | 2 +- api_docs/task_manager.mdx | 2 +- api_docs/telemetry.mdx | 2 +- api_docs/telemetry_collection_manager.mdx | 2 +- api_docs/telemetry_collection_xpack.mdx | 2 +- api_docs/telemetry_management_section.mdx | 2 +- api_docs/text_based_languages.mdx | 2 +- api_docs/threat_intelligence.mdx | 2 +- api_docs/timelines.mdx | 2 +- api_docs/transform.mdx | 2 +- api_docs/triggers_actions_ui.mdx | 2 +- api_docs/ui_actions.mdx | 2 +- api_docs/ui_actions_enhanced.mdx | 2 +- api_docs/unified_doc_viewer.mdx | 2 +- api_docs/unified_histogram.mdx | 2 +- api_docs/unified_search.mdx | 2 +- api_docs/unified_search_autocomplete.mdx | 2 +- api_docs/uptime.mdx | 2 +- api_docs/url_forwarding.mdx | 2 +- api_docs/usage_collection.mdx | 2 +- api_docs/ux.mdx | 2 +- api_docs/vis_default_editor.mdx | 2 +- api_docs/vis_type_gauge.mdx | 2 +- api_docs/vis_type_heatmap.mdx | 2 +- api_docs/vis_type_pie.mdx | 2 +- api_docs/vis_type_table.mdx | 2 +- api_docs/vis_type_timelion.mdx | 2 +- api_docs/vis_type_timeseries.mdx | 2 +- api_docs/vis_type_vega.mdx | 2 +- api_docs/vis_type_vislib.mdx | 2 +- api_docs/vis_type_xy.mdx | 2 +- api_docs/visualizations.mdx | 2 +- 641 files changed, 11420 insertions(+), 789 deletions(-) diff --git a/api_docs/actions.mdx b/api_docs/actions.mdx index 175c79c8edd8..9b6fc4e40992 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: 2024-01-04 +date: 2024-01-05 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 67938b9ee86c..08df2353949d 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'advancedSettings'] --- import advancedSettingsObj from './advanced_settings.devdocs.json'; diff --git a/api_docs/ai_assistant_management_observability.mdx b/api_docs/ai_assistant_management_observability.mdx index 568c9569b3e5..c63f25666847 100644 --- a/api_docs/ai_assistant_management_observability.mdx +++ b/api_docs/ai_assistant_management_observability.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/aiAssistantManagementObservability title: "aiAssistantManagementObservability" image: https://source.unsplash.com/400x175/?github description: API docs for the aiAssistantManagementObservability plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'aiAssistantManagementObservability'] --- import aiAssistantManagementObservabilityObj from './ai_assistant_management_observability.devdocs.json'; diff --git a/api_docs/ai_assistant_management_selection.mdx b/api_docs/ai_assistant_management_selection.mdx index ce9a17f1097c..b60876a8b2d0 100644 --- a/api_docs/ai_assistant_management_selection.mdx +++ b/api_docs/ai_assistant_management_selection.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/aiAssistantManagementSelection title: "aiAssistantManagementSelection" image: https://source.unsplash.com/400x175/?github description: API docs for the aiAssistantManagementSelection plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'aiAssistantManagementSelection'] --- import aiAssistantManagementSelectionObj from './ai_assistant_management_selection.devdocs.json'; diff --git a/api_docs/aiops.mdx b/api_docs/aiops.mdx index efe4742f812a..15fa9e290efd 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: 2024-01-04 +date: 2024-01-05 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 5fd8e35e631a..1c8c1df0579b 100644 --- a/api_docs/alerting.devdocs.json +++ b/api_docs/alerting.devdocs.json @@ -3573,18 +3573,6 @@ "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/server/lib/detection_engine/rule_preview/api/preview_rules/route.ts" }, - { - "plugin": "stackAlerts", - "path": "x-pack/plugins/stack_alerts/server/rule_types/geo_containment/lib/get_entities_and_generate_alerts.ts" - }, - { - "plugin": "stackAlerts", - "path": "x-pack/plugins/stack_alerts/server/rule_types/geo_containment/executor.ts" - }, - { - "plugin": "stackAlerts", - "path": "x-pack/plugins/stack_alerts/server/rule_types/geo_containment/executor.ts" - }, { "plugin": "synthetics", "path": "x-pack/plugins/synthetics/server/alert_rules/common.ts" diff --git a/api_docs/alerting.mdx b/api_docs/alerting.mdx index e38c25b1345d..28e361099dda 100644 --- a/api_docs/alerting.mdx +++ b/api_docs/alerting.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/alerting title: "alerting" image: https://source.unsplash.com/400x175/?github description: API docs for the alerting plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'alerting'] --- import alertingObj from './alerting.devdocs.json'; diff --git a/api_docs/apm.mdx b/api_docs/apm.mdx index 97004593fa23..8a11d4b792ef 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'apm'] --- import apmObj from './apm.devdocs.json'; diff --git a/api_docs/apm_data_access.mdx b/api_docs/apm_data_access.mdx index 0967e55be0f9..486a98544233 100644 --- a/api_docs/apm_data_access.mdx +++ b/api_docs/apm_data_access.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/apmDataAccess title: "apmDataAccess" image: https://source.unsplash.com/400x175/?github description: API docs for the apmDataAccess plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'apmDataAccess'] --- import apmDataAccessObj from './apm_data_access.devdocs.json'; diff --git a/api_docs/asset_manager.mdx b/api_docs/asset_manager.mdx index 1cd598a4a078..3aa9b422a878 100644 --- a/api_docs/asset_manager.mdx +++ b/api_docs/asset_manager.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/assetManager title: "assetManager" image: https://source.unsplash.com/400x175/?github description: API docs for the assetManager plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'assetManager'] --- import assetManagerObj from './asset_manager.devdocs.json'; diff --git a/api_docs/banners.mdx b/api_docs/banners.mdx index fcfe454cd2ef..933a72cbfb56 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: 2024-01-04 +date: 2024-01-05 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 42b81bc4929d..08752e5f08cc 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: 2024-01-04 +date: 2024-01-05 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 569b7601fc2e..789f5a2e2ad1 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'canvas'] --- import canvasObj from './canvas.devdocs.json'; diff --git a/api_docs/cases.mdx b/api_docs/cases.mdx index b3d7095d4690..50dee46bbc17 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cases'] --- import casesObj from './cases.devdocs.json'; diff --git a/api_docs/charts.mdx b/api_docs/charts.mdx index 1b368f3d4535..904d7ad0d6ea 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: 2024-01-04 +date: 2024-01-05 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 1b9f49f8192d..de6eb5383068 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloud'] --- import cloudObj from './cloud.devdocs.json'; diff --git a/api_docs/cloud_data_migration.mdx b/api_docs/cloud_data_migration.mdx index 2f280ede3337..f8df5d8b1d7f 100644 --- a/api_docs/cloud_data_migration.mdx +++ b/api_docs/cloud_data_migration.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudDataMigration title: "cloudDataMigration" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudDataMigration plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudDataMigration'] --- import cloudDataMigrationObj from './cloud_data_migration.devdocs.json'; diff --git a/api_docs/cloud_defend.mdx b/api_docs/cloud_defend.mdx index e5983addb500..a3e3efcff6aa 100644 --- a/api_docs/cloud_defend.mdx +++ b/api_docs/cloud_defend.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudDefend title: "cloudDefend" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudDefend plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudDefend'] --- import cloudDefendObj from './cloud_defend.devdocs.json'; diff --git a/api_docs/cloud_experiments.mdx b/api_docs/cloud_experiments.mdx index 697403428944..fa3d2ba58b0c 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: 2024-01-04 +date: 2024-01-05 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 28df21b79fb9..884584688fcd 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: 2024-01-04 +date: 2024-01-05 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 9da7224fcc9d..1b98439c1e0d 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'console'] --- import consoleObj from './console.devdocs.json'; diff --git a/api_docs/content_management.mdx b/api_docs/content_management.mdx index 644a576b9a31..f9dba5f90403 100644 --- a/api_docs/content_management.mdx +++ b/api_docs/content_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/contentManagement title: "contentManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the contentManagement plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'contentManagement'] --- import contentManagementObj from './content_management.devdocs.json'; diff --git a/api_docs/controls.mdx b/api_docs/controls.mdx index 6d149d7f848d..6dfd5cfbce66 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'controls'] --- import controlsObj from './controls.devdocs.json'; diff --git a/api_docs/custom_integrations.mdx b/api_docs/custom_integrations.mdx index 6c513a57370b..066b2ad67f52 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'customIntegrations'] --- import customIntegrationsObj from './custom_integrations.devdocs.json'; diff --git a/api_docs/dashboard.mdx b/api_docs/dashboard.mdx index 8b12f4b0b382..3aaf1a73398e 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: 2024-01-04 +date: 2024-01-05 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 ceed4cf64c76..cf0fbc962179 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dashboardEnhanced'] --- import dashboardEnhancedObj from './dashboard_enhanced.devdocs.json'; diff --git a/api_docs/data.mdx b/api_docs/data.mdx index 59da5a91e2c5..908a26ac7ca0 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data'] --- import dataObj from './data.devdocs.json'; diff --git a/api_docs/data_query.mdx b/api_docs/data_query.mdx index 57b16fdff130..e8ed44d73684 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data.query'] --- import dataQueryObj from './data_query.devdocs.json'; diff --git a/api_docs/data_search.mdx b/api_docs/data_search.mdx index 62cd1bbac728..14d4d5b20d10 100644 --- a/api_docs/data_search.mdx +++ b/api_docs/data_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/data-search title: "data.search" image: https://source.unsplash.com/400x175/?github description: API docs for the data.search plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data.search'] --- import dataSearchObj from './data_search.devdocs.json'; diff --git a/api_docs/data_view_editor.mdx b/api_docs/data_view_editor.mdx index 299c8ec4f418..482b412c91fc 100644 --- a/api_docs/data_view_editor.mdx +++ b/api_docs/data_view_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViewEditor title: "dataViewEditor" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViewEditor plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewEditor'] --- import dataViewEditorObj from './data_view_editor.devdocs.json'; diff --git a/api_docs/data_view_field_editor.mdx b/api_docs/data_view_field_editor.mdx index 426a400c774f..75fc42ef61f6 100644 --- a/api_docs/data_view_field_editor.mdx +++ b/api_docs/data_view_field_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViewFieldEditor title: "dataViewFieldEditor" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViewFieldEditor plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewFieldEditor'] --- import dataViewFieldEditorObj from './data_view_field_editor.devdocs.json'; diff --git a/api_docs/data_view_management.mdx b/api_docs/data_view_management.mdx index d6991202136d..6e49fa6c26ff 100644 --- a/api_docs/data_view_management.mdx +++ b/api_docs/data_view_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViewManagement title: "dataViewManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViewManagement plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewManagement'] --- import dataViewManagementObj from './data_view_management.devdocs.json'; diff --git a/api_docs/data_views.mdx b/api_docs/data_views.mdx index a0cdcce02e88..f8ac9c9b24ca 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViews'] --- import dataViewsObj from './data_views.devdocs.json'; diff --git a/api_docs/data_visualizer.mdx b/api_docs/data_visualizer.mdx index bacd296a4046..d27868ff533f 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataVisualizer'] --- import dataVisualizerObj from './data_visualizer.devdocs.json'; diff --git a/api_docs/dataset_quality.mdx b/api_docs/dataset_quality.mdx index 79815bf40637..51c627244fdc 100644 --- a/api_docs/dataset_quality.mdx +++ b/api_docs/dataset_quality.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/datasetQuality title: "datasetQuality" image: https://source.unsplash.com/400x175/?github description: API docs for the datasetQuality plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'datasetQuality'] --- import datasetQualityObj from './dataset_quality.devdocs.json'; diff --git a/api_docs/deprecations_by_api.mdx b/api_docs/deprecations_by_api.mdx index 4ce5183771c8..b5602a70aa9a 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -17,7 +17,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | Deprecated API | Referencing plugin(s) | Remove By | | ---------------|-----------|-----------| | | ml, stackAlerts | - | -| | ruleRegistry, observability, ml, infra, monitoring, securitySolution, stackAlerts, synthetics, transform, uptime | - | +| | ruleRegistry, observability, ml, infra, monitoring, securitySolution, synthetics, transform, uptime | - | | | share, uiActions, guidedOnboarding, home, serverless, management, spaces, savedObjects, indexManagement, visualizations, dashboard, savedObjectsTagging, expressionXY, lens, expressionMetricVis, expressionGauge, security, alerting, triggersActionsUi, cases, aiops, advancedSettings, licenseManagement, maps, dataVisualizer, ml, exploratoryView, fleet, metricsDataAccess, osquery, ingestPipelines, profiling, apm, expressionImage, expressionMetric, expressionError, expressionRevealImage, expressionRepeatImage, expressionShape, crossClusterReplication, graph, grokdebugger, indexLifecycleManagement, infra, logstash, monitoring, observabilityOnboarding, devTools, painlessLab, remoteClusters, rollup, searchprofiler, newsfeed, securitySolution, snapshotRestore, synthetics, transform, upgradeAssistant, uptime, ux, watcher, cloudDataMigration, console, filesManagement, kibanaOverview, visDefaultEditor, expressionHeatmap, expressionLegacyMetricVis, expressionPartitionVis, expressionTagcloud, visTypeTable, visTypeTimelion, visTypeTimeseries, visTypeVega, visTypeVislib | - | | | encryptedSavedObjects, actions, data, ml, logstash, securitySolution, cloudChat | - | | | actions, ml, savedObjectsTagging, enterpriseSearch | - | diff --git a/api_docs/deprecations_by_plugin.mdx b/api_docs/deprecations_by_plugin.mdx index b55449facaff..fb5eb527d5e6 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -1419,7 +1419,6 @@ migrates to using the Kibana Privilege model: https://github.com/elastic/kibana/ | Deprecated API | Reference location(s) | Remove By | | ---------------|-----------|-----------| | | [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/stack_alerts/public/rule_types/es_query/index.ts#:~:text=registerNavigation), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/stack_alerts/public/rule_types/es_query/index.ts#:~:text=registerNavigation), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/stack_alerts/public/rule_types/es_query/index.ts#:~:text=registerNavigation), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/stack_alerts/public/rule_types/es_query/index.ts#:~:text=registerNavigation), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/stack_alerts/public/rule_types/es_query/index.ts#:~:text=registerNavigation) | - | -| | [get_entities_and_generate_alerts.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/stack_alerts/server/rule_types/geo_containment/lib/get_entities_and_generate_alerts.ts#:~:text=alertFactory), [executor.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/stack_alerts/server/rule_types/geo_containment/executor.ts#:~:text=alertFactory), [executor.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/stack_alerts/server/rule_types/geo_containment/executor.ts#:~:text=alertFactory) | - | | | [fetch_search_source_query.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/stack_alerts/server/rule_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/rule_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/rule_types/es_query/rule_type.test.ts#:~:text=fetch) | - | | | [data_view_select.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/stack_alerts/public/rule_types/geo_containment/rule_form/data_view_select.tsx#:~:text=indexPatterns), [boundary_form.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/stack_alerts/public/rule_types/geo_containment/rule_form/boundary_form.tsx#:~:text=indexPatterns), [boundary_form.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/stack_alerts/public/rule_types/geo_containment/rule_form/boundary_form.tsx#:~:text=indexPatterns), [entity_form.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/stack_alerts/public/rule_types/geo_containment/rule_form/entity_form.tsx#:~:text=indexPatterns), [entity_form.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/stack_alerts/public/rule_types/geo_containment/rule_form/entity_form.tsx#:~:text=indexPatterns) | - | | | [expression.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/stack_alerts/public/rule_types/threshold/expression.tsx#:~:text=fieldFormats) | - | diff --git a/api_docs/deprecations_by_team.mdx b/api_docs/deprecations_by_team.mdx index 5c49d1c2111f..50a0f24b90d1 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- diff --git a/api_docs/dev_tools.mdx b/api_docs/dev_tools.mdx index c34d79777073..2eb27ed7d537 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: 2024-01-04 +date: 2024-01-05 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 47dfbf70d346..0401920b1678 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: 2024-01-04 +date: 2024-01-05 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 caa873b92b45..8d3d79e298cb 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'discoverEnhanced'] --- import discoverEnhancedObj from './discover_enhanced.devdocs.json'; diff --git a/api_docs/ecs_data_quality_dashboard.mdx b/api_docs/ecs_data_quality_dashboard.mdx index 49056bd1bf75..821e5c3e07aa 100644 --- a/api_docs/ecs_data_quality_dashboard.mdx +++ b/api_docs/ecs_data_quality_dashboard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ecsDataQualityDashboard title: "ecsDataQualityDashboard" image: https://source.unsplash.com/400x175/?github description: API docs for the ecsDataQualityDashboard plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ecsDataQualityDashboard'] --- import ecsDataQualityDashboardObj from './ecs_data_quality_dashboard.devdocs.json'; diff --git a/api_docs/elastic_assistant.mdx b/api_docs/elastic_assistant.mdx index dfb7d99f0c30..c9b0a42d493d 100644 --- a/api_docs/elastic_assistant.mdx +++ b/api_docs/elastic_assistant.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/elasticAssistant title: "elasticAssistant" image: https://source.unsplash.com/400x175/?github description: API docs for the elasticAssistant plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'elasticAssistant'] --- import elasticAssistantObj from './elastic_assistant.devdocs.json'; diff --git a/api_docs/embeddable.devdocs.json b/api_docs/embeddable.devdocs.json index c840f13b2782..12da9ef05339 100644 --- a/api_docs/embeddable.devdocs.json +++ b/api_docs/embeddable.devdocs.json @@ -1746,48 +1746,6 @@ "id": "def-public.CustomizePanelAction.Unnamed.$1", "type": "Object", "tags": [], - "label": "overlays", - "description": [], - "signature": [ - { - "pluginId": "@kbn/core-overlays-browser", - "scope": "common", - "docId": "kibKbnCoreOverlaysBrowserPluginApi", - "section": "def-common.OverlayStart", - "text": "OverlayStart" - } - ], - "path": "src/plugins/embeddable/public/embeddable_panel/panel_actions/customize_panel_action/customize_panel_action.tsx", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - }, - { - "parentPluginId": "embeddable", - "id": "def-public.CustomizePanelAction.Unnamed.$2", - "type": "Object", - "tags": [], - "label": "theme", - "description": [], - "signature": [ - { - "pluginId": "@kbn/core-theme-browser", - "scope": "common", - "docId": "kibKbnCoreThemeBrowserPluginApi", - "section": "def-common.ThemeServiceSetup", - "text": "ThemeServiceSetup" - } - ], - "path": "src/plugins/embeddable/public/embeddable_panel/panel_actions/customize_panel_action/customize_panel_action.tsx", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - }, - { - "parentPluginId": "embeddable", - "id": "def-public.CustomizePanelAction.Unnamed.$3", - "type": "Object", - "tags": [], "label": "editPanel", "description": [], "signature": [ @@ -1803,71 +1761,6 @@ "deprecated": false, "trackAdoption": false, "isRequired": true - }, - { - "parentPluginId": "embeddable", - "id": "def-public.CustomizePanelAction.Unnamed.$4", - "type": "Array", - "tags": [], - "label": "commonlyUsedRanges", - "description": [], - "signature": [ - "CommonlyUsedRange", - "[] | undefined" - ], - "path": "src/plugins/embeddable/public/embeddable_panel/panel_actions/customize_panel_action/customize_panel_action.tsx", - "deprecated": false, - "trackAdoption": false, - "isRequired": false - }, - { - "parentPluginId": "embeddable", - "id": "def-public.CustomizePanelAction.Unnamed.$5", - "type": "string", - "tags": [], - "label": "dateFormat", - "description": [], - "signature": [ - "string | undefined" - ], - "path": "src/plugins/embeddable/public/embeddable_panel/panel_actions/customize_panel_action/customize_panel_action.tsx", - "deprecated": false, - "trackAdoption": false, - "isRequired": false - } - ], - "returnComment": [] - }, - { - "parentPluginId": "embeddable", - "id": "def-public.CustomizePanelAction.isTimeRangeCompatible", - "type": "Function", - "tags": [], - "label": "isTimeRangeCompatible", - "description": [], - "signature": [ - "({ embeddable }: ", - "CustomizePanelActionContext", - ") => boolean" - ], - "path": "src/plugins/embeddable/public/embeddable_panel/panel_actions/customize_panel_action/customize_panel_action.tsx", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "embeddable", - "id": "def-public.CustomizePanelAction.isTimeRangeCompatible.$1", - "type": "Object", - "tags": [], - "label": "{ embeddable }", - "description": [], - "signature": [ - "CustomizePanelActionContext" - ], - "path": "src/plugins/embeddable/public/embeddable_panel/panel_actions/customize_panel_action/customize_panel_action.tsx", - "deprecated": false, - "trackAdoption": false, - "isRequired": true } ], "returnComment": [] diff --git a/api_docs/embeddable.mdx b/api_docs/embeddable.mdx index 7b0b5851dd68..76eae0e07b40 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'embeddable'] --- import embeddableObj from './embeddable.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-presentation](https://github.com/orgs/elastic/teams/kib | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 547 | 1 | 446 | 8 | +| 541 | 1 | 440 | 7 | ## Client diff --git a/api_docs/embeddable_enhanced.mdx b/api_docs/embeddable_enhanced.mdx index 991825410088..548174d7de37 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: 2024-01-04 +date: 2024-01-05 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 daa6d36a9614..352efa1e656a 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: 2024-01-04 +date: 2024-01-05 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 9474de5f8197..bd1c4bdaf32a 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: 2024-01-04 +date: 2024-01-05 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 8320de7c77f9..6c760ef1be96 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: 2024-01-04 +date: 2024-01-05 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 3bc7ef1e9dd7..89cf436a8d03 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'eventAnnotation'] --- import eventAnnotationObj from './event_annotation.devdocs.json'; diff --git a/api_docs/event_annotation_listing.mdx b/api_docs/event_annotation_listing.mdx index 4f01a013f655..4285b824b286 100644 --- a/api_docs/event_annotation_listing.mdx +++ b/api_docs/event_annotation_listing.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/eventAnnotationListing title: "eventAnnotationListing" image: https://source.unsplash.com/400x175/?github description: API docs for the eventAnnotationListing plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'eventAnnotationListing'] --- import eventAnnotationListingObj from './event_annotation_listing.devdocs.json'; diff --git a/api_docs/event_log.mdx b/api_docs/event_log.mdx index dc3c20ed884e..0f598efcc8e8 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'eventLog'] --- import eventLogObj from './event_log.devdocs.json'; diff --git a/api_docs/exploratory_view.mdx b/api_docs/exploratory_view.mdx index 1086207ae79e..eddcfa9df88b 100644 --- a/api_docs/exploratory_view.mdx +++ b/api_docs/exploratory_view.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/exploratoryView title: "exploratoryView" image: https://source.unsplash.com/400x175/?github description: API docs for the exploratoryView plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'exploratoryView'] --- import exploratoryViewObj from './exploratory_view.devdocs.json'; diff --git a/api_docs/expression_error.mdx b/api_docs/expression_error.mdx index ec4f95d64f91..498a0ab17963 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionError'] --- import expressionErrorObj from './expression_error.devdocs.json'; diff --git a/api_docs/expression_gauge.mdx b/api_docs/expression_gauge.mdx index fdf929c6a59c..a58ef618b198 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionGauge'] --- import expressionGaugeObj from './expression_gauge.devdocs.json'; diff --git a/api_docs/expression_heatmap.mdx b/api_docs/expression_heatmap.mdx index 38d225279672..53f605f27359 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionHeatmap'] --- import expressionHeatmapObj from './expression_heatmap.devdocs.json'; diff --git a/api_docs/expression_image.mdx b/api_docs/expression_image.mdx index 27e04629ee41..8ffa228f761e 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: 2024-01-04 +date: 2024-01-05 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 dee6029f3cb9..3339ac65b98d 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: 2024-01-04 +date: 2024-01-05 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 3096059ad767..d5053bdf2009 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: 2024-01-04 +date: 2024-01-05 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 2a20d57c3b13..b4df1088239a 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: 2024-01-04 +date: 2024-01-05 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 04ecc8db4966..94b1732f35b8 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: 2024-01-04 +date: 2024-01-05 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 b6b0ac67a9cb..1875640df8d1 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: 2024-01-04 +date: 2024-01-05 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 e5ab37d98ab7..ac5b410ac3c5 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: 2024-01-04 +date: 2024-01-05 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 a07ed74186ff..6c36c1616bbb 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: 2024-01-04 +date: 2024-01-05 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 2aa729e87260..7080b06bdcad 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionTagcloud'] --- import expressionTagcloudObj from './expression_tagcloud.devdocs.json'; diff --git a/api_docs/expression_x_y.mdx b/api_docs/expression_x_y.mdx index 0b10fe16fe0f..9c93e19857db 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionXY'] --- import expressionXYObj from './expression_x_y.devdocs.json'; diff --git a/api_docs/expressions.mdx b/api_docs/expressions.mdx index b65dc56d93d7..7e6becdb5e3b 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressions'] --- import expressionsObj from './expressions.devdocs.json'; diff --git a/api_docs/features.mdx b/api_docs/features.mdx index 9dd615856349..4e9cddb8f0c9 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: 2024-01-04 +date: 2024-01-05 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 04e8add44042..83dc20b9d14f 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: 2024-01-04 +date: 2024-01-05 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 4c98ec2a3d91..05805282482b 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fileUpload'] --- import fileUploadObj from './file_upload.devdocs.json'; diff --git a/api_docs/files.mdx b/api_docs/files.mdx index 492b70d6729b..0a106848874e 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'files'] --- import filesObj from './files.devdocs.json'; diff --git a/api_docs/files_management.mdx b/api_docs/files_management.mdx index 34f47024dfd7..c41633bb5c40 100644 --- a/api_docs/files_management.mdx +++ b/api_docs/files_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/filesManagement title: "filesManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the filesManagement plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'filesManagement'] --- import filesManagementObj from './files_management.devdocs.json'; diff --git a/api_docs/fleet.mdx b/api_docs/fleet.mdx index 71082e7d6c85..d023bf23660d 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: 2024-01-04 +date: 2024-01-05 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 f145084416fb..f1c3cfb57137 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'globalSearch'] --- import globalSearchObj from './global_search.devdocs.json'; diff --git a/api_docs/guided_onboarding.mdx b/api_docs/guided_onboarding.mdx index 69906278ddaf..67e293184baf 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: 2024-01-04 +date: 2024-01-05 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 24aa7c9926bd..e15635e437a3 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'home'] --- import homeObj from './home.devdocs.json'; diff --git a/api_docs/image_embeddable.mdx b/api_docs/image_embeddable.mdx index f0e831980622..269c949a2b51 100644 --- a/api_docs/image_embeddable.mdx +++ b/api_docs/image_embeddable.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/imageEmbeddable title: "imageEmbeddable" image: https://source.unsplash.com/400x175/?github description: API docs for the imageEmbeddable plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'imageEmbeddable'] --- import imageEmbeddableObj from './image_embeddable.devdocs.json'; diff --git a/api_docs/index_lifecycle_management.mdx b/api_docs/index_lifecycle_management.mdx index e180f0d1641d..673edd6fc999 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: 2024-01-04 +date: 2024-01-05 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 5d41b96d012e..d7047ed6918c 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: 2024-01-04 +date: 2024-01-05 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 f5c39b03aca7..306a2dd4f183 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'infra'] --- import infraObj from './infra.devdocs.json'; diff --git a/api_docs/ingest_pipelines.mdx b/api_docs/ingest_pipelines.mdx index 6e9aff3bfba0..604704f4a464 100644 --- a/api_docs/ingest_pipelines.mdx +++ b/api_docs/ingest_pipelines.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ingestPipelines title: "ingestPipelines" image: https://source.unsplash.com/400x175/?github description: API docs for the ingestPipelines plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ingestPipelines'] --- import ingestPipelinesObj from './ingest_pipelines.devdocs.json'; diff --git a/api_docs/inspector.mdx b/api_docs/inspector.mdx index 03c65d44f35e..c031e57df940 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: 2024-01-04 +date: 2024-01-05 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 0086ac4ce9e8..2c4f4409c50e 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: 2024-01-04 +date: 2024-01-05 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 be92db311d96..58c8dd293a89 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ace'] --- import kbnAceObj from './kbn_ace.devdocs.json'; diff --git a/api_docs/kbn_actions_types.mdx b/api_docs/kbn_actions_types.mdx index ea6042678334..67732f9450a6 100644 --- a/api_docs/kbn_actions_types.mdx +++ b/api_docs/kbn_actions_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-actions-types title: "@kbn/actions-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/actions-types plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/actions-types'] --- import kbnActionsTypesObj from './kbn_actions_types.devdocs.json'; diff --git a/api_docs/kbn_aiops_components.mdx b/api_docs/kbn_aiops_components.mdx index 0fceae2c6aa5..99efb29fa187 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/aiops-components'] --- import kbnAiopsComponentsObj from './kbn_aiops_components.devdocs.json'; diff --git a/api_docs/kbn_aiops_utils.mdx b/api_docs/kbn_aiops_utils.mdx index 0c572f58a141..7c4d66e6a79b 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/aiops-utils'] --- import kbnAiopsUtilsObj from './kbn_aiops_utils.devdocs.json'; diff --git a/api_docs/kbn_alerting_api_integration_helpers.mdx b/api_docs/kbn_alerting_api_integration_helpers.mdx index 48cae6747c96..5d97cbcef983 100644 --- a/api_docs/kbn_alerting_api_integration_helpers.mdx +++ b/api_docs/kbn_alerting_api_integration_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerting-api-integration-helpers title: "@kbn/alerting-api-integration-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerting-api-integration-helpers plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerting-api-integration-helpers'] --- import kbnAlertingApiIntegrationHelpersObj from './kbn_alerting_api_integration_helpers.devdocs.json'; diff --git a/api_docs/kbn_alerting_state_types.mdx b/api_docs/kbn_alerting_state_types.mdx index 7109d9c5de8c..ea31276702c8 100644 --- a/api_docs/kbn_alerting_state_types.mdx +++ b/api_docs/kbn_alerting_state_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerting-state-types title: "@kbn/alerting-state-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerting-state-types plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerting-state-types'] --- import kbnAlertingStateTypesObj from './kbn_alerting_state_types.devdocs.json'; diff --git a/api_docs/kbn_alerting_types.mdx b/api_docs/kbn_alerting_types.mdx index 81baf5ce3dea..9c0634d2f5fa 100644 --- a/api_docs/kbn_alerting_types.mdx +++ b/api_docs/kbn_alerting_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerting-types title: "@kbn/alerting-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerting-types plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerting-types'] --- import kbnAlertingTypesObj from './kbn_alerting_types.devdocs.json'; diff --git a/api_docs/kbn_alerts_as_data_utils.mdx b/api_docs/kbn_alerts_as_data_utils.mdx index 9e2d04708b8d..d13f7538c6f1 100644 --- a/api_docs/kbn_alerts_as_data_utils.mdx +++ b/api_docs/kbn_alerts_as_data_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerts-as-data-utils title: "@kbn/alerts-as-data-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerts-as-data-utils plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerts-as-data-utils'] --- import kbnAlertsAsDataUtilsObj from './kbn_alerts_as_data_utils.devdocs.json'; diff --git a/api_docs/kbn_alerts_ui_shared.mdx b/api_docs/kbn_alerts_ui_shared.mdx index b835cdf34543..dd820870f56a 100644 --- a/api_docs/kbn_alerts_ui_shared.mdx +++ b/api_docs/kbn_alerts_ui_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerts-ui-shared title: "@kbn/alerts-ui-shared" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerts-ui-shared plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerts-ui-shared'] --- import kbnAlertsUiSharedObj from './kbn_alerts_ui_shared.devdocs.json'; diff --git a/api_docs/kbn_analytics.mdx b/api_docs/kbn_analytics.mdx index bb47843b82e3..07f4f676b648 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: 2024-01-04 +date: 2024-01-05 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 3b5f66fe191c..aa6359d94408 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-client'] --- import kbnAnalyticsClientObj from './kbn_analytics_client.devdocs.json'; diff --git a/api_docs/kbn_analytics_collection_utils.mdx b/api_docs/kbn_analytics_collection_utils.mdx index a5ebd4cabb52..26f300afff2f 100644 --- a/api_docs/kbn_analytics_collection_utils.mdx +++ b/api_docs/kbn_analytics_collection_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-collection-utils title: "@kbn/analytics-collection-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-collection-utils plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-collection-utils'] --- import kbnAnalyticsCollectionUtilsObj from './kbn_analytics_collection_utils.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 4ad36ce3266e..eecc34a7903a 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: 2024-01-04 +date: 2024-01-05 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 2f441677caed..12347d76060a 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: 2024-01-04 +date: 2024-01-05 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 6d37607eb378..6f8daf129a9a 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: 2024-01-04 +date: 2024-01-05 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 dbf2ed50486e..4c7a7db8dc10 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-fullstory'] --- import kbnAnalyticsShippersFullstoryObj from './kbn_analytics_shippers_fullstory.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_gainsight.mdx b/api_docs/kbn_analytics_shippers_gainsight.mdx index 6c2e2085a35e..67adc5447da8 100644 --- a/api_docs/kbn_analytics_shippers_gainsight.mdx +++ b/api_docs/kbn_analytics_shippers_gainsight.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-gainsight title: "@kbn/analytics-shippers-gainsight" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-gainsight plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-gainsight'] --- import kbnAnalyticsShippersGainsightObj from './kbn_analytics_shippers_gainsight.devdocs.json'; diff --git a/api_docs/kbn_apm_config_loader.mdx b/api_docs/kbn_apm_config_loader.mdx index 2e4da0de9fff..fb2645ed8940 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-config-loader'] --- import kbnApmConfigLoaderObj from './kbn_apm_config_loader.devdocs.json'; diff --git a/api_docs/kbn_apm_synthtrace.mdx b/api_docs/kbn_apm_synthtrace.mdx index 08be197d2f32..c5a2d9d1be71 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-synthtrace'] --- import kbnApmSynthtraceObj from './kbn_apm_synthtrace.devdocs.json'; diff --git a/api_docs/kbn_apm_synthtrace_client.mdx b/api_docs/kbn_apm_synthtrace_client.mdx index 57f76574a6a0..b7e5007d1dae 100644 --- a/api_docs/kbn_apm_synthtrace_client.mdx +++ b/api_docs/kbn_apm_synthtrace_client.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-synthtrace-client title: "@kbn/apm-synthtrace-client" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-synthtrace-client plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-synthtrace-client'] --- import kbnApmSynthtraceClientObj from './kbn_apm_synthtrace_client.devdocs.json'; diff --git a/api_docs/kbn_apm_utils.mdx b/api_docs/kbn_apm_utils.mdx index d4f8acded8be..19dd1cddbbb5 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: 2024-01-04 +date: 2024-01-05 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 691cc29eab2b..3b1aaa7f5bc1 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/axe-config'] --- import kbnAxeConfigObj from './kbn_axe_config.devdocs.json'; diff --git a/api_docs/kbn_bfetch_error.mdx b/api_docs/kbn_bfetch_error.mdx index 6ffb7d64aa16..95e9ef9d8e2c 100644 --- a/api_docs/kbn_bfetch_error.mdx +++ b/api_docs/kbn_bfetch_error.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-bfetch-error title: "@kbn/bfetch-error" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/bfetch-error plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/bfetch-error'] --- import kbnBfetchErrorObj from './kbn_bfetch_error.devdocs.json'; diff --git a/api_docs/kbn_calculate_auto.mdx b/api_docs/kbn_calculate_auto.mdx index bbcb29ede912..4f9a6ae98957 100644 --- a/api_docs/kbn_calculate_auto.mdx +++ b/api_docs/kbn_calculate_auto.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-calculate-auto title: "@kbn/calculate-auto" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/calculate-auto plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/calculate-auto'] --- import kbnCalculateAutoObj from './kbn_calculate_auto.devdocs.json'; diff --git a/api_docs/kbn_calculate_width_from_char_count.mdx b/api_docs/kbn_calculate_width_from_char_count.mdx index 168799bba2c8..8a0212183d0e 100644 --- a/api_docs/kbn_calculate_width_from_char_count.mdx +++ b/api_docs/kbn_calculate_width_from_char_count.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-calculate-width-from-char-count title: "@kbn/calculate-width-from-char-count" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/calculate-width-from-char-count plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/calculate-width-from-char-count'] --- import kbnCalculateWidthFromCharCountObj from './kbn_calculate_width_from_char_count.devdocs.json'; diff --git a/api_docs/kbn_cases_components.mdx b/api_docs/kbn_cases_components.mdx index 1cb18fc4b85c..3ad99c30a213 100644 --- a/api_docs/kbn_cases_components.mdx +++ b/api_docs/kbn_cases_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cases-components title: "@kbn/cases-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cases-components plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cases-components'] --- import kbnCasesComponentsObj from './kbn_cases_components.devdocs.json'; diff --git a/api_docs/kbn_cell_actions.mdx b/api_docs/kbn_cell_actions.mdx index af7a6aec2f06..5da607184446 100644 --- a/api_docs/kbn_cell_actions.mdx +++ b/api_docs/kbn_cell_actions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cell-actions title: "@kbn/cell-actions" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cell-actions plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cell-actions'] --- import kbnCellActionsObj from './kbn_cell_actions.devdocs.json'; diff --git a/api_docs/kbn_chart_expressions_common.mdx b/api_docs/kbn_chart_expressions_common.mdx index 8709c69a78d2..f99acdf51bc1 100644 --- a/api_docs/kbn_chart_expressions_common.mdx +++ b/api_docs/kbn_chart_expressions_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-chart-expressions-common title: "@kbn/chart-expressions-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/chart-expressions-common plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/chart-expressions-common'] --- import kbnChartExpressionsCommonObj from './kbn_chart_expressions_common.devdocs.json'; diff --git a/api_docs/kbn_chart_icons.mdx b/api_docs/kbn_chart_icons.mdx index f3d78c78a277..99dfb9291a2c 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: 2024-01-04 +date: 2024-01-05 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 fd14fa1f9cc0..8e4e8dcfeaf1 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: 2024-01-04 +date: 2024-01-05 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 c5160318f304..3c1646598d3c 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: 2024-01-04 +date: 2024-01-05 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 6b5d8e5811c6..9ae2a3c9cf53 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: 2024-01-04 +date: 2024-01-05 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 c25eb3b034f9..0d428a2b65c4 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cli-dev-mode'] --- import kbnCliDevModeObj from './kbn_cli_dev_mode.devdocs.json'; diff --git a/api_docs/kbn_code_editor.mdx b/api_docs/kbn_code_editor.mdx index b1faf78313c5..c979f6dc50d4 100644 --- a/api_docs/kbn_code_editor.mdx +++ b/api_docs/kbn_code_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-code-editor title: "@kbn/code-editor" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/code-editor plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/code-editor'] --- import kbnCodeEditorObj from './kbn_code_editor.devdocs.json'; diff --git a/api_docs/kbn_code_owners.mdx b/api_docs/kbn_code_owners.mdx index 45c2f1eec850..f226a1348df2 100644 --- a/api_docs/kbn_code_owners.mdx +++ b/api_docs/kbn_code_owners.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-code-owners title: "@kbn/code-owners" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/code-owners plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/code-owners'] --- import kbnCodeOwnersObj from './kbn_code_owners.devdocs.json'; diff --git a/api_docs/kbn_coloring.mdx b/api_docs/kbn_coloring.mdx index 016a50f4eed6..888e0b94e7c9 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: 2024-01-04 +date: 2024-01-05 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 92e2a6e6a98d..ecdf371ddfff 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: 2024-01-04 +date: 2024-01-05 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 538b978f01f6..5e15a806482f 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: 2024-01-04 +date: 2024-01-05 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 7a11d031669b..e8b490fcaa55 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config-schema'] --- import kbnConfigSchemaObj from './kbn_config_schema.devdocs.json'; diff --git a/api_docs/kbn_content_management_content_editor.mdx b/api_docs/kbn_content_management_content_editor.mdx index a01fcd538b27..2080f7a4f545 100644 --- a/api_docs/kbn_content_management_content_editor.mdx +++ b/api_docs/kbn_content_management_content_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-content-editor title: "@kbn/content-management-content-editor" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-content-editor plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-content-editor'] --- import kbnContentManagementContentEditorObj from './kbn_content_management_content_editor.devdocs.json'; diff --git a/api_docs/kbn_content_management_tabbed_table_list_view.mdx b/api_docs/kbn_content_management_tabbed_table_list_view.mdx index ab99b334698e..afa1cc531eec 100644 --- a/api_docs/kbn_content_management_tabbed_table_list_view.mdx +++ b/api_docs/kbn_content_management_tabbed_table_list_view.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-tabbed-table-list-view title: "@kbn/content-management-tabbed-table-list-view" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-tabbed-table-list-view plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-tabbed-table-list-view'] --- import kbnContentManagementTabbedTableListViewObj from './kbn_content_management_tabbed_table_list_view.devdocs.json'; diff --git a/api_docs/kbn_content_management_table_list_view.mdx b/api_docs/kbn_content_management_table_list_view.mdx index ac36b039e2e2..296cdd60739d 100644 --- a/api_docs/kbn_content_management_table_list_view.mdx +++ b/api_docs/kbn_content_management_table_list_view.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-table-list-view title: "@kbn/content-management-table-list-view" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-table-list-view plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-table-list-view'] --- import kbnContentManagementTableListViewObj from './kbn_content_management_table_list_view.devdocs.json'; diff --git a/api_docs/kbn_content_management_table_list_view_common.mdx b/api_docs/kbn_content_management_table_list_view_common.mdx index ba7e057ea4c5..295f28d250ef 100644 --- a/api_docs/kbn_content_management_table_list_view_common.mdx +++ b/api_docs/kbn_content_management_table_list_view_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-table-list-view-common title: "@kbn/content-management-table-list-view-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-table-list-view-common plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-table-list-view-common'] --- import kbnContentManagementTableListViewCommonObj from './kbn_content_management_table_list_view_common.devdocs.json'; diff --git a/api_docs/kbn_content_management_table_list_view_table.mdx b/api_docs/kbn_content_management_table_list_view_table.mdx index 4eb648daed69..bd4a59931d36 100644 --- a/api_docs/kbn_content_management_table_list_view_table.mdx +++ b/api_docs/kbn_content_management_table_list_view_table.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-table-list-view-table title: "@kbn/content-management-table-list-view-table" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-table-list-view-table plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-table-list-view-table'] --- import kbnContentManagementTableListViewTableObj from './kbn_content_management_table_list_view_table.devdocs.json'; diff --git a/api_docs/kbn_content_management_utils.mdx b/api_docs/kbn_content_management_utils.mdx index b93c28f3f242..2334bbea1106 100644 --- a/api_docs/kbn_content_management_utils.mdx +++ b/api_docs/kbn_content_management_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-utils title: "@kbn/content-management-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-utils plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-utils'] --- import kbnContentManagementUtilsObj from './kbn_content_management_utils.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_browser.mdx b/api_docs/kbn_core_analytics_browser.mdx index 5d321c806dae..42c9d614c579 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: 2024-01-04 +date: 2024-01-05 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 1f543f4bf84c..153a2c7a9152 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: 2024-01-04 +date: 2024-01-05 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 2705851553d3..b514f46a767d 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: 2024-01-04 +date: 2024-01-05 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 7c3743c1dbd8..22a2b868300d 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: 2024-01-04 +date: 2024-01-05 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 3e4b93af573a..8e99ad34f05a 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: 2024-01-04 +date: 2024-01-05 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 13fddb27bcd4..34dc36645e8d 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: 2024-01-04 +date: 2024-01-05 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 79983ab12c2e..003b923f10aa 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: 2024-01-04 +date: 2024-01-05 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 c96835fd136f..6286d2cb724e 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: 2024-01-04 +date: 2024-01-05 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 0d0d8e97c742..4129c3bcf844 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: 2024-01-04 +date: 2024-01-05 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 8448a8305a7e..189ddf130568 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: 2024-01-04 +date: 2024-01-05 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 9723b65a4498..c00e06b1d4e5 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: 2024-01-04 +date: 2024-01-05 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 596f3e1409ae..dfc0190d41a1 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: 2024-01-04 +date: 2024-01-05 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_apps_server_internal.mdx b/api_docs/kbn_core_apps_server_internal.mdx index d271d9e00176..9a818b7a9cf7 100644 --- a/api_docs/kbn_core_apps_server_internal.mdx +++ b/api_docs/kbn_core_apps_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-apps-server-internal title: "@kbn/core-apps-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-apps-server-internal plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-apps-server-internal'] --- import kbnCoreAppsServerInternalObj from './kbn_core_apps_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_base_browser_mocks.mdx b/api_docs/kbn_core_base_browser_mocks.mdx index 67397822cc15..5d983edad908 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: 2024-01-04 +date: 2024-01-05 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 96261af6de97..96380b2c5e49 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: 2024-01-04 +date: 2024-01-05 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 690927a8f239..10e1fbe8f64d 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: 2024-01-04 +date: 2024-01-05 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 acdf0cea0938..8811b252d3a4 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: 2024-01-04 +date: 2024-01-05 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 05311bbc8df0..3e2a93bdaa39 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: 2024-01-04 +date: 2024-01-05 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 b394f4e578b4..a43d1d79f59b 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: 2024-01-04 +date: 2024-01-05 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 04e0c62d9dea..9aecb50d3630 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: 2024-01-04 +date: 2024-01-05 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 4b249f1bff21..36c6be975a5d 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: 2024-01-04 +date: 2024-01-05 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 5e8bdf8c5aa0..635558913735 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: 2024-01-04 +date: 2024-01-05 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 02e3a5ec0123..9b90d0d77d1b 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: 2024-01-04 +date: 2024-01-05 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 228937230005..36d73d21f57f 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: 2024-01-04 +date: 2024-01-05 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_custom_branding_browser.mdx b/api_docs/kbn_core_custom_branding_browser.mdx index fb768b7c12d3..11c405617243 100644 --- a/api_docs/kbn_core_custom_branding_browser.mdx +++ b/api_docs/kbn_core_custom_branding_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-browser title: "@kbn/core-custom-branding-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-browser plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-browser'] --- import kbnCoreCustomBrandingBrowserObj from './kbn_core_custom_branding_browser.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_browser_internal.mdx b/api_docs/kbn_core_custom_branding_browser_internal.mdx index 47066277a282..cf5f3594cacd 100644 --- a/api_docs/kbn_core_custom_branding_browser_internal.mdx +++ b/api_docs/kbn_core_custom_branding_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-browser-internal title: "@kbn/core-custom-branding-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-browser-internal plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-browser-internal'] --- import kbnCoreCustomBrandingBrowserInternalObj from './kbn_core_custom_branding_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_browser_mocks.mdx b/api_docs/kbn_core_custom_branding_browser_mocks.mdx index 0557c03698a2..5efaad8b4b76 100644 --- a/api_docs/kbn_core_custom_branding_browser_mocks.mdx +++ b/api_docs/kbn_core_custom_branding_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-browser-mocks title: "@kbn/core-custom-branding-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-browser-mocks plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-browser-mocks'] --- import kbnCoreCustomBrandingBrowserMocksObj from './kbn_core_custom_branding_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_common.mdx b/api_docs/kbn_core_custom_branding_common.mdx index e4c2d814ce4c..c8d037dfb1be 100644 --- a/api_docs/kbn_core_custom_branding_common.mdx +++ b/api_docs/kbn_core_custom_branding_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-common title: "@kbn/core-custom-branding-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-common plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-common'] --- import kbnCoreCustomBrandingCommonObj from './kbn_core_custom_branding_common.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_server.mdx b/api_docs/kbn_core_custom_branding_server.mdx index 47df9f6bd415..ac3d4fee5471 100644 --- a/api_docs/kbn_core_custom_branding_server.mdx +++ b/api_docs/kbn_core_custom_branding_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-server title: "@kbn/core-custom-branding-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-server plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-server'] --- import kbnCoreCustomBrandingServerObj from './kbn_core_custom_branding_server.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_server_internal.mdx b/api_docs/kbn_core_custom_branding_server_internal.mdx index 8f0176938100..f394f80ac1a4 100644 --- a/api_docs/kbn_core_custom_branding_server_internal.mdx +++ b/api_docs/kbn_core_custom_branding_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-server-internal title: "@kbn/core-custom-branding-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-server-internal plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-server-internal'] --- import kbnCoreCustomBrandingServerInternalObj from './kbn_core_custom_branding_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_server_mocks.mdx b/api_docs/kbn_core_custom_branding_server_mocks.mdx index 5c6ac50845b0..6fa595b3f7dd 100644 --- a/api_docs/kbn_core_custom_branding_server_mocks.mdx +++ b/api_docs/kbn_core_custom_branding_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-server-mocks title: "@kbn/core-custom-branding-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-server-mocks plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-server-mocks'] --- import kbnCoreCustomBrandingServerMocksObj from './kbn_core_custom_branding_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_browser.mdx b/api_docs/kbn_core_deprecations_browser.mdx index cb4891afb2a6..4dd8071edb61 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: 2024-01-04 +date: 2024-01-05 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 2fcebc148f34..2868afa3f6c5 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: 2024-01-04 +date: 2024-01-05 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 40c40b888547..3583323fb993 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: 2024-01-04 +date: 2024-01-05 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 276dae6fdc91..aa0538b54ed9 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: 2024-01-04 +date: 2024-01-05 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 06938c8a2b3d..66613027f159 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: 2024-01-04 +date: 2024-01-05 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 096e7236e152..07f76eadc4a0 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: 2024-01-04 +date: 2024-01-05 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 cc44b8b202e8..c2eedb7775bc 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: 2024-01-04 +date: 2024-01-05 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 2f95b164db63..7476d9890e76 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: 2024-01-04 +date: 2024-01-05 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 e001c1a7741c..ff520667e628 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: 2024-01-04 +date: 2024-01-05 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 0dd3e339adf5..698406787e33 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: 2024-01-04 +date: 2024-01-05 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 039d4286527a..a4bfe1af57f1 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: 2024-01-04 +date: 2024-01-05 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 6ae23ebdbc4f..c6579465e4d9 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-client-server-internal'] --- import kbnCoreElasticsearchClientServerInternalObj from './kbn_core_elasticsearch_client_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx b/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx index 84519ae1e6f5..50797c4a7044 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-client-server-mocks'] --- import kbnCoreElasticsearchClientServerMocksObj from './kbn_core_elasticsearch_client_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_server.mdx b/api_docs/kbn_core_elasticsearch_server.mdx index 58dc5db37427..5877335b3b4b 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-server'] --- import kbnCoreElasticsearchServerObj from './kbn_core_elasticsearch_server.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_server_internal.mdx b/api_docs/kbn_core_elasticsearch_server_internal.mdx index 30259cc8ff03..dfd4378709ee 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: 2024-01-04 +date: 2024-01-05 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 fb88fcd87870..b3194820e611 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: 2024-01-04 +date: 2024-01-05 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 0b45eda63a4d..9096578c4a86 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: 2024-01-04 +date: 2024-01-05 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 68780da32595..d8329ab84c6f 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: 2024-01-04 +date: 2024-01-05 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 84acec6f8c4d..c6051b14b8bb 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: 2024-01-04 +date: 2024-01-05 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 6f5cdfc30e9f..0f4b1d809e2a 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: 2024-01-04 +date: 2024-01-05 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 dae8f7597fa8..e0335fd19b45 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: 2024-01-04 +date: 2024-01-05 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 d3443180f5e3..e34ee98f0854 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: 2024-01-04 +date: 2024-01-05 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 9bcd85c18be2..a9cd993ef361 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: 2024-01-04 +date: 2024-01-05 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 c55c66060c45..9a092dd21291 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: 2024-01-04 +date: 2024-01-05 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 c02aee85f62c..fe7dfdc0640b 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: 2024-01-04 +date: 2024-01-05 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 a370ba31b739..ca637613e3dc 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: 2024-01-04 +date: 2024-01-05 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 4cd23b56d204..7bae8c7510fe 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: 2024-01-04 +date: 2024-01-05 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 b1d5fa2f87bf..c0dc5ef4d816 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: 2024-01-04 +date: 2024-01-05 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 95910196e46a..c4a4931aa224 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: 2024-01-04 +date: 2024-01-05 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 bf351d6b6045..d5b59d087d88 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: 2024-01-04 +date: 2024-01-05 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 cf934a82ce8a..fdaf73a8bdf9 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: 2024-01-04 +date: 2024-01-05 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 cf0cc09149fe..7a13acd3b6ee 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: 2024-01-04 +date: 2024-01-05 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 c843f511ba71..3bc12db9ecfe 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: 2024-01-04 +date: 2024-01-05 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 9b26b97d0bf2..d6d4afcb46f8 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: 2024-01-04 +date: 2024-01-05 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 3e9098cf3068..f86eb611844b 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: 2024-01-04 +date: 2024-01-05 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 0f301dc896f4..fb0b69d74b6c 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: 2024-01-04 +date: 2024-01-05 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 4619b1f04432..8717f3484e4d 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: 2024-01-04 +date: 2024-01-05 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 1b0b50082abf..89196d48aa80 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: 2024-01-04 +date: 2024-01-05 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 1646c74c42d1..13108de8ed0b 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: 2024-01-04 +date: 2024-01-05 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 95405dcd06ca..c79302c665bd 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: 2024-01-04 +date: 2024-01-05 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 d23065a22a01..5346aa263fbf 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: 2024-01-04 +date: 2024-01-05 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 807e09bb6a59..5dc4097c8c4d 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: 2024-01-04 +date: 2024-01-05 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 20ebff06fbca..d5bfe62f3f7c 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: 2024-01-04 +date: 2024-01-05 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 f56413569351..a9e8270c39be 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: 2024-01-04 +date: 2024-01-05 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 31ac9457e072..f73490a95c85 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: 2024-01-04 +date: 2024-01-05 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 47ccee6e6cd1..ef90dab3f1ad 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: 2024-01-04 +date: 2024-01-05 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_mocks.mdx b/api_docs/kbn_core_injected_metadata_browser_mocks.mdx index 2ed3ed3355a4..1b36c7da8133 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: 2024-01-04 +date: 2024-01-05 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 24be40a1fc58..8597ee8c0c58 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: 2024-01-04 +date: 2024-01-05 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 e1e5c0423104..6d73ad37a3a4 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: 2024-01-04 +date: 2024-01-05 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 64ffdd809b2a..e15a9cda86c0 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: 2024-01-04 +date: 2024-01-05 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 6e94acb61527..f1a80b337c64 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: 2024-01-04 +date: 2024-01-05 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_lifecycle_server.mdx b/api_docs/kbn_core_lifecycle_server.mdx index fc5a818242d3..fb234bfd464e 100644 --- a/api_docs/kbn_core_lifecycle_server.mdx +++ b/api_docs/kbn_core_lifecycle_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-server title: "@kbn/core-lifecycle-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-server plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-lifecycle-server'] --- import kbnCoreLifecycleServerObj from './kbn_core_lifecycle_server.devdocs.json'; diff --git a/api_docs/kbn_core_lifecycle_server_mocks.mdx b/api_docs/kbn_core_lifecycle_server_mocks.mdx index d66a001fbed3..c050429f9497 100644 --- a/api_docs/kbn_core_lifecycle_server_mocks.mdx +++ b/api_docs/kbn_core_lifecycle_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-server-mocks title: "@kbn/core-lifecycle-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-server-mocks plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-lifecycle-server-mocks'] --- import kbnCoreLifecycleServerMocksObj from './kbn_core_lifecycle_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_logging_browser_mocks.mdx b/api_docs/kbn_core_logging_browser_mocks.mdx index 584b2355c327..4a382b53f403 100644 --- a/api_docs/kbn_core_logging_browser_mocks.mdx +++ b/api_docs/kbn_core_logging_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-browser-mocks title: "@kbn/core-logging-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-browser-mocks plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-browser-mocks'] --- import kbnCoreLoggingBrowserMocksObj from './kbn_core_logging_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_logging_common_internal.mdx b/api_docs/kbn_core_logging_common_internal.mdx index a1e076498112..a1be0d78c787 100644 --- a/api_docs/kbn_core_logging_common_internal.mdx +++ b/api_docs/kbn_core_logging_common_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-common-internal title: "@kbn/core-logging-common-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-common-internal plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-common-internal'] --- import kbnCoreLoggingCommonInternalObj from './kbn_core_logging_common_internal.devdocs.json'; diff --git a/api_docs/kbn_core_logging_server.mdx b/api_docs/kbn_core_logging_server.mdx index 431cd7f5a46b..d10d6f1cb0fb 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: 2024-01-04 +date: 2024-01-05 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 89e76e1e5d97..1cb9d7a42a66 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: 2024-01-04 +date: 2024-01-05 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 7706403fd084..76e0e48e87d1 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: 2024-01-04 +date: 2024-01-05 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 13f01e4c371d..68bcc653afe3 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: 2024-01-04 +date: 2024-01-05 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 1f612d9b47e4..9be45a959922 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: 2024-01-04 +date: 2024-01-05 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 a5110c2ef580..f91bee45de34 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: 2024-01-04 +date: 2024-01-05 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 0794553156ba..08fd3abf4b2f 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: 2024-01-04 +date: 2024-01-05 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 1fcb936b7740..0a1cf0c52011 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: 2024-01-04 +date: 2024-01-05 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 e9d8e7bd6333..cdf78183d362 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: 2024-01-04 +date: 2024-01-05 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 41847b2965ce..b933d9fb7b07 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: 2024-01-04 +date: 2024-01-05 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 dc5608723d68..09603fc421f9 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: 2024-01-04 +date: 2024-01-05 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 74e310e07bc4..d6b92cf6550f 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: 2024-01-04 +date: 2024-01-05 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 3c89672e3fcb..9b1954f72aea 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: 2024-01-04 +date: 2024-01-05 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 f68349b2df2b..8c0198cc375f 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: 2024-01-04 +date: 2024-01-05 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 aa66bff4ae8c..8321d240778a 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: 2024-01-04 +date: 2024-01-05 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 099c145770ad..dcd73424735c 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: 2024-01-04 +date: 2024-01-05 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 5ee90e5a9a9f..f8d6214e106b 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: 2024-01-04 +date: 2024-01-05 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 aca97bed11b2..3dd3b0dfe182 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: 2024-01-04 +date: 2024-01-05 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 3ad8d49e085d..99b2909488b7 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: 2024-01-04 +date: 2024-01-05 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 7517e87c6bf4..05bb9690c66d 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: 2024-01-04 +date: 2024-01-05 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_plugins_contracts_browser.mdx b/api_docs/kbn_core_plugins_contracts_browser.mdx index 2d32821e57a6..745e3ff7dc36 100644 --- a/api_docs/kbn_core_plugins_contracts_browser.mdx +++ b/api_docs/kbn_core_plugins_contracts_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-contracts-browser title: "@kbn/core-plugins-contracts-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-contracts-browser plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-contracts-browser'] --- import kbnCorePluginsContractsBrowserObj from './kbn_core_plugins_contracts_browser.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_contracts_server.mdx b/api_docs/kbn_core_plugins_contracts_server.mdx index 3a622d5b1991..dd9290362f01 100644 --- a/api_docs/kbn_core_plugins_contracts_server.mdx +++ b/api_docs/kbn_core_plugins_contracts_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-contracts-server title: "@kbn/core-plugins-contracts-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-contracts-server plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-contracts-server'] --- import kbnCorePluginsContractsServerObj from './kbn_core_plugins_contracts_server.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_server.mdx b/api_docs/kbn_core_plugins_server.mdx index e97622f466a7..22e9bdc28990 100644 --- a/api_docs/kbn_core_plugins_server.mdx +++ b/api_docs/kbn_core_plugins_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-server title: "@kbn/core-plugins-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-server plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-server'] --- import kbnCorePluginsServerObj from './kbn_core_plugins_server.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_server_mocks.mdx b/api_docs/kbn_core_plugins_server_mocks.mdx index 789728222a03..141a858f1514 100644 --- a/api_docs/kbn_core_plugins_server_mocks.mdx +++ b/api_docs/kbn_core_plugins_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-server-mocks title: "@kbn/core-plugins-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-server-mocks plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-server-mocks'] --- import kbnCorePluginsServerMocksObj from './kbn_core_plugins_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_preboot_server.mdx b/api_docs/kbn_core_preboot_server.mdx index 3188532eef0c..78745c8f8794 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: 2024-01-04 +date: 2024-01-05 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 9abf502bc984..ac0c2b312d4f 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: 2024-01-04 +date: 2024-01-05 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 1b65c430646d..2eaff65af4b9 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: 2024-01-04 +date: 2024-01-05 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 269a838711fe..cac034b79dbb 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: 2024-01-04 +date: 2024-01-05 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 530d51da435a..ab6260c4eb1d 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: 2024-01-04 +date: 2024-01-05 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_root_server_internal.mdx b/api_docs/kbn_core_root_server_internal.mdx index d88b4b65ba87..6ee52e34d7a5 100644 --- a/api_docs/kbn_core_root_server_internal.mdx +++ b/api_docs/kbn_core_root_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-root-server-internal title: "@kbn/core-root-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-root-server-internal plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-root-server-internal'] --- import kbnCoreRootServerInternalObj from './kbn_core_root_server_internal.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 405eb70d599c..a4696878794f 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: 2024-01-04 +date: 2024-01-05 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 36f8838849be..a2a20ce874df 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: 2024-01-04 +date: 2024-01-05 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_mocks.mdx b/api_docs/kbn_core_saved_objects_api_server_mocks.mdx index 690c0b69d424..315bd86bcfe8 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: 2024-01-04 +date: 2024-01-05 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 0dbdf60396e5..c6fad755d60d 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: 2024-01-04 +date: 2024-01-05 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 ea3ea08c9248..d352c77e86b6 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: 2024-01-04 +date: 2024-01-05 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 8ea6c02a57b2..2386bbb34583 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: 2024-01-04 +date: 2024-01-05 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 0819d5a1e799..f38f8a175534 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: 2024-01-04 +date: 2024-01-05 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 4658f309b11a..e2123b9db7fe 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: 2024-01-04 +date: 2024-01-05 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 a74bec6b40ad..a03a55579e7c 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: 2024-01-04 +date: 2024-01-05 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 1a4c01991982..d447d007c9ef 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: 2024-01-04 +date: 2024-01-05 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 f37847eb15bd..e9c44ca486b1 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-import-export-server-mocks'] --- import kbnCoreSavedObjectsImportExportServerMocksObj from './kbn_core_saved_objects_import_export_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_migration_server_internal.mdx b/api_docs/kbn_core_saved_objects_migration_server_internal.mdx index be10a7df2c69..6557ea3b88b0 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: 2024-01-04 +date: 2024-01-05 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 83d236a7c90b..ca68c544a4a8 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: 2024-01-04 +date: 2024-01-05 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 073d01306e15..528d68226c1e 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: 2024-01-04 +date: 2024-01-05 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 ff992ba279e5..53029290bbce 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: 2024-01-04 +date: 2024-01-05 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 d0c9b94683c4..aebb6f5ffb2a 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: 2024-01-04 +date: 2024-01-05 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 9a655a53f3d2..8de3b757d7fe 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: 2024-01-04 +date: 2024-01-05 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 30d1a76ba87a..6790c9b264fd 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: 2024-01-04 +date: 2024-01-05 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 e7b9d2225333..da0ed41bb941 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: 2024-01-04 +date: 2024-01-05 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 1ced970793db..2640368c30be 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: 2024-01-04 +date: 2024-01-05 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 cb2db0211eeb..772cd4def6a6 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: 2024-01-04 +date: 2024-01-05 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 2defa9b66cd1..8e08cf85ec1a 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: 2024-01-04 +date: 2024-01-05 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 bcd02b5b63d8..272f643a6321 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: 2024-01-04 +date: 2024-01-05 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 7c28f8c40e05..534bbae8b469 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: 2024-01-04 +date: 2024-01-05 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_kbn_server.mdx b/api_docs/kbn_core_test_helpers_kbn_server.mdx index d1f753772176..acdfb8291f5c 100644 --- a/api_docs/kbn_core_test_helpers_kbn_server.mdx +++ b/api_docs/kbn_core_test_helpers_kbn_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-kbn-server title: "@kbn/core-test-helpers-kbn-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-kbn-server plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-kbn-server'] --- import kbnCoreTestHelpersKbnServerObj from './kbn_core_test_helpers_kbn_server.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_model_versions.mdx b/api_docs/kbn_core_test_helpers_model_versions.mdx index df6c2317422f..8f8d5cd2f030 100644 --- a/api_docs/kbn_core_test_helpers_model_versions.mdx +++ b/api_docs/kbn_core_test_helpers_model_versions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-model-versions title: "@kbn/core-test-helpers-model-versions" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-model-versions plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-model-versions'] --- import kbnCoreTestHelpersModelVersionsObj from './kbn_core_test_helpers_model_versions.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 a5d5ec6bcf42..bece1dfffd54 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: 2024-01-04 +date: 2024-01-05 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_test_helpers_test_utils.mdx b/api_docs/kbn_core_test_helpers_test_utils.mdx index 3812d80d0584..03096fa4ea6b 100644 --- a/api_docs/kbn_core_test_helpers_test_utils.mdx +++ b/api_docs/kbn_core_test_helpers_test_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-test-utils title: "@kbn/core-test-helpers-test-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-test-utils plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-test-utils'] --- import kbnCoreTestHelpersTestUtilsObj from './kbn_core_test_helpers_test_utils.devdocs.json'; diff --git a/api_docs/kbn_core_theme_browser.mdx b/api_docs/kbn_core_theme_browser.mdx index ad3d2637f65c..10c78c84e597 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: 2024-01-04 +date: 2024-01-05 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_mocks.mdx b/api_docs/kbn_core_theme_browser_mocks.mdx index 1c655b9d3774..8096b2c0c6b2 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: 2024-01-04 +date: 2024-01-05 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 933b7613d430..0806dcc0e27e 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: 2024-01-04 +date: 2024-01-05 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 1759294c3ede..591c1f9eda15 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: 2024-01-04 +date: 2024-01-05 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 711277a14d31..c5ed348ea284 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: 2024-01-04 +date: 2024-01-05 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 48f92b475d5e..c2713fdc462d 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: 2024-01-04 +date: 2024-01-05 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 9ab86721089f..fd65be4fcb46 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: 2024-01-04 +date: 2024-01-05 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 a177e83347b1..cab535e4d818 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: 2024-01-04 +date: 2024-01-05 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 d82f2f595f8e..8cd3baf2d70b 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: 2024-01-04 +date: 2024-01-05 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 c1fce322f950..b2976124fb3e 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: 2024-01-04 +date: 2024-01-05 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 420a7ba708a2..46fe662e811a 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: 2024-01-04 +date: 2024-01-05 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 8df47910b261..f333f187c4c1 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: 2024-01-04 +date: 2024-01-05 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_core_user_settings_server.mdx b/api_docs/kbn_core_user_settings_server.mdx index b4252ff9424a..f95c6ea99795 100644 --- a/api_docs/kbn_core_user_settings_server.mdx +++ b/api_docs/kbn_core_user_settings_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-settings-server title: "@kbn/core-user-settings-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-settings-server plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-settings-server'] --- import kbnCoreUserSettingsServerObj from './kbn_core_user_settings_server.devdocs.json'; diff --git a/api_docs/kbn_core_user_settings_server_internal.mdx b/api_docs/kbn_core_user_settings_server_internal.mdx index 3fcfb92e24af..0a5de0b387e3 100644 --- a/api_docs/kbn_core_user_settings_server_internal.mdx +++ b/api_docs/kbn_core_user_settings_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-settings-server-internal title: "@kbn/core-user-settings-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-settings-server-internal plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-settings-server-internal'] --- import kbnCoreUserSettingsServerInternalObj from './kbn_core_user_settings_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_user_settings_server_mocks.mdx b/api_docs/kbn_core_user_settings_server_mocks.mdx index bcd3b4593802..a469906822a7 100644 --- a/api_docs/kbn_core_user_settings_server_mocks.mdx +++ b/api_docs/kbn_core_user_settings_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-settings-server-mocks title: "@kbn/core-user-settings-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-settings-server-mocks plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-settings-server-mocks'] --- import kbnCoreUserSettingsServerMocksObj from './kbn_core_user_settings_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_crypto.mdx b/api_docs/kbn_crypto.mdx index 1756c3f446e3..62d9f95e0951 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: 2024-01-04 +date: 2024-01-05 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 df724db842c5..d7ca756cce0e 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/crypto-browser'] --- import kbnCryptoBrowserObj from './kbn_crypto_browser.devdocs.json'; diff --git a/api_docs/kbn_custom_icons.mdx b/api_docs/kbn_custom_icons.mdx index f2a931c88273..a0ca9002c070 100644 --- a/api_docs/kbn_custom_icons.mdx +++ b/api_docs/kbn_custom_icons.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-custom-icons title: "@kbn/custom-icons" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/custom-icons plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/custom-icons'] --- import kbnCustomIconsObj from './kbn_custom_icons.devdocs.json'; diff --git a/api_docs/kbn_custom_integrations.mdx b/api_docs/kbn_custom_integrations.mdx index 99d54015c69a..3fcd8906bd39 100644 --- a/api_docs/kbn_custom_integrations.mdx +++ b/api_docs/kbn_custom_integrations.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-custom-integrations title: "@kbn/custom-integrations" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/custom-integrations plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/custom-integrations'] --- import kbnCustomIntegrationsObj from './kbn_custom_integrations.devdocs.json'; diff --git a/api_docs/kbn_cypress_config.mdx b/api_docs/kbn_cypress_config.mdx index e9a58ed538b8..bef6cd7cc7ac 100644 --- a/api_docs/kbn_cypress_config.mdx +++ b/api_docs/kbn_cypress_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cypress-config title: "@kbn/cypress-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cypress-config plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cypress-config'] --- import kbnCypressConfigObj from './kbn_cypress_config.devdocs.json'; diff --git a/api_docs/kbn_data_service.mdx b/api_docs/kbn_data_service.mdx index 643081b1d4da..6f263e3da035 100644 --- a/api_docs/kbn_data_service.mdx +++ b/api_docs/kbn_data_service.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-data-service title: "@kbn/data-service" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/data-service plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/data-service'] --- import kbnDataServiceObj from './kbn_data_service.devdocs.json'; diff --git a/api_docs/kbn_datemath.mdx b/api_docs/kbn_datemath.mdx index 81c40771e0bb..16beebc82084 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/datemath'] --- import kbnDatemathObj from './kbn_datemath.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_analytics.mdx b/api_docs/kbn_deeplinks_analytics.mdx index 2f5c0b0c898e..6c571e0fe0b4 100644 --- a/api_docs/kbn_deeplinks_analytics.mdx +++ b/api_docs/kbn_deeplinks_analytics.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-analytics title: "@kbn/deeplinks-analytics" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-analytics plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-analytics'] --- import kbnDeeplinksAnalyticsObj from './kbn_deeplinks_analytics.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_devtools.mdx b/api_docs/kbn_deeplinks_devtools.mdx index be2b50795b6b..2da79e7a1f59 100644 --- a/api_docs/kbn_deeplinks_devtools.mdx +++ b/api_docs/kbn_deeplinks_devtools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-devtools title: "@kbn/deeplinks-devtools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-devtools plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-devtools'] --- import kbnDeeplinksDevtoolsObj from './kbn_deeplinks_devtools.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_management.mdx b/api_docs/kbn_deeplinks_management.mdx index 9a9c64b5db9b..95bff06def67 100644 --- a/api_docs/kbn_deeplinks_management.mdx +++ b/api_docs/kbn_deeplinks_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-management title: "@kbn/deeplinks-management" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-management plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-management'] --- import kbnDeeplinksManagementObj from './kbn_deeplinks_management.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_ml.mdx b/api_docs/kbn_deeplinks_ml.mdx index 7afa5a8820ef..5a9306c0523a 100644 --- a/api_docs/kbn_deeplinks_ml.mdx +++ b/api_docs/kbn_deeplinks_ml.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-ml title: "@kbn/deeplinks-ml" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-ml plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-ml'] --- import kbnDeeplinksMlObj from './kbn_deeplinks_ml.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_observability.mdx b/api_docs/kbn_deeplinks_observability.mdx index f43d2395f139..da7f8ac91cd9 100644 --- a/api_docs/kbn_deeplinks_observability.mdx +++ b/api_docs/kbn_deeplinks_observability.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-observability title: "@kbn/deeplinks-observability" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-observability plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-observability'] --- import kbnDeeplinksObservabilityObj from './kbn_deeplinks_observability.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_search.mdx b/api_docs/kbn_deeplinks_search.mdx index f213317ca7a0..8957459c8787 100644 --- a/api_docs/kbn_deeplinks_search.mdx +++ b/api_docs/kbn_deeplinks_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-search title: "@kbn/deeplinks-search" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-search plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-search'] --- import kbnDeeplinksSearchObj from './kbn_deeplinks_search.devdocs.json'; diff --git a/api_docs/kbn_default_nav_analytics.mdx b/api_docs/kbn_default_nav_analytics.mdx index 2cac4b3d4fce..0584a1becfdd 100644 --- a/api_docs/kbn_default_nav_analytics.mdx +++ b/api_docs/kbn_default_nav_analytics.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-default-nav-analytics title: "@kbn/default-nav-analytics" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/default-nav-analytics plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/default-nav-analytics'] --- import kbnDefaultNavAnalyticsObj from './kbn_default_nav_analytics.devdocs.json'; diff --git a/api_docs/kbn_default_nav_devtools.mdx b/api_docs/kbn_default_nav_devtools.mdx index 6fcd2c17b24e..d1172c422ae5 100644 --- a/api_docs/kbn_default_nav_devtools.mdx +++ b/api_docs/kbn_default_nav_devtools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-default-nav-devtools title: "@kbn/default-nav-devtools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/default-nav-devtools plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/default-nav-devtools'] --- import kbnDefaultNavDevtoolsObj from './kbn_default_nav_devtools.devdocs.json'; diff --git a/api_docs/kbn_default_nav_management.mdx b/api_docs/kbn_default_nav_management.mdx index d6165f2f72d2..97f2b0e545f3 100644 --- a/api_docs/kbn_default_nav_management.mdx +++ b/api_docs/kbn_default_nav_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-default-nav-management title: "@kbn/default-nav-management" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/default-nav-management plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/default-nav-management'] --- import kbnDefaultNavManagementObj from './kbn_default_nav_management.devdocs.json'; diff --git a/api_docs/kbn_default_nav_ml.mdx b/api_docs/kbn_default_nav_ml.mdx index b5a858abc505..ea8203e7807d 100644 --- a/api_docs/kbn_default_nav_ml.mdx +++ b/api_docs/kbn_default_nav_ml.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-default-nav-ml title: "@kbn/default-nav-ml" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/default-nav-ml plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/default-nav-ml'] --- import kbnDefaultNavMlObj from './kbn_default_nav_ml.devdocs.json'; diff --git a/api_docs/kbn_dev_cli_errors.mdx b/api_docs/kbn_dev_cli_errors.mdx index ff8d6d8c7437..0bcb226be09e 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: 2024-01-04 +date: 2024-01-05 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 41dc8147ad3a..4a5e0f11ef6c 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: 2024-01-04 +date: 2024-01-05 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 e4581551a701..652c7f260d80 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: 2024-01-04 +date: 2024-01-05 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 d8eba73051f3..c4901a654547 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-utils'] --- import kbnDevUtilsObj from './kbn_dev_utils.devdocs.json'; diff --git a/api_docs/kbn_discover_utils.mdx b/api_docs/kbn_discover_utils.mdx index 834b54a7cc8b..0aebf568df0e 100644 --- a/api_docs/kbn_discover_utils.mdx +++ b/api_docs/kbn_discover_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-discover-utils title: "@kbn/discover-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/discover-utils plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/discover-utils'] --- import kbnDiscoverUtilsObj from './kbn_discover_utils.devdocs.json'; diff --git a/api_docs/kbn_doc_links.mdx b/api_docs/kbn_doc_links.mdx index 26ad9f0b338a..5a5b37d1782b 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: 2024-01-04 +date: 2024-01-05 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 97ec6e097df3..32348f44bd00 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/docs-utils'] --- import kbnDocsUtilsObj from './kbn_docs_utils.devdocs.json'; diff --git a/api_docs/kbn_dom_drag_drop.mdx b/api_docs/kbn_dom_drag_drop.mdx index 69962080ec4d..9828cab37f00 100644 --- a/api_docs/kbn_dom_drag_drop.mdx +++ b/api_docs/kbn_dom_drag_drop.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dom-drag-drop title: "@kbn/dom-drag-drop" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dom-drag-drop plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dom-drag-drop'] --- import kbnDomDragDropObj from './kbn_dom_drag_drop.devdocs.json'; diff --git a/api_docs/kbn_ebt_tools.mdx b/api_docs/kbn_ebt_tools.mdx index b9a95c21a65f..8508582482b8 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ebt-tools'] --- import kbnEbtToolsObj from './kbn_ebt_tools.devdocs.json'; diff --git a/api_docs/kbn_ecs.mdx b/api_docs/kbn_ecs.mdx index 655a8f472780..4286c1ccfe66 100644 --- a/api_docs/kbn_ecs.mdx +++ b/api_docs/kbn_ecs.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ecs title: "@kbn/ecs" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ecs plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ecs'] --- import kbnEcsObj from './kbn_ecs.devdocs.json'; diff --git a/api_docs/kbn_ecs_data_quality_dashboard.mdx b/api_docs/kbn_ecs_data_quality_dashboard.mdx index 5f82c5773956..f96a9ec52b92 100644 --- a/api_docs/kbn_ecs_data_quality_dashboard.mdx +++ b/api_docs/kbn_ecs_data_quality_dashboard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ecs-data-quality-dashboard title: "@kbn/ecs-data-quality-dashboard" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ecs-data-quality-dashboard plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ecs-data-quality-dashboard'] --- import kbnEcsDataQualityDashboardObj from './kbn_ecs_data_quality_dashboard.devdocs.json'; diff --git a/api_docs/kbn_elastic_agent_utils.mdx b/api_docs/kbn_elastic_agent_utils.mdx index c37ce828a851..f6df41c4f6df 100644 --- a/api_docs/kbn_elastic_agent_utils.mdx +++ b/api_docs/kbn_elastic_agent_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-elastic-agent-utils title: "@kbn/elastic-agent-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/elastic-agent-utils plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/elastic-agent-utils'] --- import kbnElasticAgentUtilsObj from './kbn_elastic_agent_utils.devdocs.json'; diff --git a/api_docs/kbn_elastic_assistant.mdx b/api_docs/kbn_elastic_assistant.mdx index 1d76023b5865..909678cae316 100644 --- a/api_docs/kbn_elastic_assistant.mdx +++ b/api_docs/kbn_elastic_assistant.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-elastic-assistant title: "@kbn/elastic-assistant" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/elastic-assistant plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/elastic-assistant'] --- import kbnElasticAssistantObj from './kbn_elastic_assistant.devdocs.json'; diff --git a/api_docs/kbn_elastic_assistant_common.mdx b/api_docs/kbn_elastic_assistant_common.mdx index dc32cd0edca7..e2e4f236a1a0 100644 --- a/api_docs/kbn_elastic_assistant_common.mdx +++ b/api_docs/kbn_elastic_assistant_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-elastic-assistant-common title: "@kbn/elastic-assistant-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/elastic-assistant-common plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/elastic-assistant-common'] --- import kbnElasticAssistantCommonObj from './kbn_elastic_assistant_common.devdocs.json'; diff --git a/api_docs/kbn_es.mdx b/api_docs/kbn_es.mdx index fef9a0cc1a18..da45af0b343e 100644 --- a/api_docs/kbn_es.mdx +++ b/api_docs/kbn_es.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es title: "@kbn/es" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es'] --- import kbnEsObj from './kbn_es.devdocs.json'; diff --git a/api_docs/kbn_es_archiver.mdx b/api_docs/kbn_es_archiver.mdx index cb8a2c1ea7cb..67abe05e9bf2 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: 2024-01-04 +date: 2024-01-05 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 211c745a6f22..2c423d62f92f 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-errors'] --- import kbnEsErrorsObj from './kbn_es_errors.devdocs.json'; diff --git a/api_docs/kbn_es_query.mdx b/api_docs/kbn_es_query.mdx index 74a7c73aec30..6bdb08de3efe 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: 2024-01-04 +date: 2024-01-05 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 2239b14ba2ac..0b2165aa8af4 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: 2024-01-04 +date: 2024-01-05 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 a87f273b8bdd..4791ea44d6b3 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/eslint-plugin-imports'] --- import kbnEslintPluginImportsObj from './kbn_eslint_plugin_imports.devdocs.json'; diff --git a/api_docs/kbn_event_annotation_common.mdx b/api_docs/kbn_event_annotation_common.mdx index a78fb63d369e..e5fcb23a6568 100644 --- a/api_docs/kbn_event_annotation_common.mdx +++ b/api_docs/kbn_event_annotation_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-event-annotation-common title: "@kbn/event-annotation-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/event-annotation-common plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/event-annotation-common'] --- import kbnEventAnnotationCommonObj from './kbn_event_annotation_common.devdocs.json'; diff --git a/api_docs/kbn_event_annotation_components.mdx b/api_docs/kbn_event_annotation_components.mdx index 7b0106699b55..5187ac07cd6f 100644 --- a/api_docs/kbn_event_annotation_components.mdx +++ b/api_docs/kbn_event_annotation_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-event-annotation-components title: "@kbn/event-annotation-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/event-annotation-components plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/event-annotation-components'] --- import kbnEventAnnotationComponentsObj from './kbn_event_annotation_components.devdocs.json'; diff --git a/api_docs/kbn_expandable_flyout.mdx b/api_docs/kbn_expandable_flyout.mdx index ae0884401810..8807a3ef0669 100644 --- a/api_docs/kbn_expandable_flyout.mdx +++ b/api_docs/kbn_expandable_flyout.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-expandable-flyout title: "@kbn/expandable-flyout" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/expandable-flyout plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/expandable-flyout'] --- import kbnExpandableFlyoutObj from './kbn_expandable_flyout.devdocs.json'; diff --git a/api_docs/kbn_field_types.mdx b/api_docs/kbn_field_types.mdx index cb55a29f3f27..d30d8c4c0928 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/field-types'] --- import kbnFieldTypesObj from './kbn_field_types.devdocs.json'; diff --git a/api_docs/kbn_field_utils.mdx b/api_docs/kbn_field_utils.mdx index 06b57eb8264e..c1a49910d999 100644 --- a/api_docs/kbn_field_utils.mdx +++ b/api_docs/kbn_field_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-field-utils title: "@kbn/field-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/field-utils plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/field-utils'] --- import kbnFieldUtilsObj from './kbn_field_utils.devdocs.json'; diff --git a/api_docs/kbn_find_used_node_modules.mdx b/api_docs/kbn_find_used_node_modules.mdx index 0c91dccea3f6..ef45987a7a58 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: 2024-01-04 +date: 2024-01-05 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 1f31375de175..222bd8a02a9f 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: 2024-01-04 +date: 2024-01-05 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_ftr_common_functional_ui_services.devdocs.json b/api_docs/kbn_ftr_common_functional_ui_services.devdocs.json index 79a57d84974d..e2f2105db52c 100644 --- a/api_docs/kbn_ftr_common_functional_ui_services.devdocs.json +++ b/api_docs/kbn_ftr_common_functional_ui_services.devdocs.json @@ -17,10 +17,9981 @@ "objects": [] }, "common": { - "classes": [], + "classes": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper", + "type": "Class", + "tags": [], + "label": "WebElementWrapper", + "description": [], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.isChromium", + "type": "boolean", + "tags": [], + "label": "isChromium", + "description": [], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.create", + "type": "Function", + "tags": [], + "label": "create", + "description": [], + "signature": [ + "(webElement: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.WebElementWrapper", + "text": "WebElementWrapper" + }, + " | ", + "WebElement", + ", locator: ", + "By", + " | null, driver: ", + "WebDriver", + ", timeout: number, fixedHeaderHeight: number, logger: ", + { + "pluginId": "@kbn/tooling-log", + "scope": "common", + "docId": "kibKbnToolingLogPluginApi", + "section": "def-common.ToolingLog", + "text": "ToolingLog" + }, + ", browserType: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.Browsers", + "text": "Browsers" + }, + ") => ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.WebElementWrapper", + "text": "WebElementWrapper" + } + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.create.$1", + "type": "CompoundType", + "tags": [], + "label": "webElement", + "description": [], + "signature": [ + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.WebElementWrapper", + "text": "WebElementWrapper" + }, + " | ", + "WebElement" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.create.$2", + "type": "CompoundType", + "tags": [], + "label": "locator", + "description": [], + "signature": [ + "By", + " | null" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.create.$3", + "type": "Object", + "tags": [], + "label": "driver", + "description": [], + "signature": [ + "WebDriver" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.create.$4", + "type": "number", + "tags": [], + "label": "timeout", + "description": [], + "signature": [ + "number" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.create.$5", + "type": "number", + "tags": [], + "label": "fixedHeaderHeight", + "description": [], + "signature": [ + "number" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.create.$6", + "type": "Object", + "tags": [], + "label": "logger", + "description": [], + "signature": [ + { + "pluginId": "@kbn/tooling-log", + "scope": "common", + "docId": "kibKbnToolingLogPluginApi", + "section": "def-common.ToolingLog", + "text": "ToolingLog" + } + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.create.$7", + "type": "Enum", + "tags": [], + "label": "browserType", + "description": [], + "signature": [ + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.Browsers", + "text": "Browsers" + } + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.Unnamed", + "type": "Function", + "tags": [], + "label": "Constructor", + "description": [], + "signature": [ + "any" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.Unnamed.$1", + "type": "Object", + "tags": [], + "label": "_webElement", + "description": [], + "signature": [ + "WebElement" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.Unnamed.$2", + "type": "CompoundType", + "tags": [], + "label": "locator", + "description": [], + "signature": [ + "By", + " | null" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.Unnamed.$3", + "type": "Object", + "tags": [], + "label": "driver", + "description": [], + "signature": [ + "WebDriver" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.Unnamed.$4", + "type": "number", + "tags": [], + "label": "timeout", + "description": [], + "signature": [ + "number" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.Unnamed.$5", + "type": "number", + "tags": [], + "label": "fixedHeaderHeight", + "description": [], + "signature": [ + "number" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.Unnamed.$6", + "type": "Object", + "tags": [], + "label": "logger", + "description": [], + "signature": [ + { + "pluginId": "@kbn/tooling-log", + "scope": "common", + "docId": "kibKbnToolingLogPluginApi", + "section": "def-common.ToolingLog", + "text": "ToolingLog" + } + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.Unnamed.$7", + "type": "Enum", + "tags": [], + "label": "browserType", + "description": [], + "signature": [ + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.Browsers", + "text": "Browsers" + } + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.isDisplayed", + "type": "Function", + "tags": [ + "return" + ], + "label": "isDisplayed", + "description": [ + "\nReturns whether or not the element would be visible to an actual user. This means\nthat the following types of elements are considered to be not displayed:\n\n - Elements with display: none\n - Elements with visibility: hidden\n - Elements positioned outside of the viewport that cannot be scrolled into view\n - Elements with opacity: 0\n - Elements with no offsetWidth or offsetHeight\n\nhttps://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/lib/webdriver_exports_WebElement.html#isDisplayed\n" + ], + "signature": [ + "() => Promise" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.isEnabled", + "type": "Function", + "tags": [ + "return" + ], + "label": "isEnabled", + "description": [ + "\nTests whether this element is enabled, as dictated by the disabled attribute.\nhttps://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/lib/webdriver_exports_WebElement.html#isEnabled\n" + ], + "signature": [ + "() => Promise" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.isSelected", + "type": "Function", + "tags": [ + "return" + ], + "label": "isSelected", + "description": [ + "\nTests whether this element is selected.\nhttps://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/lib/webdriver_exports_WebElement.html#isSelected\n" + ], + "signature": [ + "() => Promise" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.click", + "type": "Function", + "tags": [ + "return" + ], + "label": "click", + "description": [ + "\nClicks on this element.\nhttps://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/lib/webdriver_exports_WebElement.html#click\n" + ], + "signature": [ + "(topOffset?: number | undefined) => Promise" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.click.$1", + "type": "number", + "tags": [], + "label": "topOffset", + "description": [], + "signature": [ + "number | undefined" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.focus", + "type": "Function", + "tags": [ + "return" + ], + "label": "focus", + "description": [ + "\nFocuses this element.\n" + ], + "signature": [ + "() => Promise" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.openHref", + "type": "Function", + "tags": [ + "return" + ], + "label": "openHref", + "description": [ + "\nIf possible, opens 'href' of this element directly through the URL\n" + ], + "signature": [ + "() => Promise" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.elementHasClass", + "type": "Function", + "tags": [ + "return" + ], + "label": "elementHasClass", + "description": [ + "\nCheck if webelement wrapper has a specific class.\n" + ], + "signature": [ + "(className: string) => Promise" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.elementHasClass.$1", + "type": "string", + "tags": [], + "label": "className", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.clearValue", + "type": "Function", + "tags": [ + "default" + ], + "label": "clearValue", + "description": [ + "\nClear the value of this element. This command has no effect if the underlying DOM element\nis neither a text INPUT element nor a TEXTAREA element.\nhttps://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/lib/webdriver_exports_WebElement.html#clear\n" + ], + "signature": [ + "(options?: ClearOptions) => Promise" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.clearValue.$1", + "type": "Object", + "tags": [], + "label": "options", + "description": [ + "option to clear input with JS: `arguments[0].value=''`" + ], + "signature": [ + "ClearOptions" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.clearValueWithKeyboard", + "type": "Function", + "tags": [ + "default" + ], + "label": "clearValueWithKeyboard", + "description": [ + "\nClear the value of this element using Keyboard" + ], + "signature": [ + "(options?: TypeOptions) => Promise" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.clearValueWithKeyboard.$1", + "type": "Object", + "tags": [], + "label": "options", + "description": [ + "to input characters one by one" + ], + "signature": [ + "TypeOptions" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.selectValueWithKeyboard", + "type": "Function", + "tags": [], + "label": "selectValueWithKeyboard", + "description": [], + "signature": [ + "() => Promise" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.type", + "type": "Function", + "tags": [ + "return" + ], + "label": "type", + "description": [ + "\nTypes a key sequence on the DOM element represented by this instance. Modifier keys\n(SHIFT, CONTROL, ALT, META) are stateful; once a modifier is processed in the key sequence,\nthat key state is toggled until one of the following occurs:\n\nThe modifier key is encountered again in the sequence. At this point the state of the key is\ntoggled (along with the appropriate keyup/down events).\nThe input.Key.NULL key is encountered in the sequence. When this key is encountered, all\nmodifier keys current in the down state are released (with accompanying keyup events). The NULL\nkey can be used to simulate common keyboard shortcuts.\nhttps://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/lib/webdriver_exports_WebElement.html#sendKeys\n" + ], + "signature": [ + "(value: string | string[], options?: TypeOptions) => Promise" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.type.$1", + "type": "CompoundType", + "tags": [], + "label": "value", + "description": [], + "signature": [ + "string | string[]" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.type.$2", + "type": "Object", + "tags": [], + "label": "options", + "description": [], + "signature": [ + "TypeOptions" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.pressKeys", + "type": "Function", + "tags": [], + "label": "pressKeys", + "description": [], + "signature": [ + "{ (keys: T | T[]): Promise; (keys: T | T[]): Promise; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.pressKeys.$1", + "type": "string", + "tags": [], + "label": "keys", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.getAttribute", + "type": "Function", + "tags": [], + "label": "getAttribute", + "description": [ + "\nRetrieves the current value of the given attribute of this element. Will return the current\nvalue, even if it has been modified after the page has been loaded. More exactly, this method\nwill return the value of the given attribute, unless that attribute is not present, in which\ncase the value of the property with the same name is returned. If neither value is set, null\nis returned (for example, the \"value\" property of a textarea element). The \"style\" attribute\nis converted as best can be to a text representation with a trailing semi-colon.\nhttps://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/lib/webdriver_exports_WebElement.html#getAttribute\n" + ], + "signature": [ + "(name: string) => Promise" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.getAttribute.$1", + "type": "string", + "tags": [], + "label": "name", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.getComputedStyle", + "type": "Function", + "tags": [ + "return" + ], + "label": "getComputedStyle", + "description": [ + "\nRetrieves the value of a computed style property for this instance. If the element inherits\nthe named style from its parent, the parent will be queried for its value. Where possible,\ncolor values will be converted to their hex representation (e.g. #00ff00 instead of rgb(0, 255, 0)).\nhttps://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/lib/webdriver_exports_WebElement.html#getCssValue\n" + ], + "signature": [ + "(propertyName: string) => Promise" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.getComputedStyle.$1", + "type": "string", + "tags": [], + "label": "propertyName", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.getVisibleText", + "type": "Function", + "tags": [ + "return" + ], + "label": "getVisibleText", + "description": [ + "\nGet the visible (i.e. not hidden by CSS) innerText of this element, including sub-elements,\nwithout any leading or trailing whitespace.\nhttps://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/lib/webdriver_exports_WebElement.html#getText\n" + ], + "signature": [ + "() => Promise" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.getTagName", + "type": "Function", + "tags": [], + "label": "getTagName", + "description": [], + "signature": [ + "{ (): Promise; (): Promise; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.getPosition", + "type": "Function", + "tags": [ + "return" + ], + "label": "getPosition", + "description": [ + "\nReturns an object describing an element's location, in pixels relative to the document element,\nand the element's size in pixels.\nhttps://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/lib/webdriver_exports_WebElement.html#getRect\n" + ], + "signature": [ + "() => Promise<{ height: number; width: number; x: number; y: number; }>" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.getSize", + "type": "Function", + "tags": [ + "return" + ], + "label": "getSize", + "description": [ + "\nReturns an object describing an element's location, in pixels relative to the document element,\nand the element's size in pixels.\nhttps://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/lib/webdriver_exports_WebElement.html#getRect\n" + ], + "signature": [ + "() => Promise<{ height: number; width: number; x: number; y: number; }>" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.moveMouseTo", + "type": "Function", + "tags": [ + "return" + ], + "label": "moveMouseTo", + "description": [ + "\nMoves the remote environment’s mouse cursor to the current element with optional offset\nhttps://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/lib/input_exports_Actions.html#move" + ], + "signature": [ + "(options?: { xOffset: number; yOffset: number; }) => Promise" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.moveMouseTo.$1", + "type": "Object", + "tags": [], + "label": "options", + "description": [], + "signature": [ + "{ xOffset: number; yOffset: number; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.clickMouseButton", + "type": "Function", + "tags": [ + "return" + ], + "label": "clickMouseButton", + "description": [ + "\nInserts an action for moving the mouse to element center, unless optional offset is provided.\nThen adds an action for left-click (down/up) with the mouse.\nhttps://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/lib/input_exports_Actions.html#click\n" + ], + "signature": [ + "(options?: { xOffset: number; yOffset: number; }) => Promise" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.clickMouseButton.$1", + "type": "Object", + "tags": [], + "label": "options", + "description": [], + "signature": [ + "{ xOffset: number; yOffset: number; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.doubleClick", + "type": "Function", + "tags": [ + "return" + ], + "label": "doubleClick", + "description": [ + "\nInserts action for performing a double left-click with the mouse.\nhttps://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/lib/input_exports_Actions.html#doubleClick" + ], + "signature": [ + "() => Promise" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.findByCssSelector", + "type": "Function", + "tags": [ + "return" + ], + "label": "findByCssSelector", + "description": [ + "\nGets the first element inside this element matching the given CSS selector.\nhttps://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/lib/webdriver_exports_WebElement.html#findElement\n" + ], + "signature": [ + "(selector: string) => Promise<", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.WebElementWrapper", + "text": "WebElementWrapper" + }, + ">" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.findByCssSelector.$1", + "type": "string", + "tags": [], + "label": "selector", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.findAllByCssSelector", + "type": "Function", + "tags": [ + "return" + ], + "label": "findAllByCssSelector", + "description": [ + "\nGets all elements inside this element matching the given CSS selector.\nhttps://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/lib/webdriver_exports_WebElement.html#findElement\n" + ], + "signature": [ + "(selector: string, timeout?: number | undefined) => Promise<", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.WebElementWrapper", + "text": "WebElementWrapper" + }, + "[]>" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.findAllByCssSelector.$1", + "type": "string", + "tags": [], + "label": "selector", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.findAllByCssSelector.$2", + "type": "number", + "tags": [], + "label": "timeout", + "description": [], + "signature": [ + "number | undefined" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.findByTestSubject", + "type": "Function", + "tags": [ + "return" + ], + "label": "findByTestSubject", + "description": [ + "\nGets the first element inside this element matching the given data-test-subj selector.\n" + ], + "signature": [ + "(selector: string) => Promise<", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.WebElementWrapper", + "text": "WebElementWrapper" + }, + ">" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.findByTestSubject.$1", + "type": "string", + "tags": [], + "label": "selector", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.findAllByTestSubject", + "type": "Function", + "tags": [ + "return" + ], + "label": "findAllByTestSubject", + "description": [ + "\nGets all elements inside this element matching the given data-test-subj selector.\n" + ], + "signature": [ + "(selector: string, timeout?: number | undefined) => Promise<", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.WebElementWrapper", + "text": "WebElementWrapper" + }, + "[]>" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.findAllByTestSubject.$1", + "type": "string", + "tags": [], + "label": "selector", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.findAllByTestSubject.$2", + "type": "number", + "tags": [], + "label": "timeout", + "description": [], + "signature": [ + "number | undefined" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.findByClassName", + "type": "Function", + "tags": [ + "return" + ], + "label": "findByClassName", + "description": [ + "\nGets the first element inside this element matching the given CSS class name.\nhttps://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/lib/webdriver_exports_WebElement.html#findElement\n" + ], + "signature": [ + "(className: string) => Promise<", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.WebElementWrapper", + "text": "WebElementWrapper" + }, + ">" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.findByClassName.$1", + "type": "string", + "tags": [], + "label": "className", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.findAllByClassName", + "type": "Function", + "tags": [ + "return" + ], + "label": "findAllByClassName", + "description": [ + "\nGets all elements inside this element matching the given CSS class name.\nhttps://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/lib/webdriver_exports_WebElement.html#findElement\n" + ], + "signature": [ + "(className: string, timeout?: number | undefined) => Promise<", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.WebElementWrapper", + "text": "WebElementWrapper" + }, + "[]>" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.findAllByClassName.$1", + "type": "string", + "tags": [], + "label": "className", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.findAllByClassName.$2", + "type": "number", + "tags": [], + "label": "timeout", + "description": [], + "signature": [ + "number | undefined" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.findByTagName", + "type": "Function", + "tags": [], + "label": "findByTagName", + "description": [], + "signature": [ + "{ (tagName: T): Promise<", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.WebElementWrapper", + "text": "WebElementWrapper" + }, + ">; (tagName: T): Promise<", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.WebElementWrapper", + "text": "WebElementWrapper" + }, + ">; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.findByTagName.$1", + "type": "string", + "tags": [], + "label": "tagName", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.findAllByTagName", + "type": "Function", + "tags": [], + "label": "findAllByTagName", + "description": [], + "signature": [ + "{ (tagName: T, timeout?: number | undefined): Promise<", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.WebElementWrapper", + "text": "WebElementWrapper" + }, + "[]>; (tagName: T, timeout?: number | undefined): Promise<", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.WebElementWrapper", + "text": "WebElementWrapper" + }, + "[]>; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.findAllByTagName.$1", + "type": "string", + "tags": [], + "label": "tagName", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.findAllByTagName.$2", + "type": "number", + "tags": [], + "label": "timeout", + "description": [], + "signature": [ + "number | undefined" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.findByXpath", + "type": "Function", + "tags": [ + "return" + ], + "label": "findByXpath", + "description": [ + "\nGets the first element inside this element matching the given XPath selector.\nhttps://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/lib/webdriver_exports_WebElement.html#findElement\n" + ], + "signature": [ + "(selector: string) => Promise<", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.WebElementWrapper", + "text": "WebElementWrapper" + }, + ">" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.findByXpath.$1", + "type": "string", + "tags": [], + "label": "selector", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.findAllByXpath", + "type": "Function", + "tags": [ + "return" + ], + "label": "findAllByXpath", + "description": [ + "\nGets all elements inside this element matching the given XPath selector.\nhttps://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/lib/webdriver_exports_WebElement.html#findElement\n" + ], + "signature": [ + "(selector: string, timeout?: number | undefined) => Promise<", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.WebElementWrapper", + "text": "WebElementWrapper" + }, + "[]>" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.findAllByXpath.$1", + "type": "string", + "tags": [], + "label": "selector", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.findAllByXpath.$2", + "type": "number", + "tags": [], + "label": "timeout", + "description": [], + "signature": [ + "number | undefined" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.findByPartialLinkText", + "type": "Function", + "tags": [ + "return" + ], + "label": "findByPartialLinkText", + "description": [ + "\nGets the first element inside this element matching the given partial link text.\nhttps://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/lib/webdriver_exports_WebElement.html#findElement\n" + ], + "signature": [ + "(linkText: string) => Promise<", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.WebElementWrapper", + "text": "WebElementWrapper" + }, + ">" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.findByPartialLinkText.$1", + "type": "string", + "tags": [], + "label": "linkText", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.findAllByPartialLinkText", + "type": "Function", + "tags": [ + "return" + ], + "label": "findAllByPartialLinkText", + "description": [ + "\nGets all elements inside this element matching the given partial link text.\nhttps://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/lib/webdriver_exports_WebElement.html#findElement\n" + ], + "signature": [ + "(linkText: string, timeout?: number | undefined) => Promise<", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.WebElementWrapper", + "text": "WebElementWrapper" + }, + "[]>" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.findAllByPartialLinkText.$1", + "type": "string", + "tags": [], + "label": "linkText", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.findAllByPartialLinkText.$2", + "type": "number", + "tags": [], + "label": "timeout", + "description": [], + "signature": [ + "number | undefined" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.waitForDeletedByCssSelector", + "type": "Function", + "tags": [ + "return" + ], + "label": "waitForDeletedByCssSelector", + "description": [ + "\nWaits for all elements inside this element matching the given CSS selector to be destroyed.\n" + ], + "signature": [ + "(selector: string, implicitTimeout?: number) => Promise" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.waitForDeletedByCssSelector.$1", + "type": "string", + "tags": [], + "label": "selector", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.waitForDeletedByCssSelector.$2", + "type": "number", + "tags": [], + "label": "implicitTimeout", + "description": [], + "signature": [ + "number" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.scrollIntoView", + "type": "Function", + "tags": [ + "return" + ], + "label": "scrollIntoView", + "description": [ + "\nScroll the element into view\n" + ], + "signature": [ + "(scrollIntoViewOptions?: ScrollIntoViewOptions | undefined) => Promise" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.scrollIntoView.$1", + "type": "Object", + "tags": [], + "label": "scrollIntoViewOptions", + "description": [], + "signature": [ + "ScrollIntoViewOptions | undefined" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.scrollIntoViewIfNecessary", + "type": "Function", + "tags": [ + "nonstandard", + "return" + ], + "label": "scrollIntoViewIfNecessary", + "description": [ + "\nScroll the element into view if it is not already, avoiding the fixed header if necessary\nThis method is a variation of the scrollIntoView method, where we only scroll into an element\nif it is not part of the \"scrollable view\".\nThis implies a specific behavior, since the \"scrollable view\" of the view is identified by\nthe `document.scrollingElement`, which always results to the html or body tag.\n\nUse cases:\n- An element (a section, a footer) is not visible in the whole page and we need to scroll into it.\n- An element is covered by the fixed header and we need to scroll into it ensuring is not covered.\n\nIn case you have a scrollable list smaller that the size of the HTML document and you need\nto scroll into an element of that list, prefer using the `.scrollIntoView` method.\n" + ], + "signature": [ + "(topOffsetOrOptions?: number | { topOffset?: number | undefined; bottomOffset?: number | undefined; } | undefined) => Promise" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.scrollIntoViewIfNecessary.$1", + "type": "CompoundType", + "tags": [], + "label": "topOffsetOrOptions", + "description": [], + "signature": [ + "number | { topOffset?: number | undefined; bottomOffset?: number | undefined; } | undefined" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.parseDomContent", + "type": "Function", + "tags": [ + "nonstandard", + "return" + ], + "label": "parseDomContent", + "description": [ + "\nGets element innerHTML and wrap it up with cheerio\n" + ], + "signature": [ + "() => Promise<", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerioStatic", + "text": "CustomCheerioStatic" + }, + ">" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.WebElementWrapper.takeScreenshot", + "type": "Function", + "tags": [], + "label": "takeScreenshot", + "description": [ + "\nCreates the screenshot of the element\n" + ], + "signature": [ + "() => Promise" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/web_element_wrapper.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + } + ], + "initialIsOpen": false + } + ], "functions": [], - "interfaces": [], - "enums": [], + "interfaces": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio", + "type": "Interface", + "tags": [], + "label": "CustomCheerio", + "description": [], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.Unnamed", + "type": "IndexSignature", + "tags": [], + "label": "[index: number]: Element", + "description": [], + "signature": [ + "[index: number]: cheerio.Element" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.length", + "type": "number", + "tags": [], + "label": "length", + "description": [], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.attr", + "type": "Function", + "tags": [], + "label": "attr", + "description": [], + "signature": [ + "{ (): { [attr: string]: string; }; (name: string): string; (name: string, value: any): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.attr", + "type": "Function", + "tags": [], + "label": "attr", + "description": [], + "signature": [ + "{ (): { [attr: string]: string; }; (name: string): string; (name: string, value: any): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.attr.$1", + "type": "string", + "tags": [], + "label": "name", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.attr", + "type": "Function", + "tags": [], + "label": "attr", + "description": [], + "signature": [ + "{ (): { [attr: string]: string; }; (name: string): string; (name: string, value: any): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.attr.$1", + "type": "string", + "tags": [], + "label": "name", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.attr.$2", + "type": "Any", + "tags": [], + "label": "value", + "description": [], + "signature": [ + "any" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.data", + "type": "Function", + "tags": [], + "label": "data", + "description": [], + "signature": [ + "{ (): any; (name: string): any; (name: string, value: any): any; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.data", + "type": "Function", + "tags": [], + "label": "data", + "description": [], + "signature": [ + "{ (): any; (name: string): any; (name: string, value: any): any; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.data.$1", + "type": "string", + "tags": [], + "label": "name", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.data", + "type": "Function", + "tags": [], + "label": "data", + "description": [], + "signature": [ + "{ (): any; (name: string): any; (name: string, value: any): any; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.data.$1", + "type": "string", + "tags": [], + "label": "name", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.data.$2", + "type": "Any", + "tags": [], + "label": "value", + "description": [], + "signature": [ + "any" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.val", + "type": "Function", + "tags": [], + "label": "val", + "description": [], + "signature": [ + "{ (): string; (value: string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.val", + "type": "Function", + "tags": [], + "label": "val", + "description": [], + "signature": [ + "{ (): string; (value: string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.val.$1", + "type": "string", + "tags": [], + "label": "value", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.removeAttr", + "type": "Function", + "tags": [], + "label": "removeAttr", + "description": [], + "signature": [ + "(name: string) => ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + } + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.removeAttr.$1", + "type": "string", + "tags": [], + "label": "name", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.has", + "type": "Function", + "tags": [], + "label": "has", + "description": [], + "signature": [ + "{ (selector: string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (element: cheerio.Element): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.has.$1", + "type": "string", + "tags": [], + "label": "selector", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.has", + "type": "Function", + "tags": [], + "label": "has", + "description": [], + "signature": [ + "{ (selector: string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (element: cheerio.Element): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.has.$1", + "type": "CompoundType", + "tags": [], + "label": "element", + "description": [], + "signature": [ + "cheerio.Element" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.hasClass", + "type": "Function", + "tags": [], + "label": "hasClass", + "description": [], + "signature": [ + "(className: string) => boolean" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.hasClass.$1", + "type": "string", + "tags": [], + "label": "className", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.addClass", + "type": "Function", + "tags": [], + "label": "addClass", + "description": [], + "signature": [ + "(classNames: string) => ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + } + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.addClass.$1", + "type": "string", + "tags": [], + "label": "classNames", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.removeClass", + "type": "Function", + "tags": [], + "label": "removeClass", + "description": [], + "signature": [ + "{ (): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (className: string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (func: (index: number, className: string) => string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.removeClass", + "type": "Function", + "tags": [], + "label": "removeClass", + "description": [], + "signature": [ + "{ (): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (className: string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (func: (index: number, className: string) => string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.removeClass.$1", + "type": "string", + "tags": [], + "label": "className", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.removeClass", + "type": "Function", + "tags": [], + "label": "removeClass", + "description": [], + "signature": [ + "{ (): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (className: string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (func: (index: number, className: string) => string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.removeClass.$1", + "type": "Function", + "tags": [], + "label": "func", + "description": [], + "signature": [ + "(index: number, className: string) => string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.toggleClass", + "type": "Function", + "tags": [], + "label": "toggleClass", + "description": [], + "signature": [ + "{ (className: string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (className: string, toggleSwitch: boolean): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (toggleSwitch?: boolean | undefined): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (func: (index: number, className: string, toggleSwitch: boolean) => string, toggleSwitch?: boolean | undefined): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.toggleClass.$1", + "type": "string", + "tags": [], + "label": "className", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.toggleClass", + "type": "Function", + "tags": [], + "label": "toggleClass", + "description": [], + "signature": [ + "{ (className: string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (className: string, toggleSwitch: boolean): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (toggleSwitch?: boolean | undefined): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (func: (index: number, className: string, toggleSwitch: boolean) => string, toggleSwitch?: boolean | undefined): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.toggleClass.$1", + "type": "string", + "tags": [], + "label": "className", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.toggleClass.$2", + "type": "boolean", + "tags": [], + "label": "toggleSwitch", + "description": [], + "signature": [ + "boolean" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.toggleClass", + "type": "Function", + "tags": [], + "label": "toggleClass", + "description": [], + "signature": [ + "{ (className: string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (className: string, toggleSwitch: boolean): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (toggleSwitch?: boolean | undefined): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (func: (index: number, className: string, toggleSwitch: boolean) => string, toggleSwitch?: boolean | undefined): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.toggleClass.$1", + "type": "CompoundType", + "tags": [], + "label": "toggleSwitch", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.toggleClass", + "type": "Function", + "tags": [], + "label": "toggleClass", + "description": [], + "signature": [ + "{ (className: string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (className: string, toggleSwitch: boolean): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (toggleSwitch?: boolean | undefined): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (func: (index: number, className: string, toggleSwitch: boolean) => string, toggleSwitch?: boolean | undefined): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.toggleClass.$1", + "type": "Function", + "tags": [], + "label": "func", + "description": [], + "signature": [ + "(index: number, className: string, toggleSwitch: boolean) => string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.toggleClass.$2", + "type": "CompoundType", + "tags": [], + "label": "toggleSwitch", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.is", + "type": "Function", + "tags": [], + "label": "is", + "description": [], + "signature": [ + "{ (selector: string): boolean; (element: cheerio.Element): boolean; (element: cheerio.Element[]): boolean; (selection: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "): boolean; (func: (index: number, element: cheerio.Element) => boolean): boolean; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.is.$1", + "type": "string", + "tags": [], + "label": "selector", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.is", + "type": "Function", + "tags": [], + "label": "is", + "description": [], + "signature": [ + "{ (selector: string): boolean; (element: cheerio.Element): boolean; (element: cheerio.Element[]): boolean; (selection: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "): boolean; (func: (index: number, element: cheerio.Element) => boolean): boolean; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.is.$1", + "type": "CompoundType", + "tags": [], + "label": "element", + "description": [], + "signature": [ + "cheerio.Element" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.is", + "type": "Function", + "tags": [], + "label": "is", + "description": [], + "signature": [ + "{ (selector: string): boolean; (element: cheerio.Element): boolean; (element: cheerio.Element[]): boolean; (selection: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "): boolean; (func: (index: number, element: cheerio.Element) => boolean): boolean; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.is.$1", + "type": "Array", + "tags": [], + "label": "element", + "description": [], + "signature": [ + "cheerio.Element[]" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.is", + "type": "Function", + "tags": [], + "label": "is", + "description": [], + "signature": [ + "{ (selector: string): boolean; (element: cheerio.Element): boolean; (element: cheerio.Element[]): boolean; (selection: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "): boolean; (func: (index: number, element: cheerio.Element) => boolean): boolean; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.is.$1", + "type": "Object", + "tags": [], + "label": "selection", + "description": [], + "signature": [ + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + } + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.is", + "type": "Function", + "tags": [], + "label": "is", + "description": [], + "signature": [ + "{ (selector: string): boolean; (element: cheerio.Element): boolean; (element: cheerio.Element[]): boolean; (selection: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "): boolean; (func: (index: number, element: cheerio.Element) => boolean): boolean; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.is.$1", + "type": "Function", + "tags": [], + "label": "func", + "description": [], + "signature": [ + "(index: number, element: cheerio.Element) => boolean" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.serialize", + "type": "Function", + "tags": [], + "label": "serialize", + "description": [], + "signature": [ + "() => string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.serializeArray", + "type": "Function", + "tags": [], + "label": "serializeArray", + "description": [], + "signature": [ + "() => { name: string; value: string; }[]" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.find", + "type": "Function", + "tags": [], + "label": "find", + "description": [], + "signature": [ + "{ (selector: string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (element: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.find.$1", + "type": "string", + "tags": [], + "label": "selector", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.find", + "type": "Function", + "tags": [], + "label": "find", + "description": [], + "signature": [ + "{ (selector: string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (element: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.find.$1", + "type": "Object", + "tags": [], + "label": "element", + "description": [], + "signature": [ + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + } + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.parent", + "type": "Function", + "tags": [], + "label": "parent", + "description": [], + "signature": [ + "(selector?: string | undefined) => ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + } + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.parent.$1", + "type": "string", + "tags": [], + "label": "selector", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.parents", + "type": "Function", + "tags": [], + "label": "parents", + "description": [], + "signature": [ + "(selector?: string | undefined) => ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + } + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.parents.$1", + "type": "string", + "tags": [], + "label": "selector", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.parentsUntil", + "type": "Function", + "tags": [], + "label": "parentsUntil", + "description": [], + "signature": [ + "{ (selector?: string | undefined, filter?: string | undefined): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (element: cheerio.Element, filter?: string | undefined): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (element: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + ", filter?: string | undefined): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.parentsUntil.$1", + "type": "string", + "tags": [], + "label": "selector", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.parentsUntil.$2", + "type": "string", + "tags": [], + "label": "filter", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.parentsUntil", + "type": "Function", + "tags": [], + "label": "parentsUntil", + "description": [], + "signature": [ + "{ (selector?: string | undefined, filter?: string | undefined): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (element: cheerio.Element, filter?: string | undefined): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (element: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + ", filter?: string | undefined): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.parentsUntil.$1", + "type": "CompoundType", + "tags": [], + "label": "element", + "description": [], + "signature": [ + "cheerio.Element" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.parentsUntil.$2", + "type": "string", + "tags": [], + "label": "filter", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.parentsUntil", + "type": "Function", + "tags": [], + "label": "parentsUntil", + "description": [], + "signature": [ + "{ (selector?: string | undefined, filter?: string | undefined): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (element: cheerio.Element, filter?: string | undefined): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (element: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + ", filter?: string | undefined): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.parentsUntil.$1", + "type": "Object", + "tags": [], + "label": "element", + "description": [], + "signature": [ + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + } + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.parentsUntil.$2", + "type": "string", + "tags": [], + "label": "filter", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.prop", + "type": "Function", + "tags": [], + "label": "prop", + "description": [], + "signature": [ + "{ (name: string): any; (name: string, value: any): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.prop.$1", + "type": "string", + "tags": [], + "label": "name", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.prop", + "type": "Function", + "tags": [], + "label": "prop", + "description": [], + "signature": [ + "{ (name: string): any; (name: string, value: any): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.prop.$1", + "type": "string", + "tags": [], + "label": "name", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.prop.$2", + "type": "Any", + "tags": [], + "label": "value", + "description": [], + "signature": [ + "any" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.closest", + "type": "Function", + "tags": [], + "label": "closest", + "description": [], + "signature": [ + "{ (): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (selector: string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.closest", + "type": "Function", + "tags": [], + "label": "closest", + "description": [], + "signature": [ + "{ (): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (selector: string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.closest.$1", + "type": "string", + "tags": [], + "label": "selector", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.next", + "type": "Function", + "tags": [], + "label": "next", + "description": [], + "signature": [ + "(selector?: string | undefined) => ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + } + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.next.$1", + "type": "string", + "tags": [], + "label": "selector", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.nextAll", + "type": "Function", + "tags": [], + "label": "nextAll", + "description": [], + "signature": [ + "{ (): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (selector: string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.nextAll", + "type": "Function", + "tags": [], + "label": "nextAll", + "description": [], + "signature": [ + "{ (): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (selector: string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.nextAll.$1", + "type": "string", + "tags": [], + "label": "selector", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.nextUntil", + "type": "Function", + "tags": [], + "label": "nextUntil", + "description": [], + "signature": [ + "{ (selector?: string | undefined, filter?: string | undefined): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (element: cheerio.Element, filter?: string | undefined): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (element: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + ", filter?: string | undefined): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.nextUntil.$1", + "type": "string", + "tags": [], + "label": "selector", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.nextUntil.$2", + "type": "string", + "tags": [], + "label": "filter", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.nextUntil", + "type": "Function", + "tags": [], + "label": "nextUntil", + "description": [], + "signature": [ + "{ (selector?: string | undefined, filter?: string | undefined): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (element: cheerio.Element, filter?: string | undefined): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (element: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + ", filter?: string | undefined): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.nextUntil.$1", + "type": "CompoundType", + "tags": [], + "label": "element", + "description": [], + "signature": [ + "cheerio.Element" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.nextUntil.$2", + "type": "string", + "tags": [], + "label": "filter", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.nextUntil", + "type": "Function", + "tags": [], + "label": "nextUntil", + "description": [], + "signature": [ + "{ (selector?: string | undefined, filter?: string | undefined): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (element: cheerio.Element, filter?: string | undefined): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (element: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + ", filter?: string | undefined): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.nextUntil.$1", + "type": "Object", + "tags": [], + "label": "element", + "description": [], + "signature": [ + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + } + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.nextUntil.$2", + "type": "string", + "tags": [], + "label": "filter", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.prev", + "type": "Function", + "tags": [], + "label": "prev", + "description": [], + "signature": [ + "(selector?: string | undefined) => ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + } + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.prev.$1", + "type": "string", + "tags": [], + "label": "selector", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.prevAll", + "type": "Function", + "tags": [], + "label": "prevAll", + "description": [], + "signature": [ + "{ (): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (selector: string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.prevAll", + "type": "Function", + "tags": [], + "label": "prevAll", + "description": [], + "signature": [ + "{ (): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (selector: string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.prevAll.$1", + "type": "string", + "tags": [], + "label": "selector", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.prevUntil", + "type": "Function", + "tags": [], + "label": "prevUntil", + "description": [], + "signature": [ + "{ (selector?: string | undefined, filter?: string | undefined): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (element: cheerio.Element, filter?: string | undefined): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (element: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + ", filter?: string | undefined): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.prevUntil.$1", + "type": "string", + "tags": [], + "label": "selector", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.prevUntil.$2", + "type": "string", + "tags": [], + "label": "filter", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.prevUntil", + "type": "Function", + "tags": [], + "label": "prevUntil", + "description": [], + "signature": [ + "{ (selector?: string | undefined, filter?: string | undefined): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (element: cheerio.Element, filter?: string | undefined): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (element: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + ", filter?: string | undefined): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.prevUntil.$1", + "type": "CompoundType", + "tags": [], + "label": "element", + "description": [], + "signature": [ + "cheerio.Element" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.prevUntil.$2", + "type": "string", + "tags": [], + "label": "filter", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.prevUntil", + "type": "Function", + "tags": [], + "label": "prevUntil", + "description": [], + "signature": [ + "{ (selector?: string | undefined, filter?: string | undefined): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (element: cheerio.Element, filter?: string | undefined): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (element: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + ", filter?: string | undefined): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.prevUntil.$1", + "type": "Object", + "tags": [], + "label": "element", + "description": [], + "signature": [ + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + } + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.prevUntil.$2", + "type": "string", + "tags": [], + "label": "filter", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.slice", + "type": "Function", + "tags": [], + "label": "slice", + "description": [], + "signature": [ + "(start: number, end?: number | undefined) => ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + } + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.slice.$1", + "type": "number", + "tags": [], + "label": "start", + "description": [], + "signature": [ + "number" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.slice.$2", + "type": "number", + "tags": [], + "label": "end", + "description": [], + "signature": [ + "number | undefined" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.siblings", + "type": "Function", + "tags": [], + "label": "siblings", + "description": [], + "signature": [ + "(selector?: string | undefined) => ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + } + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.siblings.$1", + "type": "string", + "tags": [], + "label": "selector", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.children", + "type": "Function", + "tags": [], + "label": "children", + "description": [], + "signature": [ + "(selector?: string | undefined) => ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + } + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.children.$1", + "type": "string", + "tags": [], + "label": "selector", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.contents", + "type": "Function", + "tags": [], + "label": "contents", + "description": [], + "signature": [ + "() => ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + } + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.each", + "type": "Function", + "tags": [], + "label": "each", + "description": [], + "signature": [ + "(func: (index: number, element: cheerio.Element) => any) => ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + } + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.each.$1", + "type": "Function", + "tags": [], + "label": "func", + "description": [], + "signature": [ + "(index: number, element: cheerio.Element) => any" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.map", + "type": "Function", + "tags": [], + "label": "map", + "description": [], + "signature": [ + "(func: (index: number, element: cheerio.Element) => any) => ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + } + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.map.$1", + "type": "Function", + "tags": [], + "label": "func", + "description": [], + "signature": [ + "(index: number, element: cheerio.Element) => any" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.filter", + "type": "Function", + "tags": [], + "label": "filter", + "description": [], + "signature": [ + "{ (selector: string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (selection: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (element: cheerio.Element): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (elements: cheerio.Element[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (func: (index: number, element: cheerio.Element) => boolean): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.filter.$1", + "type": "string", + "tags": [], + "label": "selector", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.filter", + "type": "Function", + "tags": [], + "label": "filter", + "description": [], + "signature": [ + "{ (selector: string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (selection: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (element: cheerio.Element): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (elements: cheerio.Element[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (func: (index: number, element: cheerio.Element) => boolean): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.filter.$1", + "type": "Object", + "tags": [], + "label": "selection", + "description": [], + "signature": [ + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + } + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.filter", + "type": "Function", + "tags": [], + "label": "filter", + "description": [], + "signature": [ + "{ (selector: string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (selection: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (element: cheerio.Element): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (elements: cheerio.Element[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (func: (index: number, element: cheerio.Element) => boolean): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.filter.$1", + "type": "CompoundType", + "tags": [], + "label": "element", + "description": [], + "signature": [ + "cheerio.Element" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.filter", + "type": "Function", + "tags": [], + "label": "filter", + "description": [], + "signature": [ + "{ (selector: string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (selection: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (element: cheerio.Element): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (elements: cheerio.Element[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (func: (index: number, element: cheerio.Element) => boolean): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.filter.$1", + "type": "Array", + "tags": [], + "label": "elements", + "description": [], + "signature": [ + "cheerio.Element[]" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.filter", + "type": "Function", + "tags": [], + "label": "filter", + "description": [], + "signature": [ + "{ (selector: string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (selection: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (element: cheerio.Element): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (elements: cheerio.Element[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (func: (index: number, element: cheerio.Element) => boolean): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.filter.$1", + "type": "Function", + "tags": [], + "label": "func", + "description": [], + "signature": [ + "(index: number, element: cheerio.Element) => boolean" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.not", + "type": "Function", + "tags": [], + "label": "not", + "description": [], + "signature": [ + "{ (selector: string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (selection: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (element: cheerio.Element): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (func: (index: number, element: cheerio.Element) => boolean): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.not.$1", + "type": "string", + "tags": [], + "label": "selector", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.not", + "type": "Function", + "tags": [], + "label": "not", + "description": [], + "signature": [ + "{ (selector: string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (selection: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (element: cheerio.Element): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (func: (index: number, element: cheerio.Element) => boolean): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.not.$1", + "type": "Object", + "tags": [], + "label": "selection", + "description": [], + "signature": [ + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + } + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.not", + "type": "Function", + "tags": [], + "label": "not", + "description": [], + "signature": [ + "{ (selector: string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (selection: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (element: cheerio.Element): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (func: (index: number, element: cheerio.Element) => boolean): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.not.$1", + "type": "CompoundType", + "tags": [], + "label": "element", + "description": [], + "signature": [ + "cheerio.Element" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.not", + "type": "Function", + "tags": [], + "label": "not", + "description": [], + "signature": [ + "{ (selector: string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (selection: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (element: cheerio.Element): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (func: (index: number, element: cheerio.Element) => boolean): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.not.$1", + "type": "Function", + "tags": [], + "label": "func", + "description": [], + "signature": [ + "(index: number, element: cheerio.Element) => boolean" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.first", + "type": "Function", + "tags": [], + "label": "first", + "description": [], + "signature": [ + "() => ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + } + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.last", + "type": "Function", + "tags": [], + "label": "last", + "description": [], + "signature": [ + "() => ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + } + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.eq", + "type": "Function", + "tags": [], + "label": "eq", + "description": [], + "signature": [ + "(index: number) => ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + } + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.eq.$1", + "type": "number", + "tags": [], + "label": "index", + "description": [], + "signature": [ + "number" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.get", + "type": "Function", + "tags": [], + "label": "get", + "description": [], + "signature": [ + "{ (): any[]; (index: number): any; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.get", + "type": "Function", + "tags": [], + "label": "get", + "description": [], + "signature": [ + "{ (): any[]; (index: number): any; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.get.$1", + "type": "number", + "tags": [], + "label": "index", + "description": [], + "signature": [ + "number" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.index", + "type": "Function", + "tags": [], + "label": "index", + "description": [], + "signature": [ + "{ (): number; (selector: string): number; (selection: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "): number; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.index", + "type": "Function", + "tags": [], + "label": "index", + "description": [], + "signature": [ + "{ (): number; (selector: string): number; (selection: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "): number; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.index.$1", + "type": "string", + "tags": [], + "label": "selector", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.index", + "type": "Function", + "tags": [], + "label": "index", + "description": [], + "signature": [ + "{ (): number; (selector: string): number; (selection: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "): number; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.index.$1", + "type": "Object", + "tags": [], + "label": "selection", + "description": [], + "signature": [ + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + } + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.end", + "type": "Function", + "tags": [], + "label": "end", + "description": [], + "signature": [ + "() => ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + } + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.add", + "type": "Function", + "tags": [], + "label": "add", + "description": [], + "signature": [ + "{ (selectorOrHtml: string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (selector: string, context: Document): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (element: cheerio.Element): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (elements: cheerio.Element[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (selection: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.add.$1", + "type": "string", + "tags": [], + "label": "selectorOrHtml", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.add", + "type": "Function", + "tags": [], + "label": "add", + "description": [], + "signature": [ + "{ (selectorOrHtml: string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (selector: string, context: Document): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (element: cheerio.Element): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (elements: cheerio.Element[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (selection: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.add.$1", + "type": "string", + "tags": [], + "label": "selector", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.add.$2", + "type": "Object", + "tags": [], + "label": "context", + "description": [], + "signature": [ + "Document" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.add", + "type": "Function", + "tags": [], + "label": "add", + "description": [], + "signature": [ + "{ (selectorOrHtml: string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (selector: string, context: Document): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (element: cheerio.Element): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (elements: cheerio.Element[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (selection: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.add.$1", + "type": "CompoundType", + "tags": [], + "label": "element", + "description": [], + "signature": [ + "cheerio.Element" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.add", + "type": "Function", + "tags": [], + "label": "add", + "description": [], + "signature": [ + "{ (selectorOrHtml: string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (selector: string, context: Document): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (element: cheerio.Element): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (elements: cheerio.Element[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (selection: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.add.$1", + "type": "Array", + "tags": [], + "label": "elements", + "description": [], + "signature": [ + "cheerio.Element[]" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.add", + "type": "Function", + "tags": [], + "label": "add", + "description": [], + "signature": [ + "{ (selectorOrHtml: string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (selector: string, context: Document): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (element: cheerio.Element): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (elements: cheerio.Element[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (selection: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.add.$1", + "type": "Object", + "tags": [], + "label": "selection", + "description": [], + "signature": [ + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + } + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.addBack", + "type": "Function", + "tags": [], + "label": "addBack", + "description": [], + "signature": [ + "{ (): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (filter: string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.addBack", + "type": "Function", + "tags": [], + "label": "addBack", + "description": [], + "signature": [ + "{ (): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (filter: string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.addBack.$1", + "type": "string", + "tags": [], + "label": "filter", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.appendTo", + "type": "Function", + "tags": [], + "label": "appendTo", + "description": [], + "signature": [ + "(target: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + ") => ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + } + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.appendTo.$1", + "type": "Object", + "tags": [], + "label": "target", + "description": [], + "signature": [ + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + } + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.prependTo", + "type": "Function", + "tags": [], + "label": "prependTo", + "description": [], + "signature": [ + "(target: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + ") => ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + } + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.prependTo.$1", + "type": "Object", + "tags": [], + "label": "target", + "description": [], + "signature": [ + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + } + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.append", + "type": "Function", + "tags": [], + "label": "append", + "description": [], + "signature": [ + "{ (content: string, ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: Document, ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: Document[], ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + ", ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.append.$1", + "type": "string", + "tags": [], + "label": "content", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.append.$2", + "type": "Array", + "tags": [], + "label": "contents", + "description": [], + "signature": [ + "any[]" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.append", + "type": "Function", + "tags": [], + "label": "append", + "description": [], + "signature": [ + "{ (content: string, ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: Document, ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: Document[], ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + ", ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.append.$1", + "type": "Object", + "tags": [], + "label": "content", + "description": [], + "signature": [ + "Document" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.append.$2", + "type": "Array", + "tags": [], + "label": "contents", + "description": [], + "signature": [ + "any[]" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.append", + "type": "Function", + "tags": [], + "label": "append", + "description": [], + "signature": [ + "{ (content: string, ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: Document, ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: Document[], ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + ", ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.append.$1", + "type": "Array", + "tags": [], + "label": "content", + "description": [], + "signature": [ + "Document[]" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.append.$2", + "type": "Array", + "tags": [], + "label": "contents", + "description": [], + "signature": [ + "any[]" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.append", + "type": "Function", + "tags": [], + "label": "append", + "description": [], + "signature": [ + "{ (content: string, ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: Document, ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: Document[], ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + ", ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.append.$1", + "type": "Object", + "tags": [], + "label": "content", + "description": [], + "signature": [ + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + } + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.append.$2", + "type": "Array", + "tags": [], + "label": "contents", + "description": [], + "signature": [ + "any[]" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.prepend", + "type": "Function", + "tags": [], + "label": "prepend", + "description": [], + "signature": [ + "{ (content: string, ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: Document, ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: Document[], ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + ", ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.prepend.$1", + "type": "string", + "tags": [], + "label": "content", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.prepend.$2", + "type": "Array", + "tags": [], + "label": "contents", + "description": [], + "signature": [ + "any[]" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.prepend", + "type": "Function", + "tags": [], + "label": "prepend", + "description": [], + "signature": [ + "{ (content: string, ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: Document, ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: Document[], ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + ", ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.prepend.$1", + "type": "Object", + "tags": [], + "label": "content", + "description": [], + "signature": [ + "Document" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.prepend.$2", + "type": "Array", + "tags": [], + "label": "contents", + "description": [], + "signature": [ + "any[]" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.prepend", + "type": "Function", + "tags": [], + "label": "prepend", + "description": [], + "signature": [ + "{ (content: string, ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: Document, ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: Document[], ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + ", ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.prepend.$1", + "type": "Array", + "tags": [], + "label": "content", + "description": [], + "signature": [ + "Document[]" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.prepend.$2", + "type": "Array", + "tags": [], + "label": "contents", + "description": [], + "signature": [ + "any[]" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.prepend", + "type": "Function", + "tags": [], + "label": "prepend", + "description": [], + "signature": [ + "{ (content: string, ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: Document, ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: Document[], ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + ", ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.prepend.$1", + "type": "Object", + "tags": [], + "label": "content", + "description": [], + "signature": [ + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + } + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.prepend.$2", + "type": "Array", + "tags": [], + "label": "contents", + "description": [], + "signature": [ + "any[]" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.after", + "type": "Function", + "tags": [], + "label": "after", + "description": [], + "signature": [ + "{ (content: string, ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: Document, ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: Document[], ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + ", ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.after.$1", + "type": "string", + "tags": [], + "label": "content", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.after.$2", + "type": "Array", + "tags": [], + "label": "contents", + "description": [], + "signature": [ + "any[]" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.after", + "type": "Function", + "tags": [], + "label": "after", + "description": [], + "signature": [ + "{ (content: string, ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: Document, ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: Document[], ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + ", ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.after.$1", + "type": "Object", + "tags": [], + "label": "content", + "description": [], + "signature": [ + "Document" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.after.$2", + "type": "Array", + "tags": [], + "label": "contents", + "description": [], + "signature": [ + "any[]" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.after", + "type": "Function", + "tags": [], + "label": "after", + "description": [], + "signature": [ + "{ (content: string, ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: Document, ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: Document[], ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + ", ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.after.$1", + "type": "Array", + "tags": [], + "label": "content", + "description": [], + "signature": [ + "Document[]" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.after.$2", + "type": "Array", + "tags": [], + "label": "contents", + "description": [], + "signature": [ + "any[]" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.after", + "type": "Function", + "tags": [], + "label": "after", + "description": [], + "signature": [ + "{ (content: string, ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: Document, ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: Document[], ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + ", ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.after.$1", + "type": "Object", + "tags": [], + "label": "content", + "description": [], + "signature": [ + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + } + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.after.$2", + "type": "Array", + "tags": [], + "label": "contents", + "description": [], + "signature": [ + "any[]" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.insertAfter", + "type": "Function", + "tags": [], + "label": "insertAfter", + "description": [], + "signature": [ + "{ (content: string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: Document): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.insertAfter.$1", + "type": "string", + "tags": [], + "label": "content", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.insertAfter", + "type": "Function", + "tags": [], + "label": "insertAfter", + "description": [], + "signature": [ + "{ (content: string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: Document): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.insertAfter.$1", + "type": "Object", + "tags": [], + "label": "content", + "description": [], + "signature": [ + "Document" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.insertAfter", + "type": "Function", + "tags": [], + "label": "insertAfter", + "description": [], + "signature": [ + "{ (content: string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: Document): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.insertAfter.$1", + "type": "Object", + "tags": [], + "label": "content", + "description": [], + "signature": [ + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + } + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.before", + "type": "Function", + "tags": [], + "label": "before", + "description": [], + "signature": [ + "{ (content: string, ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: Document, ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: Document[], ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + ", ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.before.$1", + "type": "string", + "tags": [], + "label": "content", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.before.$2", + "type": "Array", + "tags": [], + "label": "contents", + "description": [], + "signature": [ + "any[]" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.before", + "type": "Function", + "tags": [], + "label": "before", + "description": [], + "signature": [ + "{ (content: string, ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: Document, ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: Document[], ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + ", ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.before.$1", + "type": "Object", + "tags": [], + "label": "content", + "description": [], + "signature": [ + "Document" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.before.$2", + "type": "Array", + "tags": [], + "label": "contents", + "description": [], + "signature": [ + "any[]" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.before", + "type": "Function", + "tags": [], + "label": "before", + "description": [], + "signature": [ + "{ (content: string, ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: Document, ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: Document[], ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + ", ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.before.$1", + "type": "Array", + "tags": [], + "label": "content", + "description": [], + "signature": [ + "Document[]" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.before.$2", + "type": "Array", + "tags": [], + "label": "contents", + "description": [], + "signature": [ + "any[]" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.before", + "type": "Function", + "tags": [], + "label": "before", + "description": [], + "signature": [ + "{ (content: string, ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: Document, ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: Document[], ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + ", ...contents: any[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.before.$1", + "type": "Object", + "tags": [], + "label": "content", + "description": [], + "signature": [ + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + } + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.before.$2", + "type": "Array", + "tags": [], + "label": "contents", + "description": [], + "signature": [ + "any[]" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.insertBefore", + "type": "Function", + "tags": [], + "label": "insertBefore", + "description": [], + "signature": [ + "{ (content: string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: Document): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.insertBefore.$1", + "type": "string", + "tags": [], + "label": "content", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.insertBefore", + "type": "Function", + "tags": [], + "label": "insertBefore", + "description": [], + "signature": [ + "{ (content: string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: Document): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.insertBefore.$1", + "type": "Object", + "tags": [], + "label": "content", + "description": [], + "signature": [ + "Document" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.insertBefore", + "type": "Function", + "tags": [], + "label": "insertBefore", + "description": [], + "signature": [ + "{ (content: string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: Document): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.insertBefore.$1", + "type": "Object", + "tags": [], + "label": "content", + "description": [], + "signature": [ + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + } + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.remove", + "type": "Function", + "tags": [], + "label": "remove", + "description": [], + "signature": [ + "(selector?: string | undefined) => ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + } + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.remove.$1", + "type": "string", + "tags": [], + "label": "selector", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.replaceWith", + "type": "Function", + "tags": [], + "label": "replaceWith", + "description": [], + "signature": [ + "{ (content: string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: cheerio.Element): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: cheerio.Element[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: () => ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.replaceWith.$1", + "type": "string", + "tags": [], + "label": "content", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.replaceWith", + "type": "Function", + "tags": [], + "label": "replaceWith", + "description": [], + "signature": [ + "{ (content: string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: cheerio.Element): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: cheerio.Element[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: () => ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.replaceWith.$1", + "type": "CompoundType", + "tags": [], + "label": "content", + "description": [], + "signature": [ + "cheerio.Element" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.replaceWith", + "type": "Function", + "tags": [], + "label": "replaceWith", + "description": [], + "signature": [ + "{ (content: string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: cheerio.Element): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: cheerio.Element[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: () => ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.replaceWith.$1", + "type": "Array", + "tags": [], + "label": "content", + "description": [], + "signature": [ + "cheerio.Element[]" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.replaceWith", + "type": "Function", + "tags": [], + "label": "replaceWith", + "description": [], + "signature": [ + "{ (content: string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: cheerio.Element): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: cheerio.Element[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: () => ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.replaceWith.$1", + "type": "Object", + "tags": [], + "label": "content", + "description": [], + "signature": [ + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + } + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.replaceWith", + "type": "Function", + "tags": [], + "label": "replaceWith", + "description": [], + "signature": [ + "{ (content: string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: cheerio.Element): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: cheerio.Element[]): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: () => ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.replaceWith.$1", + "type": "Function", + "tags": [], + "label": "content", + "description": [], + "signature": [ + "() => ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + } + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.empty", + "type": "Function", + "tags": [], + "label": "empty", + "description": [], + "signature": [ + "() => ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + } + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.html", + "type": "Function", + "tags": [], + "label": "html", + "description": [], + "signature": [ + "{ (): string | null; (html: string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.html", + "type": "Function", + "tags": [], + "label": "html", + "description": [], + "signature": [ + "{ (): string | null; (html: string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.html.$1", + "type": "string", + "tags": [], + "label": "html", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.text", + "type": "Function", + "tags": [], + "label": "text", + "description": [], + "signature": [ + "{ (): string; (text: string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.text", + "type": "Function", + "tags": [], + "label": "text", + "description": [], + "signature": [ + "{ (): string; (text: string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.text.$1", + "type": "string", + "tags": [], + "label": "text", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.wrap", + "type": "Function", + "tags": [], + "label": "wrap", + "description": [], + "signature": [ + "{ (content: string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: Document): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.wrap.$1", + "type": "string", + "tags": [], + "label": "content", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.wrap", + "type": "Function", + "tags": [], + "label": "wrap", + "description": [], + "signature": [ + "{ (content: string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: Document): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.wrap.$1", + "type": "Object", + "tags": [], + "label": "content", + "description": [], + "signature": [ + "Document" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.wrap", + "type": "Function", + "tags": [], + "label": "wrap", + "description": [], + "signature": [ + "{ (content: string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: Document): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (content: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.wrap.$1", + "type": "Object", + "tags": [], + "label": "content", + "description": [], + "signature": [ + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + } + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.css", + "type": "Function", + "tags": [], + "label": "css", + "description": [], + "signature": [ + "{ (propertyName: string): string; (propertyNames: string[]): string[]; (propertyName: string, value: string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (propertyName: string, value: number): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (propertyName: string, func: (index: number, value: string) => string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (propertyName: string, func: (index: number, value: string) => number): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (properties: Record): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.css.$1", + "type": "string", + "tags": [], + "label": "propertyName", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.css", + "type": "Function", + "tags": [], + "label": "css", + "description": [], + "signature": [ + "{ (propertyName: string): string; (propertyNames: string[]): string[]; (propertyName: string, value: string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (propertyName: string, value: number): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (propertyName: string, func: (index: number, value: string) => string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (propertyName: string, func: (index: number, value: string) => number): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (properties: Record): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.css.$1", + "type": "Array", + "tags": [], + "label": "propertyNames", + "description": [], + "signature": [ + "string[]" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.css", + "type": "Function", + "tags": [], + "label": "css", + "description": [], + "signature": [ + "{ (propertyName: string): string; (propertyNames: string[]): string[]; (propertyName: string, value: string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (propertyName: string, value: number): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (propertyName: string, func: (index: number, value: string) => string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (propertyName: string, func: (index: number, value: string) => number): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (properties: Record): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.css.$1", + "type": "string", + "tags": [], + "label": "propertyName", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.css.$2", + "type": "string", + "tags": [], + "label": "value", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.css", + "type": "Function", + "tags": [], + "label": "css", + "description": [], + "signature": [ + "{ (propertyName: string): string; (propertyNames: string[]): string[]; (propertyName: string, value: string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (propertyName: string, value: number): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (propertyName: string, func: (index: number, value: string) => string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (propertyName: string, func: (index: number, value: string) => number): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (properties: Record): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.css.$1", + "type": "string", + "tags": [], + "label": "propertyName", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.css.$2", + "type": "number", + "tags": [], + "label": "value", + "description": [], + "signature": [ + "number" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.css", + "type": "Function", + "tags": [], + "label": "css", + "description": [], + "signature": [ + "{ (propertyName: string): string; (propertyNames: string[]): string[]; (propertyName: string, value: string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (propertyName: string, value: number): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (propertyName: string, func: (index: number, value: string) => string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (propertyName: string, func: (index: number, value: string) => number): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (properties: Record): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.css.$1", + "type": "string", + "tags": [], + "label": "propertyName", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.css.$2", + "type": "Function", + "tags": [], + "label": "func", + "description": [], + "signature": [ + "(index: number, value: string) => string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.css", + "type": "Function", + "tags": [], + "label": "css", + "description": [], + "signature": [ + "{ (propertyName: string): string; (propertyNames: string[]): string[]; (propertyName: string, value: string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (propertyName: string, value: number): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (propertyName: string, func: (index: number, value: string) => string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (propertyName: string, func: (index: number, value: string) => number): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (properties: Record): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.css.$1", + "type": "string", + "tags": [], + "label": "propertyName", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.css.$2", + "type": "Function", + "tags": [], + "label": "func", + "description": [], + "signature": [ + "(index: number, value: string) => number" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.css", + "type": "Function", + "tags": [], + "label": "css", + "description": [], + "signature": [ + "{ (propertyName: string): string; (propertyNames: string[]): string[]; (propertyName: string, value: string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (propertyName: string, value: number): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (propertyName: string, func: (index: number, value: string) => string): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (propertyName: string, func: (index: number, value: string) => number): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; (properties: Record): ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.css.$1", + "type": "Object", + "tags": [], + "label": "properties", + "description": [], + "signature": [ + "Record" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.clone", + "type": "Function", + "tags": [], + "label": "clone", + "description": [], + "signature": [ + "() => ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + } + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.toArray", + "type": "Function", + "tags": [], + "label": "toArray", + "description": [], + "signature": [ + "() => ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + "[]" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.findTestSubjects", + "type": "Function", + "tags": [], + "label": "findTestSubjects", + "description": [], + "signature": [ + "(selector: string) => ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + } + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.findTestSubjects.$1", + "type": "string", + "tags": [], + "label": "selector", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.findTestSubject", + "type": "Function", + "tags": [], + "label": "findTestSubject", + "description": [], + "signature": [ + "(selector: string) => ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + } + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerio.findTestSubject.$1", + "type": "string", + "tags": [], + "label": "selector", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerioStatic", + "type": "Interface", + "tags": [], + "label": "CustomCheerioStatic", + "description": [], + "signature": [ + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerioStatic", + "text": "CustomCheerioStatic" + }, + " extends CheerioSelector" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerioStatic.xml", + "type": "Function", + "tags": [], + "label": "xml", + "description": [], + "signature": [ + "() => string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerioStatic.root", + "type": "Function", + "tags": [], + "label": "root", + "description": [], + "signature": [ + "() => ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + } + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerioStatic.contains", + "type": "Function", + "tags": [], + "label": "contains", + "description": [], + "signature": [ + "(container: cheerio.Element, contained: cheerio.Element) => boolean" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerioStatic.contains.$1", + "type": "CompoundType", + "tags": [], + "label": "container", + "description": [], + "signature": [ + "cheerio.Element" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerioStatic.contains.$2", + "type": "CompoundType", + "tags": [], + "label": "contained", + "description": [], + "signature": [ + "cheerio.Element" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerioStatic.parseHTML", + "type": "Function", + "tags": [], + "label": "parseHTML", + "description": [], + "signature": [ + "(data: string, context?: Document | undefined, keepScripts?: boolean | undefined) => Document[]" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerioStatic.parseHTML.$1", + "type": "string", + "tags": [], + "label": "data", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerioStatic.parseHTML.$2", + "type": "Object", + "tags": [], + "label": "context", + "description": [], + "signature": [ + "Document | undefined" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerioStatic.parseHTML.$3", + "type": "CompoundType", + "tags": [], + "label": "keepScripts", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerioStatic.html", + "type": "Function", + "tags": [], + "label": "html", + "description": [], + "signature": [ + "{ (options?: cheerio.CheerioParserOptions | undefined): string; (selector: string, options?: cheerio.CheerioParserOptions | undefined): string; (element: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + ", options?: cheerio.CheerioParserOptions | undefined): string; (element: cheerio.Element, options?: cheerio.CheerioParserOptions | undefined): string; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerioStatic.html.$1", + "type": "Object", + "tags": [], + "label": "options", + "description": [], + "signature": [ + "cheerio.CheerioParserOptions | undefined" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerioStatic.html", + "type": "Function", + "tags": [], + "label": "html", + "description": [], + "signature": [ + "{ (options?: cheerio.CheerioParserOptions | undefined): string; (selector: string, options?: cheerio.CheerioParserOptions | undefined): string; (element: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + ", options?: cheerio.CheerioParserOptions | undefined): string; (element: cheerio.Element, options?: cheerio.CheerioParserOptions | undefined): string; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerioStatic.html.$1", + "type": "string", + "tags": [], + "label": "selector", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerioStatic.html.$2", + "type": "Object", + "tags": [], + "label": "options", + "description": [], + "signature": [ + "cheerio.CheerioParserOptions | undefined" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerioStatic.html", + "type": "Function", + "tags": [], + "label": "html", + "description": [], + "signature": [ + "{ (options?: cheerio.CheerioParserOptions | undefined): string; (selector: string, options?: cheerio.CheerioParserOptions | undefined): string; (element: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + ", options?: cheerio.CheerioParserOptions | undefined): string; (element: cheerio.Element, options?: cheerio.CheerioParserOptions | undefined): string; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerioStatic.html.$1", + "type": "Object", + "tags": [], + "label": "element", + "description": [], + "signature": [ + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + } + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerioStatic.html.$2", + "type": "Object", + "tags": [], + "label": "options", + "description": [], + "signature": [ + "cheerio.CheerioParserOptions | undefined" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerioStatic.html", + "type": "Function", + "tags": [], + "label": "html", + "description": [], + "signature": [ + "{ (options?: cheerio.CheerioParserOptions | undefined): string; (selector: string, options?: cheerio.CheerioParserOptions | undefined): string; (element: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + }, + ", options?: cheerio.CheerioParserOptions | undefined): string; (element: cheerio.Element, options?: cheerio.CheerioParserOptions | undefined): string; }" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerioStatic.html.$1", + "type": "CompoundType", + "tags": [], + "label": "element", + "description": [], + "signature": [ + "cheerio.Element" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerioStatic.html.$2", + "type": "Object", + "tags": [], + "label": "options", + "description": [], + "signature": [ + "cheerio.CheerioParserOptions | undefined" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerioStatic.findTestSubjects", + "type": "Function", + "tags": [], + "label": "findTestSubjects", + "description": [], + "signature": [ + "(selector: string) => ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + } + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerioStatic.findTestSubjects.$1", + "type": "string", + "tags": [], + "label": "selector", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerioStatic.findTestSubject", + "type": "Function", + "tags": [], + "label": "findTestSubject", + "description": [], + "signature": [ + "(selector: string) => ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.CustomCheerio", + "text": "CustomCheerio" + } + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.CustomCheerioStatic.findTestSubject.$1", + "type": "string", + "tags": [], + "label": "selector", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/web_element_wrapper/custom_cheerio_api.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.NetworkOptions", + "type": "Interface", + "tags": [], + "label": "NetworkOptions", + "description": [], + "path": "packages/kbn-ftr-common-functional-ui-services/services/remote/network_profiles.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.NetworkOptions.offline", + "type": "boolean", + "tags": [], + "label": "offline", + "description": [], + "path": "packages/kbn-ftr-common-functional-ui-services/services/remote/network_profiles.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.NetworkOptions.latency", + "type": "number", + "tags": [], + "label": "latency", + "description": [], + "path": "packages/kbn-ftr-common-functional-ui-services/services/remote/network_profiles.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.NetworkOptions.download_throughput", + "type": "number", + "tags": [], + "label": "download_throughput", + "description": [], + "path": "packages/kbn-ftr-common-functional-ui-services/services/remote/network_profiles.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.NetworkOptions.upload_throughput", + "type": "number", + "tags": [], + "label": "upload_throughput", + "description": [], + "path": "packages/kbn-ftr-common-functional-ui-services/services/remote/network_profiles.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.TimeoutOpt", + "type": "Interface", + "tags": [], + "label": "TimeoutOpt", + "description": [], + "path": "packages/kbn-ftr-common-functional-ui-services/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.TimeoutOpt.timeout", + "type": "number", + "tags": [], + "label": "timeout", + "description": [], + "signature": [ + "number | undefined" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + } + ], + "enums": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.Browsers", + "type": "Enum", + "tags": [], + "label": "Browsers", + "description": [], + "path": "packages/kbn-ftr-common-functional-ui-services/services/remote/browsers.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + } + ], "misc": [ { "parentPluginId": "@kbn/ftr-common-functional-ui-services", @@ -31,13 +10002,75 @@ "description": [], "signature": [ { - "pluginId": "@kbn/test", + "pluginId": "@kbn/test", + "scope": "common", + "docId": "kibKbnTestPluginApi", + "section": "def-common.GenericFtrProviderContext", + "text": "GenericFtrProviderContext" + }, + "<{ retry: typeof ", + { + "pluginId": "@kbn/ftr-common-functional-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalServicesPluginApi", + "section": "def-common.RetryService", + "text": "RetryService" + }, + "; retryOnStale: ({ getService }: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", "scope": "common", - "docId": "kibKbnTestPluginApi", - "section": "def-common.GenericFtrProviderContext", - "text": "GenericFtrProviderContext" + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.FtrProviderContext", + "text": "FtrProviderContext" + }, + ") => { (fn: () => Promise): Promise; wrap(fn: (...args: Args) => Promise): (...args: Args) => Promise; }; __webdriver__: ({ getService }: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.FtrProviderContext", + "text": "FtrProviderContext" + }, + ") => Promise<{ driver: ", + "WebDriver", + "; browserType: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.Browsers", + "text": "Browsers" + }, + "; consoleLog$: ", + "Observable", + "<{ message: string; level: string; }>; }>; find: (ctx: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.FtrProviderContext", + "text": "FtrProviderContext" + }, + ") => Promise<", + "FindService", + ">; }, {}, ProvidedTypeMap<{ retry: typeof ", + { + "pluginId": "@kbn/ftr-common-functional-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalServicesPluginApi", + "section": "def-common.RetryService", + "text": "RetryService" + }, + "; retryOnStale: ({ getService }: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.FtrProviderContext", + "text": "FtrProviderContext" }, - "<{ retryOnStale: ({ getService }: ", + ") => { (fn: () => Promise): Promise; wrap(fn: (...args: Args) => Promise): (...args: Args) => Promise; }; __webdriver__: ({ getService }: ", { "pluginId": "@kbn/ftr-common-functional-ui-services", "scope": "common", @@ -45,7 +10078,19 @@ "section": "def-common.FtrProviderContext", "text": "FtrProviderContext" }, - ") => { (fn: () => Promise): Promise; wrap(fn: (...args: Args) => Promise): (...args: Args) => Promise; }; }, {}, ProvidedTypeMap<{ retryOnStale: ({ getService }: ", + ") => Promise<{ driver: ", + "WebDriver", + "; browserType: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.Browsers", + "text": "Browsers" + }, + "; consoleLog$: ", + "Observable", + "<{ message: string; level: string; }>; }>; find: (ctx: ", { "pluginId": "@kbn/ftr-common-functional-ui-services", "scope": "common", @@ -53,15 +10098,346 @@ "section": "def-common.FtrProviderContext", "text": "FtrProviderContext" }, - ") => { (fn: () => Promise): Promise; wrap(fn: (...args: Args) => Promise): (...args: Args) => Promise; }; }>, ProvidedTypeMap<{}>>" + ") => Promise<", + "FindService", + ">; }>, ProvidedTypeMap<{}>>" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/ftr_provider_context.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.NetworkProfile", + "type": "Type", + "tags": [], + "label": "NetworkProfile", + "description": [], + "signature": [ + "\"NO_THROTTLING\" | \"FAST_3G\" | \"SLOW_3G\" | \"OFFLINE\" | \"CLOUD_USER\"" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/remote/network_profiles.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + } + ], + "objects": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.NETWORK_PROFILES", + "type": "Object", + "tags": [], + "label": "NETWORK_PROFILES", + "description": [], + "path": "packages/kbn-ftr-common-functional-ui-services/services/remote/network_profiles.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.NETWORK_PROFILES.NO_THROTTLING", + "type": "Object", + "tags": [], + "label": "NO_THROTTLING", + "description": [], + "path": "packages/kbn-ftr-common-functional-ui-services/services/remote/network_profiles.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.NETWORK_PROFILES.NO_THROTTLING.offline", + "type": "boolean", + "tags": [], + "label": "offline", + "description": [], + "signature": [ + "false" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/remote/network_profiles.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.NETWORK_PROFILES.NO_THROTTLING.latency", + "type": "number", + "tags": [], + "label": "latency", + "description": [], + "path": "packages/kbn-ftr-common-functional-ui-services/services/remote/network_profiles.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.NETWORK_PROFILES.NO_THROTTLING.download_throughput", + "type": "number", + "tags": [], + "label": "download_throughput", + "description": [], + "path": "packages/kbn-ftr-common-functional-ui-services/services/remote/network_profiles.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.NETWORK_PROFILES.NO_THROTTLING.upload_throughput", + "type": "number", + "tags": [], + "label": "upload_throughput", + "description": [], + "path": "packages/kbn-ftr-common-functional-ui-services/services/remote/network_profiles.ts", + "deprecated": false, + "trackAdoption": false + } + ] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.NETWORK_PROFILES.FAST_3G", + "type": "Object", + "tags": [], + "label": "FAST_3G", + "description": [], + "path": "packages/kbn-ftr-common-functional-ui-services/services/remote/network_profiles.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.NETWORK_PROFILES.FAST_3G.offline", + "type": "boolean", + "tags": [], + "label": "offline", + "description": [], + "signature": [ + "false" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/remote/network_profiles.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.NETWORK_PROFILES.FAST_3G.latency", + "type": "number", + "tags": [], + "label": "latency", + "description": [], + "path": "packages/kbn-ftr-common-functional-ui-services/services/remote/network_profiles.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.NETWORK_PROFILES.FAST_3G.download_throughput", + "type": "number", + "tags": [], + "label": "download_throughput", + "description": [], + "path": "packages/kbn-ftr-common-functional-ui-services/services/remote/network_profiles.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.NETWORK_PROFILES.FAST_3G.upload_throughput", + "type": "number", + "tags": [], + "label": "upload_throughput", + "description": [], + "path": "packages/kbn-ftr-common-functional-ui-services/services/remote/network_profiles.ts", + "deprecated": false, + "trackAdoption": false + } + ] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.NETWORK_PROFILES.SLOW_3G", + "type": "Object", + "tags": [], + "label": "SLOW_3G", + "description": [], + "path": "packages/kbn-ftr-common-functional-ui-services/services/remote/network_profiles.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.NETWORK_PROFILES.SLOW_3G.offline", + "type": "boolean", + "tags": [], + "label": "offline", + "description": [], + "signature": [ + "false" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/remote/network_profiles.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.NETWORK_PROFILES.SLOW_3G.latency", + "type": "number", + "tags": [], + "label": "latency", + "description": [], + "path": "packages/kbn-ftr-common-functional-ui-services/services/remote/network_profiles.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.NETWORK_PROFILES.SLOW_3G.download_throughput", + "type": "number", + "tags": [], + "label": "download_throughput", + "description": [], + "path": "packages/kbn-ftr-common-functional-ui-services/services/remote/network_profiles.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.NETWORK_PROFILES.SLOW_3G.upload_throughput", + "type": "number", + "tags": [], + "label": "upload_throughput", + "description": [], + "path": "packages/kbn-ftr-common-functional-ui-services/services/remote/network_profiles.ts", + "deprecated": false, + "trackAdoption": false + } + ] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.NETWORK_PROFILES.OFFLINE", + "type": "Object", + "tags": [], + "label": "OFFLINE", + "description": [], + "path": "packages/kbn-ftr-common-functional-ui-services/services/remote/network_profiles.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.NETWORK_PROFILES.OFFLINE.offline", + "type": "boolean", + "tags": [], + "label": "offline", + "description": [], + "signature": [ + "true" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/remote/network_profiles.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.NETWORK_PROFILES.OFFLINE.latency", + "type": "number", + "tags": [], + "label": "latency", + "description": [], + "path": "packages/kbn-ftr-common-functional-ui-services/services/remote/network_profiles.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.NETWORK_PROFILES.OFFLINE.download_throughput", + "type": "number", + "tags": [], + "label": "download_throughput", + "description": [], + "path": "packages/kbn-ftr-common-functional-ui-services/services/remote/network_profiles.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.NETWORK_PROFILES.OFFLINE.upload_throughput", + "type": "number", + "tags": [], + "label": "upload_throughput", + "description": [], + "path": "packages/kbn-ftr-common-functional-ui-services/services/remote/network_profiles.ts", + "deprecated": false, + "trackAdoption": false + } + ] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.NETWORK_PROFILES.CLOUD_USER", + "type": "Object", + "tags": [], + "label": "CLOUD_USER", + "description": [], + "path": "packages/kbn-ftr-common-functional-ui-services/services/remote/network_profiles.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.NETWORK_PROFILES.CLOUD_USER.offline", + "type": "boolean", + "tags": [], + "label": "offline", + "description": [], + "signature": [ + "false" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/remote/network_profiles.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.NETWORK_PROFILES.CLOUD_USER.latency", + "type": "number", + "tags": [], + "label": "latency", + "description": [], + "path": "packages/kbn-ftr-common-functional-ui-services/services/remote/network_profiles.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.NETWORK_PROFILES.CLOUD_USER.download_throughput", + "type": "number", + "tags": [], + "label": "download_throughput", + "description": [], + "path": "packages/kbn-ftr-common-functional-ui-services/services/remote/network_profiles.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.NETWORK_PROFILES.CLOUD_USER.upload_throughput", + "type": "number", + "tags": [], + "label": "upload_throughput", + "description": [], + "path": "packages/kbn-ftr-common-functional-ui-services/services/remote/network_profiles.ts", + "deprecated": false, + "trackAdoption": false + } + ] + } ], - "path": "packages/kbn-ftr-common-functional-ui-services/services/ftr_provider_context.ts", - "deprecated": false, - "trackAdoption": false, "initialIsOpen": false - } - ], - "objects": [ + }, { "parentPluginId": "@kbn/ftr-common-functional-ui-services", "id": "def-common.services", @@ -111,7 +10487,69 @@ "section": "def-common.GenericFtrProviderContext", "text": "GenericFtrProviderContext" }, - "<{ retryOnStale: ({ getService }: ", + "<{ retry: typeof ", + { + "pluginId": "@kbn/ftr-common-functional-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalServicesPluginApi", + "section": "def-common.RetryService", + "text": "RetryService" + }, + "; retryOnStale: ({ getService }: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.FtrProviderContext", + "text": "FtrProviderContext" + }, + ") => { (fn: () => Promise): Promise; wrap(fn: (...args: Args) => Promise): (...args: Args) => Promise; }; __webdriver__: ({ getService }: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.FtrProviderContext", + "text": "FtrProviderContext" + }, + ") => Promise<{ driver: ", + "WebDriver", + "; browserType: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.Browsers", + "text": "Browsers" + }, + "; consoleLog$: ", + "Observable", + "<{ message: string; level: string; }>; }>; find: (ctx: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.FtrProviderContext", + "text": "FtrProviderContext" + }, + ") => Promise<", + "FindService", + ">; }, {}, ProvidedTypeMap<{ retry: typeof ", + { + "pluginId": "@kbn/ftr-common-functional-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalServicesPluginApi", + "section": "def-common.RetryService", + "text": "RetryService" + }, + "; retryOnStale: ({ getService }: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.FtrProviderContext", + "text": "FtrProviderContext" + }, + ") => { (fn: () => Promise): Promise; wrap(fn: (...args: Args) => Promise): (...args: Args) => Promise; }; __webdriver__: ({ getService }: ", { "pluginId": "@kbn/ftr-common-functional-ui-services", "scope": "common", @@ -119,7 +10557,19 @@ "section": "def-common.FtrProviderContext", "text": "FtrProviderContext" }, - ") => { (fn: () => Promise): Promise; wrap(fn: (...args: Args) => Promise): (...args: Args) => Promise; }; }, {}, ProvidedTypeMap<{ retryOnStale: ({ getService }: ", + ") => Promise<{ driver: ", + "WebDriver", + "; browserType: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.Browsers", + "text": "Browsers" + }, + "; consoleLog$: ", + "Observable", + "<{ message: string; level: string; }>; }>; find: (ctx: ", { "pluginId": "@kbn/ftr-common-functional-ui-services", "scope": "common", @@ -127,13 +10577,305 @@ "section": "def-common.FtrProviderContext", "text": "FtrProviderContext" }, - ") => { (fn: () => Promise): Promise; wrap(fn: (...args: Args) => Promise): (...args: Args) => Promise; }; }>, ProvidedTypeMap<{}>>" + ") => Promise<", + "FindService", + ">; }>, ProvidedTypeMap<{}>>" ], "path": "packages/kbn-ftr-common-functional-ui-services/services/retry_on_stale.ts", "deprecated": false, "trackAdoption": false } ] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.services.__webdriver__", + "type": "Function", + "tags": [], + "label": "__webdriver__", + "description": [], + "signature": [ + "({ getService }: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.FtrProviderContext", + "text": "FtrProviderContext" + }, + ") => Promise<{ driver: ", + "WebDriver", + "; browserType: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.Browsers", + "text": "Browsers" + }, + "; consoleLog$: ", + "Observable", + "<{ message: string; level: string; }>; }>" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/all.ts", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.services.__webdriver__.$1", + "type": "Object", + "tags": [], + "label": "__0", + "description": [], + "signature": [ + { + "pluginId": "@kbn/test", + "scope": "common", + "docId": "kibKbnTestPluginApi", + "section": "def-common.GenericFtrProviderContext", + "text": "GenericFtrProviderContext" + }, + "<{ retry: typeof ", + { + "pluginId": "@kbn/ftr-common-functional-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalServicesPluginApi", + "section": "def-common.RetryService", + "text": "RetryService" + }, + "; retryOnStale: ({ getService }: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.FtrProviderContext", + "text": "FtrProviderContext" + }, + ") => { (fn: () => Promise): Promise; wrap(fn: (...args: Args) => Promise): (...args: Args) => Promise; }; __webdriver__: ({ getService }: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.FtrProviderContext", + "text": "FtrProviderContext" + }, + ") => Promise<{ driver: ", + "WebDriver", + "; browserType: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.Browsers", + "text": "Browsers" + }, + "; consoleLog$: ", + "Observable", + "<{ message: string; level: string; }>; }>; find: (ctx: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.FtrProviderContext", + "text": "FtrProviderContext" + }, + ") => Promise<", + "FindService", + ">; }, {}, ProvidedTypeMap<{ retry: typeof ", + { + "pluginId": "@kbn/ftr-common-functional-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalServicesPluginApi", + "section": "def-common.RetryService", + "text": "RetryService" + }, + "; retryOnStale: ({ getService }: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.FtrProviderContext", + "text": "FtrProviderContext" + }, + ") => { (fn: () => Promise): Promise; wrap(fn: (...args: Args) => Promise): (...args: Args) => Promise; }; __webdriver__: ({ getService }: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.FtrProviderContext", + "text": "FtrProviderContext" + }, + ") => Promise<{ driver: ", + "WebDriver", + "; browserType: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.Browsers", + "text": "Browsers" + }, + "; consoleLog$: ", + "Observable", + "<{ message: string; level: string; }>; }>; find: (ctx: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.FtrProviderContext", + "text": "FtrProviderContext" + }, + ") => Promise<", + "FindService", + ">; }>, ProvidedTypeMap<{}>>" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/remote/remote.ts", + "deprecated": false, + "trackAdoption": false + } + ] + }, + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.services.find", + "type": "Function", + "tags": [], + "label": "find", + "description": [], + "signature": [ + "(ctx: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.FtrProviderContext", + "text": "FtrProviderContext" + }, + ") => Promise<", + "FindService", + ">" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/all.ts", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "@kbn/ftr-common-functional-ui-services", + "id": "def-common.services.find.$1", + "type": "Object", + "tags": [], + "label": "ctx", + "description": [], + "signature": [ + { + "pluginId": "@kbn/test", + "scope": "common", + "docId": "kibKbnTestPluginApi", + "section": "def-common.GenericFtrProviderContext", + "text": "GenericFtrProviderContext" + }, + "<{ retry: typeof ", + { + "pluginId": "@kbn/ftr-common-functional-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalServicesPluginApi", + "section": "def-common.RetryService", + "text": "RetryService" + }, + "; retryOnStale: ({ getService }: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.FtrProviderContext", + "text": "FtrProviderContext" + }, + ") => { (fn: () => Promise): Promise; wrap(fn: (...args: Args) => Promise): (...args: Args) => Promise; }; __webdriver__: ({ getService }: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.FtrProviderContext", + "text": "FtrProviderContext" + }, + ") => Promise<{ driver: ", + "WebDriver", + "; browserType: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.Browsers", + "text": "Browsers" + }, + "; consoleLog$: ", + "Observable", + "<{ message: string; level: string; }>; }>; find: (ctx: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.FtrProviderContext", + "text": "FtrProviderContext" + }, + ") => Promise<", + "FindService", + ">; }, {}, ProvidedTypeMap<{ retry: typeof ", + { + "pluginId": "@kbn/ftr-common-functional-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalServicesPluginApi", + "section": "def-common.RetryService", + "text": "RetryService" + }, + "; retryOnStale: ({ getService }: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.FtrProviderContext", + "text": "FtrProviderContext" + }, + ") => { (fn: () => Promise): Promise; wrap(fn: (...args: Args) => Promise): (...args: Args) => Promise; }; __webdriver__: ({ getService }: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.FtrProviderContext", + "text": "FtrProviderContext" + }, + ") => Promise<{ driver: ", + "WebDriver", + "; browserType: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.Browsers", + "text": "Browsers" + }, + "; consoleLog$: ", + "Observable", + "<{ message: string; level: string; }>; }>; find: (ctx: ", + { + "pluginId": "@kbn/ftr-common-functional-ui-services", + "scope": "common", + "docId": "kibKbnFtrCommonFunctionalUiServicesPluginApi", + "section": "def-common.FtrProviderContext", + "text": "FtrProviderContext" + }, + ") => Promise<", + "FindService", + ">; }>, ProvidedTypeMap<{}>>" + ], + "path": "packages/kbn-ftr-common-functional-ui-services/services/find.ts", + "deprecated": false, + "trackAdoption": false + } + ] } ], "initialIsOpen": false diff --git a/api_docs/kbn_ftr_common_functional_ui_services.mdx b/api_docs/kbn_ftr_common_functional_ui_services.mdx index 5ae37e8d16e5..0462d908e9c3 100644 --- a/api_docs/kbn_ftr_common_functional_ui_services.mdx +++ b/api_docs/kbn_ftr_common_functional_ui_services.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ftr-common-functional-ui-services title: "@kbn/ftr-common-functional-ui-services" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ftr-common-functional-ui-services plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ftr-common-functional-ui-services'] --- import kbnFtrCommonFunctionalUiServicesObj from './kbn_ftr_common_functional_ui_services.devdocs.json'; @@ -21,13 +21,22 @@ Contact [@elastic/appex-qa](https://github.com/orgs/elastic/teams/appex-qa) for | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 4 | 0 | 4 | 0 | +| 435 | 3 | 400 | 1 | ## Common ### Objects +### Classes + + +### Interfaces + + +### Enums + + ### Consts, variables and types diff --git a/api_docs/kbn_generate.mdx b/api_docs/kbn_generate.mdx index 36eafb28920c..6de650b834e4 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/generate'] --- import kbnGenerateObj from './kbn_generate.devdocs.json'; diff --git a/api_docs/kbn_generate_console_definitions.mdx b/api_docs/kbn_generate_console_definitions.mdx index c1df6a535977..6a42e84834c0 100644 --- a/api_docs/kbn_generate_console_definitions.mdx +++ b/api_docs/kbn_generate_console_definitions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-generate-console-definitions title: "@kbn/generate-console-definitions" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/generate-console-definitions plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/generate-console-definitions'] --- import kbnGenerateConsoleDefinitionsObj from './kbn_generate_console_definitions.devdocs.json'; diff --git a/api_docs/kbn_generate_csv.mdx b/api_docs/kbn_generate_csv.mdx index 7bac3ecd7910..9bb02531f562 100644 --- a/api_docs/kbn_generate_csv.mdx +++ b/api_docs/kbn_generate_csv.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-generate-csv title: "@kbn/generate-csv" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/generate-csv plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/generate-csv'] --- import kbnGenerateCsvObj from './kbn_generate_csv.devdocs.json'; diff --git a/api_docs/kbn_guided_onboarding.mdx b/api_docs/kbn_guided_onboarding.mdx index db5cdc5bfb7d..164703f1c67f 100644 --- a/api_docs/kbn_guided_onboarding.mdx +++ b/api_docs/kbn_guided_onboarding.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-guided-onboarding title: "@kbn/guided-onboarding" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/guided-onboarding plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/guided-onboarding'] --- import kbnGuidedOnboardingObj from './kbn_guided_onboarding.devdocs.json'; diff --git a/api_docs/kbn_handlebars.mdx b/api_docs/kbn_handlebars.mdx index 6a0befe70ba7..589a9a4b0d09 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: 2024-01-04 +date: 2024-01-05 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 bb37a568b1ec..4ae37ede2820 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/hapi-mocks'] --- import kbnHapiMocksObj from './kbn_hapi_mocks.devdocs.json'; diff --git a/api_docs/kbn_health_gateway_server.mdx b/api_docs/kbn_health_gateway_server.mdx index 627e55d7366a..ed4112af4b5c 100644 --- a/api_docs/kbn_health_gateway_server.mdx +++ b/api_docs/kbn_health_gateway_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-health-gateway-server title: "@kbn/health-gateway-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/health-gateway-server plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/health-gateway-server'] --- import kbnHealthGatewayServerObj from './kbn_health_gateway_server.devdocs.json'; diff --git a/api_docs/kbn_home_sample_data_card.mdx b/api_docs/kbn_home_sample_data_card.mdx index 441e0efe22fd..cb2f6b7600b4 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: 2024-01-04 +date: 2024-01-05 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 6799d3dd72d8..4ce220fd843d 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: 2024-01-04 +date: 2024-01-05 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 8a55b8839481..2d89ab1962b2 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/i18n'] --- import kbnI18nObj from './kbn_i18n.devdocs.json'; diff --git a/api_docs/kbn_i18n_react.mdx b/api_docs/kbn_i18n_react.mdx index 11fa0001cf29..c585b16a07e4 100644 --- a/api_docs/kbn_i18n_react.mdx +++ b/api_docs/kbn_i18n_react.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-i18n-react title: "@kbn/i18n-react" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/i18n-react plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/i18n-react'] --- import kbnI18nReactObj from './kbn_i18n_react.devdocs.json'; diff --git a/api_docs/kbn_import_resolver.mdx b/api_docs/kbn_import_resolver.mdx index ec1fb89e4885..2df53cd7c60b 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/import-resolver'] --- import kbnImportResolverObj from './kbn_import_resolver.devdocs.json'; diff --git a/api_docs/kbn_infra_forge.mdx b/api_docs/kbn_infra_forge.mdx index 7f40747ccdcb..65a3c9801acf 100644 --- a/api_docs/kbn_infra_forge.mdx +++ b/api_docs/kbn_infra_forge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-infra-forge title: "@kbn/infra-forge" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/infra-forge plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/infra-forge'] --- import kbnInfraForgeObj from './kbn_infra_forge.devdocs.json'; diff --git a/api_docs/kbn_interpreter.mdx b/api_docs/kbn_interpreter.mdx index 6ac0d16ef0a8..1ca1131298dc 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: 2024-01-04 +date: 2024-01-05 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 75987734e69f..c2e410c6fcf8 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: 2024-01-04 +date: 2024-01-05 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 9e823e239757..ff2f8c4ab99a 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: 2024-01-04 +date: 2024-01-05 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 8f1a3030fbbb..b96dc45e7ae7 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/journeys'] --- import kbnJourneysObj from './kbn_journeys.devdocs.json'; diff --git a/api_docs/kbn_json_ast.mdx b/api_docs/kbn_json_ast.mdx index c49f1a87109f..7d530618c92d 100644 --- a/api_docs/kbn_json_ast.mdx +++ b/api_docs/kbn_json_ast.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-json-ast title: "@kbn/json-ast" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/json-ast plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/json-ast'] --- import kbnJsonAstObj from './kbn_json_ast.devdocs.json'; diff --git a/api_docs/kbn_kibana_manifest_schema.mdx b/api_docs/kbn_kibana_manifest_schema.mdx index 5f60c54d9642..45c9a15b7ed2 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/kibana-manifest-schema'] --- import kbnKibanaManifestSchemaObj from './kbn_kibana_manifest_schema.devdocs.json'; diff --git a/api_docs/kbn_language_documentation_popover.mdx b/api_docs/kbn_language_documentation_popover.mdx index 324f24f8675e..ef6c7127fc18 100644 --- a/api_docs/kbn_language_documentation_popover.mdx +++ b/api_docs/kbn_language_documentation_popover.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-language-documentation-popover title: "@kbn/language-documentation-popover" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/language-documentation-popover plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/language-documentation-popover'] --- import kbnLanguageDocumentationPopoverObj from './kbn_language_documentation_popover.devdocs.json'; diff --git a/api_docs/kbn_lens_embeddable_utils.mdx b/api_docs/kbn_lens_embeddable_utils.mdx index 545336948dd3..8fc7964ba9fc 100644 --- a/api_docs/kbn_lens_embeddable_utils.mdx +++ b/api_docs/kbn_lens_embeddable_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-lens-embeddable-utils title: "@kbn/lens-embeddable-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/lens-embeddable-utils plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/lens-embeddable-utils'] --- import kbnLensEmbeddableUtilsObj from './kbn_lens_embeddable_utils.devdocs.json'; diff --git a/api_docs/kbn_lens_formula_docs.mdx b/api_docs/kbn_lens_formula_docs.mdx index 49d87393a64b..ada9e5adb714 100644 --- a/api_docs/kbn_lens_formula_docs.mdx +++ b/api_docs/kbn_lens_formula_docs.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-lens-formula-docs title: "@kbn/lens-formula-docs" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/lens-formula-docs plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/lens-formula-docs'] --- import kbnLensFormulaDocsObj from './kbn_lens_formula_docs.devdocs.json'; diff --git a/api_docs/kbn_logging.mdx b/api_docs/kbn_logging.mdx index 542f339b089d..5e0b596c73ec 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: 2024-01-04 +date: 2024-01-05 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 94d7cca0be29..713ab44ef6d7 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: 2024-01-04 +date: 2024-01-05 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 bc1555c584f9..71d5d1b5bc0f 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/managed-vscode-config'] --- import kbnManagedVscodeConfigObj from './kbn_managed_vscode_config.devdocs.json'; diff --git a/api_docs/kbn_management_cards_navigation.mdx b/api_docs/kbn_management_cards_navigation.mdx index 1bdb160fbc40..cf9d1e9b01b3 100644 --- a/api_docs/kbn_management_cards_navigation.mdx +++ b/api_docs/kbn_management_cards_navigation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-cards-navigation title: "@kbn/management-cards-navigation" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-cards-navigation plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-cards-navigation'] --- import kbnManagementCardsNavigationObj from './kbn_management_cards_navigation.devdocs.json'; diff --git a/api_docs/kbn_management_settings_application.mdx b/api_docs/kbn_management_settings_application.mdx index 19b9ea606ec3..b8c533fcfb58 100644 --- a/api_docs/kbn_management_settings_application.mdx +++ b/api_docs/kbn_management_settings_application.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-application title: "@kbn/management-settings-application" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-application plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-application'] --- import kbnManagementSettingsApplicationObj from './kbn_management_settings_application.devdocs.json'; diff --git a/api_docs/kbn_management_settings_components_field_category.mdx b/api_docs/kbn_management_settings_components_field_category.mdx index affa6056621a..06ab3a7cc6a2 100644 --- a/api_docs/kbn_management_settings_components_field_category.mdx +++ b/api_docs/kbn_management_settings_components_field_category.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-components-field-category title: "@kbn/management-settings-components-field-category" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-components-field-category plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-components-field-category'] --- import kbnManagementSettingsComponentsFieldCategoryObj from './kbn_management_settings_components_field_category.devdocs.json'; diff --git a/api_docs/kbn_management_settings_components_field_input.mdx b/api_docs/kbn_management_settings_components_field_input.mdx index 8ee7f834f3c6..b4bf5e830f93 100644 --- a/api_docs/kbn_management_settings_components_field_input.mdx +++ b/api_docs/kbn_management_settings_components_field_input.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-components-field-input title: "@kbn/management-settings-components-field-input" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-components-field-input plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-components-field-input'] --- import kbnManagementSettingsComponentsFieldInputObj from './kbn_management_settings_components_field_input.devdocs.json'; diff --git a/api_docs/kbn_management_settings_components_field_row.mdx b/api_docs/kbn_management_settings_components_field_row.mdx index 68a0b2989d6d..4638629c096b 100644 --- a/api_docs/kbn_management_settings_components_field_row.mdx +++ b/api_docs/kbn_management_settings_components_field_row.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-components-field-row title: "@kbn/management-settings-components-field-row" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-components-field-row plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-components-field-row'] --- import kbnManagementSettingsComponentsFieldRowObj from './kbn_management_settings_components_field_row.devdocs.json'; diff --git a/api_docs/kbn_management_settings_components_form.mdx b/api_docs/kbn_management_settings_components_form.mdx index 01813717bb7b..ade13d0cdbab 100644 --- a/api_docs/kbn_management_settings_components_form.mdx +++ b/api_docs/kbn_management_settings_components_form.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-components-form title: "@kbn/management-settings-components-form" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-components-form plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-components-form'] --- import kbnManagementSettingsComponentsFormObj from './kbn_management_settings_components_form.devdocs.json'; diff --git a/api_docs/kbn_management_settings_field_definition.mdx b/api_docs/kbn_management_settings_field_definition.mdx index 8c23fe69ea36..e5d23eca5d4b 100644 --- a/api_docs/kbn_management_settings_field_definition.mdx +++ b/api_docs/kbn_management_settings_field_definition.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-field-definition title: "@kbn/management-settings-field-definition" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-field-definition plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-field-definition'] --- import kbnManagementSettingsFieldDefinitionObj from './kbn_management_settings_field_definition.devdocs.json'; diff --git a/api_docs/kbn_management_settings_ids.mdx b/api_docs/kbn_management_settings_ids.mdx index a2af9654d6fd..ef16bc6baa0e 100644 --- a/api_docs/kbn_management_settings_ids.mdx +++ b/api_docs/kbn_management_settings_ids.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-ids title: "@kbn/management-settings-ids" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-ids plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-ids'] --- import kbnManagementSettingsIdsObj from './kbn_management_settings_ids.devdocs.json'; diff --git a/api_docs/kbn_management_settings_section_registry.mdx b/api_docs/kbn_management_settings_section_registry.mdx index d8c9c2b467ea..8321ebeb4d89 100644 --- a/api_docs/kbn_management_settings_section_registry.mdx +++ b/api_docs/kbn_management_settings_section_registry.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-section-registry title: "@kbn/management-settings-section-registry" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-section-registry plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-section-registry'] --- import kbnManagementSettingsSectionRegistryObj from './kbn_management_settings_section_registry.devdocs.json'; diff --git a/api_docs/kbn_management_settings_types.mdx b/api_docs/kbn_management_settings_types.mdx index 843c1a1a0016..969775d6e6d6 100644 --- a/api_docs/kbn_management_settings_types.mdx +++ b/api_docs/kbn_management_settings_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-types title: "@kbn/management-settings-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-types plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-types'] --- import kbnManagementSettingsTypesObj from './kbn_management_settings_types.devdocs.json'; diff --git a/api_docs/kbn_management_settings_utilities.mdx b/api_docs/kbn_management_settings_utilities.mdx index 3c816e218588..7a5b3363f7a3 100644 --- a/api_docs/kbn_management_settings_utilities.mdx +++ b/api_docs/kbn_management_settings_utilities.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-utilities title: "@kbn/management-settings-utilities" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-utilities plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-utilities'] --- import kbnManagementSettingsUtilitiesObj from './kbn_management_settings_utilities.devdocs.json'; diff --git a/api_docs/kbn_management_storybook_config.mdx b/api_docs/kbn_management_storybook_config.mdx index eba599a7e507..66fd05170014 100644 --- a/api_docs/kbn_management_storybook_config.mdx +++ b/api_docs/kbn_management_storybook_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-storybook-config title: "@kbn/management-storybook-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-storybook-config plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-storybook-config'] --- import kbnManagementStorybookConfigObj from './kbn_management_storybook_config.devdocs.json'; diff --git a/api_docs/kbn_mapbox_gl.mdx b/api_docs/kbn_mapbox_gl.mdx index 1f5342d2c4d1..4d0bf1385439 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/mapbox-gl'] --- import kbnMapboxGlObj from './kbn_mapbox_gl.devdocs.json'; diff --git a/api_docs/kbn_maps_vector_tile_utils.mdx b/api_docs/kbn_maps_vector_tile_utils.mdx index c9bd0585c668..3d33e69cc461 100644 --- a/api_docs/kbn_maps_vector_tile_utils.mdx +++ b/api_docs/kbn_maps_vector_tile_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-maps-vector-tile-utils title: "@kbn/maps-vector-tile-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/maps-vector-tile-utils plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/maps-vector-tile-utils'] --- import kbnMapsVectorTileUtilsObj from './kbn_maps_vector_tile_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_agg_utils.mdx b/api_docs/kbn_ml_agg_utils.mdx index 5d2de4f593d7..7c0c3e82d55c 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: 2024-01-04 +date: 2024-01-05 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_anomaly_utils.mdx b/api_docs/kbn_ml_anomaly_utils.mdx index 4ae0cd37048f..81f73e0edfb7 100644 --- a/api_docs/kbn_ml_anomaly_utils.mdx +++ b/api_docs/kbn_ml_anomaly_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-anomaly-utils title: "@kbn/ml-anomaly-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-anomaly-utils plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-anomaly-utils'] --- import kbnMlAnomalyUtilsObj from './kbn_ml_anomaly_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_category_validator.mdx b/api_docs/kbn_ml_category_validator.mdx index 1749b7b94941..cc4feb403b89 100644 --- a/api_docs/kbn_ml_category_validator.mdx +++ b/api_docs/kbn_ml_category_validator.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-category-validator title: "@kbn/ml-category-validator" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-category-validator plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-category-validator'] --- import kbnMlCategoryValidatorObj from './kbn_ml_category_validator.devdocs.json'; diff --git a/api_docs/kbn_ml_chi2test.mdx b/api_docs/kbn_ml_chi2test.mdx index 87aa68a02ce1..4c0c3b7cee8a 100644 --- a/api_docs/kbn_ml_chi2test.mdx +++ b/api_docs/kbn_ml_chi2test.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-chi2test title: "@kbn/ml-chi2test" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-chi2test plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-chi2test'] --- import kbnMlChi2testObj from './kbn_ml_chi2test.devdocs.json'; diff --git a/api_docs/kbn_ml_data_frame_analytics_utils.mdx b/api_docs/kbn_ml_data_frame_analytics_utils.mdx index b51e24cfc9e0..57a98f81dfd0 100644 --- a/api_docs/kbn_ml_data_frame_analytics_utils.mdx +++ b/api_docs/kbn_ml_data_frame_analytics_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-data-frame-analytics-utils title: "@kbn/ml-data-frame-analytics-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-data-frame-analytics-utils plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-data-frame-analytics-utils'] --- import kbnMlDataFrameAnalyticsUtilsObj from './kbn_ml_data_frame_analytics_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_data_grid.mdx b/api_docs/kbn_ml_data_grid.mdx index 15704541aba3..7e838f9aa80e 100644 --- a/api_docs/kbn_ml_data_grid.mdx +++ b/api_docs/kbn_ml_data_grid.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-data-grid title: "@kbn/ml-data-grid" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-data-grid plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-data-grid'] --- import kbnMlDataGridObj from './kbn_ml_data_grid.devdocs.json'; diff --git a/api_docs/kbn_ml_date_picker.mdx b/api_docs/kbn_ml_date_picker.mdx index 7f1d1f24f296..713ab86eba72 100644 --- a/api_docs/kbn_ml_date_picker.mdx +++ b/api_docs/kbn_ml_date_picker.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-date-picker title: "@kbn/ml-date-picker" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-date-picker plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-date-picker'] --- import kbnMlDatePickerObj from './kbn_ml_date_picker.devdocs.json'; diff --git a/api_docs/kbn_ml_date_utils.mdx b/api_docs/kbn_ml_date_utils.mdx index 32d332cb3625..531d9689ede3 100644 --- a/api_docs/kbn_ml_date_utils.mdx +++ b/api_docs/kbn_ml_date_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-date-utils title: "@kbn/ml-date-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-date-utils plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-date-utils'] --- import kbnMlDateUtilsObj from './kbn_ml_date_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_error_utils.mdx b/api_docs/kbn_ml_error_utils.mdx index 0817c2940852..06d7b83320e3 100644 --- a/api_docs/kbn_ml_error_utils.mdx +++ b/api_docs/kbn_ml_error_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-error-utils title: "@kbn/ml-error-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-error-utils plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-error-utils'] --- import kbnMlErrorUtilsObj from './kbn_ml_error_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_in_memory_table.mdx b/api_docs/kbn_ml_in_memory_table.mdx index 7b99edefb5d3..b357ace2ee94 100644 --- a/api_docs/kbn_ml_in_memory_table.mdx +++ b/api_docs/kbn_ml_in_memory_table.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-in-memory-table title: "@kbn/ml-in-memory-table" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-in-memory-table plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-in-memory-table'] --- import kbnMlInMemoryTableObj from './kbn_ml_in_memory_table.devdocs.json'; diff --git a/api_docs/kbn_ml_is_defined.mdx b/api_docs/kbn_ml_is_defined.mdx index ba7f8df01c94..2e312df56194 100644 --- a/api_docs/kbn_ml_is_defined.mdx +++ b/api_docs/kbn_ml_is_defined.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-is-defined title: "@kbn/ml-is-defined" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-is-defined plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-is-defined'] --- import kbnMlIsDefinedObj from './kbn_ml_is_defined.devdocs.json'; diff --git a/api_docs/kbn_ml_is_populated_object.mdx b/api_docs/kbn_ml_is_populated_object.mdx index cc3caa796ca3..d48cdf4046fc 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: 2024-01-04 +date: 2024-01-05 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_kibana_theme.mdx b/api_docs/kbn_ml_kibana_theme.mdx index 2baaadefca37..4ec1d8121e4c 100644 --- a/api_docs/kbn_ml_kibana_theme.mdx +++ b/api_docs/kbn_ml_kibana_theme.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-kibana-theme title: "@kbn/ml-kibana-theme" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-kibana-theme plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-kibana-theme'] --- import kbnMlKibanaThemeObj from './kbn_ml_kibana_theme.devdocs.json'; diff --git a/api_docs/kbn_ml_local_storage.mdx b/api_docs/kbn_ml_local_storage.mdx index 9c43a57f9ec4..98ae63d63322 100644 --- a/api_docs/kbn_ml_local_storage.mdx +++ b/api_docs/kbn_ml_local_storage.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-local-storage title: "@kbn/ml-local-storage" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-local-storage plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-local-storage'] --- import kbnMlLocalStorageObj from './kbn_ml_local_storage.devdocs.json'; diff --git a/api_docs/kbn_ml_nested_property.mdx b/api_docs/kbn_ml_nested_property.mdx index ea76351c4944..523f7f330185 100644 --- a/api_docs/kbn_ml_nested_property.mdx +++ b/api_docs/kbn_ml_nested_property.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-nested-property title: "@kbn/ml-nested-property" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-nested-property plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-nested-property'] --- import kbnMlNestedPropertyObj from './kbn_ml_nested_property.devdocs.json'; diff --git a/api_docs/kbn_ml_number_utils.mdx b/api_docs/kbn_ml_number_utils.mdx index 8d5b4fd623e5..a0f36bfe015a 100644 --- a/api_docs/kbn_ml_number_utils.mdx +++ b/api_docs/kbn_ml_number_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-number-utils title: "@kbn/ml-number-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-number-utils plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-number-utils'] --- import kbnMlNumberUtilsObj from './kbn_ml_number_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_query_utils.mdx b/api_docs/kbn_ml_query_utils.mdx index c647a2df0a9e..c5e8f8edace0 100644 --- a/api_docs/kbn_ml_query_utils.mdx +++ b/api_docs/kbn_ml_query_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-query-utils title: "@kbn/ml-query-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-query-utils plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-query-utils'] --- import kbnMlQueryUtilsObj from './kbn_ml_query_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_random_sampler_utils.mdx b/api_docs/kbn_ml_random_sampler_utils.mdx index a841aba31164..d4d831344a17 100644 --- a/api_docs/kbn_ml_random_sampler_utils.mdx +++ b/api_docs/kbn_ml_random_sampler_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-random-sampler-utils title: "@kbn/ml-random-sampler-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-random-sampler-utils plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-random-sampler-utils'] --- import kbnMlRandomSamplerUtilsObj from './kbn_ml_random_sampler_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_route_utils.mdx b/api_docs/kbn_ml_route_utils.mdx index ccd80736003c..4551285ea2a5 100644 --- a/api_docs/kbn_ml_route_utils.mdx +++ b/api_docs/kbn_ml_route_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-route-utils title: "@kbn/ml-route-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-route-utils plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-route-utils'] --- import kbnMlRouteUtilsObj from './kbn_ml_route_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_runtime_field_utils.mdx b/api_docs/kbn_ml_runtime_field_utils.mdx index 492263a8f3d0..bee10c047988 100644 --- a/api_docs/kbn_ml_runtime_field_utils.mdx +++ b/api_docs/kbn_ml_runtime_field_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-runtime-field-utils title: "@kbn/ml-runtime-field-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-runtime-field-utils plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-runtime-field-utils'] --- import kbnMlRuntimeFieldUtilsObj from './kbn_ml_runtime_field_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_string_hash.mdx b/api_docs/kbn_ml_string_hash.mdx index f25d70b6cd1f..9c7000dd9be2 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-string-hash'] --- import kbnMlStringHashObj from './kbn_ml_string_hash.devdocs.json'; diff --git a/api_docs/kbn_ml_trained_models_utils.mdx b/api_docs/kbn_ml_trained_models_utils.mdx index a11036a8ec06..44814479857c 100644 --- a/api_docs/kbn_ml_trained_models_utils.mdx +++ b/api_docs/kbn_ml_trained_models_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-trained-models-utils title: "@kbn/ml-trained-models-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-trained-models-utils plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-trained-models-utils'] --- import kbnMlTrainedModelsUtilsObj from './kbn_ml_trained_models_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_ui_actions.mdx b/api_docs/kbn_ml_ui_actions.mdx index 77579773f2d2..667842156e96 100644 --- a/api_docs/kbn_ml_ui_actions.mdx +++ b/api_docs/kbn_ml_ui_actions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-ui-actions title: "@kbn/ml-ui-actions" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-ui-actions plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-ui-actions'] --- import kbnMlUiActionsObj from './kbn_ml_ui_actions.devdocs.json'; diff --git a/api_docs/kbn_ml_url_state.mdx b/api_docs/kbn_ml_url_state.mdx index eb3fc4d159e9..e4f78f9b55ce 100644 --- a/api_docs/kbn_ml_url_state.mdx +++ b/api_docs/kbn_ml_url_state.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-url-state title: "@kbn/ml-url-state" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-url-state plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-url-state'] --- import kbnMlUrlStateObj from './kbn_ml_url_state.devdocs.json'; diff --git a/api_docs/kbn_monaco.mdx b/api_docs/kbn_monaco.mdx index af33db98bd47..120703eb8f8e 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/monaco'] --- import kbnMonacoObj from './kbn_monaco.devdocs.json'; diff --git a/api_docs/kbn_object_versioning.mdx b/api_docs/kbn_object_versioning.mdx index 3a7f7718854d..09475095c3a0 100644 --- a/api_docs/kbn_object_versioning.mdx +++ b/api_docs/kbn_object_versioning.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-object-versioning title: "@kbn/object-versioning" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/object-versioning plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/object-versioning'] --- import kbnObjectVersioningObj from './kbn_object_versioning.devdocs.json'; diff --git a/api_docs/kbn_observability_alert_details.mdx b/api_docs/kbn_observability_alert_details.mdx index c9745d645c58..e94b1206eb35 100644 --- a/api_docs/kbn_observability_alert_details.mdx +++ b/api_docs/kbn_observability_alert_details.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-observability-alert-details title: "@kbn/observability-alert-details" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/observability-alert-details plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/observability-alert-details'] --- import kbnObservabilityAlertDetailsObj from './kbn_observability_alert_details.devdocs.json'; diff --git a/api_docs/kbn_observability_alerting_test_data.mdx b/api_docs/kbn_observability_alerting_test_data.mdx index 42a2150e0091..0008d5c38e26 100644 --- a/api_docs/kbn_observability_alerting_test_data.mdx +++ b/api_docs/kbn_observability_alerting_test_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-observability-alerting-test-data title: "@kbn/observability-alerting-test-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/observability-alerting-test-data plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/observability-alerting-test-data'] --- import kbnObservabilityAlertingTestDataObj from './kbn_observability_alerting_test_data.devdocs.json'; diff --git a/api_docs/kbn_observability_get_padded_alert_time_range_util.mdx b/api_docs/kbn_observability_get_padded_alert_time_range_util.mdx index b13a5137b825..84ec788e62c3 100644 --- a/api_docs/kbn_observability_get_padded_alert_time_range_util.mdx +++ b/api_docs/kbn_observability_get_padded_alert_time_range_util.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-observability-get-padded-alert-time-range-util title: "@kbn/observability-get-padded-alert-time-range-util" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/observability-get-padded-alert-time-range-util plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/observability-get-padded-alert-time-range-util'] --- import kbnObservabilityGetPaddedAlertTimeRangeUtilObj from './kbn_observability_get_padded_alert_time_range_util.devdocs.json'; diff --git a/api_docs/kbn_openapi_bundler.mdx b/api_docs/kbn_openapi_bundler.mdx index bd8a7f9a511a..605f12107057 100644 --- a/api_docs/kbn_openapi_bundler.mdx +++ b/api_docs/kbn_openapi_bundler.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-openapi-bundler title: "@kbn/openapi-bundler" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/openapi-bundler plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/openapi-bundler'] --- import kbnOpenapiBundlerObj from './kbn_openapi_bundler.devdocs.json'; diff --git a/api_docs/kbn_openapi_generator.mdx b/api_docs/kbn_openapi_generator.mdx index f351063dc53f..b79a5e2986ab 100644 --- a/api_docs/kbn_openapi_generator.mdx +++ b/api_docs/kbn_openapi_generator.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-openapi-generator title: "@kbn/openapi-generator" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/openapi-generator plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/openapi-generator'] --- import kbnOpenapiGeneratorObj from './kbn_openapi_generator.devdocs.json'; diff --git a/api_docs/kbn_optimizer.mdx b/api_docs/kbn_optimizer.mdx index 106de241e3f7..9c6bc1d29b40 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: 2024-01-04 +date: 2024-01-05 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 3c99f96697c1..6469a938998c 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: 2024-01-04 +date: 2024-01-05 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 9ec21c688095..c85afb88f8fd 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: 2024-01-04 +date: 2024-01-05 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_panel_loader.mdx b/api_docs/kbn_panel_loader.mdx index 95b31bd16993..5022c3172234 100644 --- a/api_docs/kbn_panel_loader.mdx +++ b/api_docs/kbn_panel_loader.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-panel-loader title: "@kbn/panel-loader" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/panel-loader plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/panel-loader'] --- import kbnPanelLoaderObj from './kbn_panel_loader.devdocs.json'; diff --git a/api_docs/kbn_performance_testing_dataset_extractor.mdx b/api_docs/kbn_performance_testing_dataset_extractor.mdx index 7bb20cc446e4..db9a30d30413 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: 2024-01-04 +date: 2024-01-05 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 9a2911c70c02..00156ca303a8 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: 2024-01-04 +date: 2024-01-05 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 0264711c8500..7f428a6f42bb 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/plugin-helpers'] --- import kbnPluginHelpersObj from './kbn_plugin_helpers.devdocs.json'; diff --git a/api_docs/kbn_profiling_utils.mdx b/api_docs/kbn_profiling_utils.mdx index 6f0b23f99b94..1728df95bbb6 100644 --- a/api_docs/kbn_profiling_utils.mdx +++ b/api_docs/kbn_profiling_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-profiling-utils title: "@kbn/profiling-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/profiling-utils plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/profiling-utils'] --- import kbnProfilingUtilsObj from './kbn_profiling_utils.devdocs.json'; diff --git a/api_docs/kbn_random_sampling.mdx b/api_docs/kbn_random_sampling.mdx index 3f36204f291b..1a285560c8fc 100644 --- a/api_docs/kbn_random_sampling.mdx +++ b/api_docs/kbn_random_sampling.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-random-sampling title: "@kbn/random-sampling" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/random-sampling plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/random-sampling'] --- import kbnRandomSamplingObj from './kbn_random_sampling.devdocs.json'; diff --git a/api_docs/kbn_react_field.mdx b/api_docs/kbn_react_field.mdx index ae92727810f6..abdfac7d3d92 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-field'] --- import kbnReactFieldObj from './kbn_react_field.devdocs.json'; diff --git a/api_docs/kbn_react_kibana_context_common.mdx b/api_docs/kbn_react_kibana_context_common.mdx index 752c4a1b3b5b..3f4c70a79e52 100644 --- a/api_docs/kbn_react_kibana_context_common.mdx +++ b/api_docs/kbn_react_kibana_context_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-kibana-context-common title: "@kbn/react-kibana-context-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-kibana-context-common plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-kibana-context-common'] --- import kbnReactKibanaContextCommonObj from './kbn_react_kibana_context_common.devdocs.json'; diff --git a/api_docs/kbn_react_kibana_context_render.mdx b/api_docs/kbn_react_kibana_context_render.mdx index 3ab51934192b..ccd5848f67a0 100644 --- a/api_docs/kbn_react_kibana_context_render.mdx +++ b/api_docs/kbn_react_kibana_context_render.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-kibana-context-render title: "@kbn/react-kibana-context-render" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-kibana-context-render plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-kibana-context-render'] --- import kbnReactKibanaContextRenderObj from './kbn_react_kibana_context_render.devdocs.json'; diff --git a/api_docs/kbn_react_kibana_context_root.mdx b/api_docs/kbn_react_kibana_context_root.mdx index b428dd102f64..9207d0cc6b10 100644 --- a/api_docs/kbn_react_kibana_context_root.mdx +++ b/api_docs/kbn_react_kibana_context_root.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-kibana-context-root title: "@kbn/react-kibana-context-root" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-kibana-context-root plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-kibana-context-root'] --- import kbnReactKibanaContextRootObj from './kbn_react_kibana_context_root.devdocs.json'; diff --git a/api_docs/kbn_react_kibana_context_styled.mdx b/api_docs/kbn_react_kibana_context_styled.mdx index ec8467440e1c..adab4ef567b7 100644 --- a/api_docs/kbn_react_kibana_context_styled.mdx +++ b/api_docs/kbn_react_kibana_context_styled.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-kibana-context-styled title: "@kbn/react-kibana-context-styled" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-kibana-context-styled plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-kibana-context-styled'] --- import kbnReactKibanaContextStyledObj from './kbn_react_kibana_context_styled.devdocs.json'; diff --git a/api_docs/kbn_react_kibana_context_theme.mdx b/api_docs/kbn_react_kibana_context_theme.mdx index 425336cc1112..1c46a73334ac 100644 --- a/api_docs/kbn_react_kibana_context_theme.mdx +++ b/api_docs/kbn_react_kibana_context_theme.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-kibana-context-theme title: "@kbn/react-kibana-context-theme" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-kibana-context-theme plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-kibana-context-theme'] --- import kbnReactKibanaContextThemeObj from './kbn_react_kibana_context_theme.devdocs.json'; diff --git a/api_docs/kbn_react_kibana_mount.mdx b/api_docs/kbn_react_kibana_mount.mdx index ae9ad6538f42..a8cdf13cc1b7 100644 --- a/api_docs/kbn_react_kibana_mount.mdx +++ b/api_docs/kbn_react_kibana_mount.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-kibana-mount title: "@kbn/react-kibana-mount" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-kibana-mount plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-kibana-mount'] --- import kbnReactKibanaMountObj from './kbn_react_kibana_mount.devdocs.json'; diff --git a/api_docs/kbn_repo_file_maps.mdx b/api_docs/kbn_repo_file_maps.mdx index 934e8dc6db22..62b20e0a98ab 100644 --- a/api_docs/kbn_repo_file_maps.mdx +++ b/api_docs/kbn_repo_file_maps.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-repo-file-maps title: "@kbn/repo-file-maps" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/repo-file-maps plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/repo-file-maps'] --- import kbnRepoFileMapsObj from './kbn_repo_file_maps.devdocs.json'; diff --git a/api_docs/kbn_repo_linter.mdx b/api_docs/kbn_repo_linter.mdx index 8452c33949f3..e15893489ec4 100644 --- a/api_docs/kbn_repo_linter.mdx +++ b/api_docs/kbn_repo_linter.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-repo-linter title: "@kbn/repo-linter" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/repo-linter plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/repo-linter'] --- import kbnRepoLinterObj from './kbn_repo_linter.devdocs.json'; diff --git a/api_docs/kbn_repo_path.mdx b/api_docs/kbn_repo_path.mdx index d1b4e65b919c..aca4a25831e8 100644 --- a/api_docs/kbn_repo_path.mdx +++ b/api_docs/kbn_repo_path.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-repo-path title: "@kbn/repo-path" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/repo-path plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/repo-path'] --- import kbnRepoPathObj from './kbn_repo_path.devdocs.json'; diff --git a/api_docs/kbn_repo_source_classifier.mdx b/api_docs/kbn_repo_source_classifier.mdx index 544e2b066426..8a30094caf7b 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/repo-source-classifier'] --- import kbnRepoSourceClassifierObj from './kbn_repo_source_classifier.devdocs.json'; diff --git a/api_docs/kbn_reporting_common.mdx b/api_docs/kbn_reporting_common.mdx index 5e307d64f309..f2cfe051b8fa 100644 --- a/api_docs/kbn_reporting_common.mdx +++ b/api_docs/kbn_reporting_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-common title: "@kbn/reporting-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-common plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-common'] --- import kbnReportingCommonObj from './kbn_reporting_common.devdocs.json'; diff --git a/api_docs/kbn_reporting_export_types_csv.mdx b/api_docs/kbn_reporting_export_types_csv.mdx index cffea7d370a0..b1ff7cddfad7 100644 --- a/api_docs/kbn_reporting_export_types_csv.mdx +++ b/api_docs/kbn_reporting_export_types_csv.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-export-types-csv title: "@kbn/reporting-export-types-csv" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-export-types-csv plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-export-types-csv'] --- import kbnReportingExportTypesCsvObj from './kbn_reporting_export_types_csv.devdocs.json'; diff --git a/api_docs/kbn_reporting_export_types_csv_common.mdx b/api_docs/kbn_reporting_export_types_csv_common.mdx index 3c031d6311cb..f4109d758df9 100644 --- a/api_docs/kbn_reporting_export_types_csv_common.mdx +++ b/api_docs/kbn_reporting_export_types_csv_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-export-types-csv-common title: "@kbn/reporting-export-types-csv-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-export-types-csv-common plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-export-types-csv-common'] --- import kbnReportingExportTypesCsvCommonObj from './kbn_reporting_export_types_csv_common.devdocs.json'; diff --git a/api_docs/kbn_reporting_export_types_pdf.mdx b/api_docs/kbn_reporting_export_types_pdf.mdx index a55f05c20655..f02299934a5d 100644 --- a/api_docs/kbn_reporting_export_types_pdf.mdx +++ b/api_docs/kbn_reporting_export_types_pdf.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-export-types-pdf title: "@kbn/reporting-export-types-pdf" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-export-types-pdf plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-export-types-pdf'] --- import kbnReportingExportTypesPdfObj from './kbn_reporting_export_types_pdf.devdocs.json'; diff --git a/api_docs/kbn_reporting_export_types_pdf_common.mdx b/api_docs/kbn_reporting_export_types_pdf_common.mdx index 16068bfc850d..8af8ba3cbc75 100644 --- a/api_docs/kbn_reporting_export_types_pdf_common.mdx +++ b/api_docs/kbn_reporting_export_types_pdf_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-export-types-pdf-common title: "@kbn/reporting-export-types-pdf-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-export-types-pdf-common plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-export-types-pdf-common'] --- import kbnReportingExportTypesPdfCommonObj from './kbn_reporting_export_types_pdf_common.devdocs.json'; diff --git a/api_docs/kbn_reporting_export_types_png.mdx b/api_docs/kbn_reporting_export_types_png.mdx index 888ab158d8b7..54ee56dcb94e 100644 --- a/api_docs/kbn_reporting_export_types_png.mdx +++ b/api_docs/kbn_reporting_export_types_png.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-export-types-png title: "@kbn/reporting-export-types-png" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-export-types-png plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-export-types-png'] --- import kbnReportingExportTypesPngObj from './kbn_reporting_export_types_png.devdocs.json'; diff --git a/api_docs/kbn_reporting_export_types_png_common.mdx b/api_docs/kbn_reporting_export_types_png_common.mdx index edeaa5bcba34..7cea2352eefd 100644 --- a/api_docs/kbn_reporting_export_types_png_common.mdx +++ b/api_docs/kbn_reporting_export_types_png_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-export-types-png-common title: "@kbn/reporting-export-types-png-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-export-types-png-common plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-export-types-png-common'] --- import kbnReportingExportTypesPngCommonObj from './kbn_reporting_export_types_png_common.devdocs.json'; diff --git a/api_docs/kbn_reporting_mocks_server.mdx b/api_docs/kbn_reporting_mocks_server.mdx index fd930185f294..85491a2b203d 100644 --- a/api_docs/kbn_reporting_mocks_server.mdx +++ b/api_docs/kbn_reporting_mocks_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-mocks-server title: "@kbn/reporting-mocks-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-mocks-server plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-mocks-server'] --- import kbnReportingMocksServerObj from './kbn_reporting_mocks_server.devdocs.json'; diff --git a/api_docs/kbn_reporting_public.mdx b/api_docs/kbn_reporting_public.mdx index efc40ca26ab5..1629166e8c75 100644 --- a/api_docs/kbn_reporting_public.mdx +++ b/api_docs/kbn_reporting_public.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-public title: "@kbn/reporting-public" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-public plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-public'] --- import kbnReportingPublicObj from './kbn_reporting_public.devdocs.json'; diff --git a/api_docs/kbn_reporting_server.mdx b/api_docs/kbn_reporting_server.mdx index 4c448634c100..358f2b46ceee 100644 --- a/api_docs/kbn_reporting_server.mdx +++ b/api_docs/kbn_reporting_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-server title: "@kbn/reporting-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-server plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-server'] --- import kbnReportingServerObj from './kbn_reporting_server.devdocs.json'; diff --git a/api_docs/kbn_resizable_layout.mdx b/api_docs/kbn_resizable_layout.mdx index b30087977bd6..c0b9efd073b9 100644 --- a/api_docs/kbn_resizable_layout.mdx +++ b/api_docs/kbn_resizable_layout.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-resizable-layout title: "@kbn/resizable-layout" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/resizable-layout plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/resizable-layout'] --- import kbnResizableLayoutObj from './kbn_resizable_layout.devdocs.json'; diff --git a/api_docs/kbn_rison.mdx b/api_docs/kbn_rison.mdx index e3d821bf6950..f2262eb5c3f0 100644 --- a/api_docs/kbn_rison.mdx +++ b/api_docs/kbn_rison.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-rison title: "@kbn/rison" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/rison plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rison'] --- import kbnRisonObj from './kbn_rison.devdocs.json'; diff --git a/api_docs/kbn_router_utils.mdx b/api_docs/kbn_router_utils.mdx index 41dd91c10405..05ce5fffc3fb 100644 --- a/api_docs/kbn_router_utils.mdx +++ b/api_docs/kbn_router_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-router-utils title: "@kbn/router-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/router-utils plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/router-utils'] --- import kbnRouterUtilsObj from './kbn_router_utils.devdocs.json'; diff --git a/api_docs/kbn_rrule.mdx b/api_docs/kbn_rrule.mdx index d7667564e267..4e31b1f5d623 100644 --- a/api_docs/kbn_rrule.mdx +++ b/api_docs/kbn_rrule.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-rrule title: "@kbn/rrule" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/rrule plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rrule'] --- import kbnRruleObj from './kbn_rrule.devdocs.json'; diff --git a/api_docs/kbn_rule_data_utils.mdx b/api_docs/kbn_rule_data_utils.mdx index ba718f93a7ea..0b65f616203c 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rule-data-utils'] --- import kbnRuleDataUtilsObj from './kbn_rule_data_utils.devdocs.json'; diff --git a/api_docs/kbn_saved_objects_settings.mdx b/api_docs/kbn_saved_objects_settings.mdx index 6dde8ce80a6b..c99b93756f8c 100644 --- a/api_docs/kbn_saved_objects_settings.mdx +++ b/api_docs/kbn_saved_objects_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-saved-objects-settings title: "@kbn/saved-objects-settings" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/saved-objects-settings plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/saved-objects-settings'] --- import kbnSavedObjectsSettingsObj from './kbn_saved_objects_settings.devdocs.json'; diff --git a/api_docs/kbn_search_api_panels.mdx b/api_docs/kbn_search_api_panels.mdx index a13947e6e526..051247be85c7 100644 --- a/api_docs/kbn_search_api_panels.mdx +++ b/api_docs/kbn_search_api_panels.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-search-api-panels title: "@kbn/search-api-panels" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/search-api-panels plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-api-panels'] --- import kbnSearchApiPanelsObj from './kbn_search_api_panels.devdocs.json'; diff --git a/api_docs/kbn_search_connectors.mdx b/api_docs/kbn_search_connectors.mdx index 87f07895068e..f0f0fb76dac2 100644 --- a/api_docs/kbn_search_connectors.mdx +++ b/api_docs/kbn_search_connectors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-search-connectors title: "@kbn/search-connectors" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/search-connectors plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-connectors'] --- import kbnSearchConnectorsObj from './kbn_search_connectors.devdocs.json'; diff --git a/api_docs/kbn_search_errors.mdx b/api_docs/kbn_search_errors.mdx index 6436525cb6a0..e623995ddec5 100644 --- a/api_docs/kbn_search_errors.mdx +++ b/api_docs/kbn_search_errors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-search-errors title: "@kbn/search-errors" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/search-errors plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-errors'] --- import kbnSearchErrorsObj from './kbn_search_errors.devdocs.json'; diff --git a/api_docs/kbn_search_index_documents.mdx b/api_docs/kbn_search_index_documents.mdx index be8ab42529bc..d1ca218b8c1f 100644 --- a/api_docs/kbn_search_index_documents.mdx +++ b/api_docs/kbn_search_index_documents.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-search-index-documents title: "@kbn/search-index-documents" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/search-index-documents plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-index-documents'] --- import kbnSearchIndexDocumentsObj from './kbn_search_index_documents.devdocs.json'; diff --git a/api_docs/kbn_search_response_warnings.mdx b/api_docs/kbn_search_response_warnings.mdx index 7fdb3a3cf28f..6cb31ef0814d 100644 --- a/api_docs/kbn_search_response_warnings.mdx +++ b/api_docs/kbn_search_response_warnings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-search-response-warnings title: "@kbn/search-response-warnings" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/search-response-warnings plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-response-warnings'] --- import kbnSearchResponseWarningsObj from './kbn_search_response_warnings.devdocs.json'; diff --git a/api_docs/kbn_security_plugin_types_common.mdx b/api_docs/kbn_security_plugin_types_common.mdx index dbee323f97b1..f422a3f537b5 100644 --- a/api_docs/kbn_security_plugin_types_common.mdx +++ b/api_docs/kbn_security_plugin_types_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-plugin-types-common title: "@kbn/security-plugin-types-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-plugin-types-common plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-plugin-types-common'] --- import kbnSecurityPluginTypesCommonObj from './kbn_security_plugin_types_common.devdocs.json'; diff --git a/api_docs/kbn_security_plugin_types_public.mdx b/api_docs/kbn_security_plugin_types_public.mdx index 98b7d98ee472..9554c4323a80 100644 --- a/api_docs/kbn_security_plugin_types_public.mdx +++ b/api_docs/kbn_security_plugin_types_public.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-plugin-types-public title: "@kbn/security-plugin-types-public" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-plugin-types-public plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-plugin-types-public'] --- import kbnSecurityPluginTypesPublicObj from './kbn_security_plugin_types_public.devdocs.json'; diff --git a/api_docs/kbn_security_plugin_types_server.mdx b/api_docs/kbn_security_plugin_types_server.mdx index e0f56bc22e01..e7aa4d3a2dd0 100644 --- a/api_docs/kbn_security_plugin_types_server.mdx +++ b/api_docs/kbn_security_plugin_types_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-plugin-types-server title: "@kbn/security-plugin-types-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-plugin-types-server plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-plugin-types-server'] --- import kbnSecurityPluginTypesServerObj from './kbn_security_plugin_types_server.devdocs.json'; diff --git a/api_docs/kbn_security_solution_features.mdx b/api_docs/kbn_security_solution_features.mdx index 2fbb7e118c61..9ee6d05d0319 100644 --- a/api_docs/kbn_security_solution_features.mdx +++ b/api_docs/kbn_security_solution_features.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-solution-features title: "@kbn/security-solution-features" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-solution-features plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-solution-features'] --- import kbnSecuritySolutionFeaturesObj from './kbn_security_solution_features.devdocs.json'; diff --git a/api_docs/kbn_security_solution_navigation.mdx b/api_docs/kbn_security_solution_navigation.mdx index 92e8e8344b2b..c1b27ac7e22c 100644 --- a/api_docs/kbn_security_solution_navigation.mdx +++ b/api_docs/kbn_security_solution_navigation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-solution-navigation title: "@kbn/security-solution-navigation" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-solution-navigation plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-solution-navigation'] --- import kbnSecuritySolutionNavigationObj from './kbn_security_solution_navigation.devdocs.json'; diff --git a/api_docs/kbn_security_solution_side_nav.mdx b/api_docs/kbn_security_solution_side_nav.mdx index aff5bd1085fa..e8d753976dbb 100644 --- a/api_docs/kbn_security_solution_side_nav.mdx +++ b/api_docs/kbn_security_solution_side_nav.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-solution-side-nav title: "@kbn/security-solution-side-nav" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-solution-side-nav plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-solution-side-nav'] --- import kbnSecuritySolutionSideNavObj from './kbn_security_solution_side_nav.devdocs.json'; diff --git a/api_docs/kbn_security_solution_storybook_config.mdx b/api_docs/kbn_security_solution_storybook_config.mdx index dc2148047902..5987e154ad97 100644 --- a/api_docs/kbn_security_solution_storybook_config.mdx +++ b/api_docs/kbn_security_solution_storybook_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-solution-storybook-config title: "@kbn/security-solution-storybook-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-solution-storybook-config plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-solution-storybook-config'] --- import kbnSecuritySolutionStorybookConfigObj from './kbn_security_solution_storybook_config.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_autocomplete.mdx b/api_docs/kbn_securitysolution_autocomplete.mdx index 7163dac06cdc..c00585e7e584 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-autocomplete'] --- import kbnSecuritysolutionAutocompleteObj from './kbn_securitysolution_autocomplete.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_data_table.mdx b/api_docs/kbn_securitysolution_data_table.mdx index 90937af245e1..31edbe0e987b 100644 --- a/api_docs/kbn_securitysolution_data_table.mdx +++ b/api_docs/kbn_securitysolution_data_table.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-data-table title: "@kbn/securitysolution-data-table" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-data-table plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-data-table'] --- import kbnSecuritysolutionDataTableObj from './kbn_securitysolution_data_table.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_ecs.mdx b/api_docs/kbn_securitysolution_ecs.mdx index 51e74190ac75..79ae0889e9b5 100644 --- a/api_docs/kbn_securitysolution_ecs.mdx +++ b/api_docs/kbn_securitysolution_ecs.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-ecs title: "@kbn/securitysolution-ecs" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-ecs plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-ecs'] --- import kbnSecuritysolutionEcsObj from './kbn_securitysolution_ecs.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_es_utils.mdx b/api_docs/kbn_securitysolution_es_utils.mdx index 17a40ed54bda..e2d8ecabdd01 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: 2024-01-04 +date: 2024-01-05 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 b2afeec510c3..f3d16f98cfe5 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: 2024-01-04 +date: 2024-01-05 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_grouping.mdx b/api_docs/kbn_securitysolution_grouping.mdx index db37eb84d866..9f5e7ab28808 100644 --- a/api_docs/kbn_securitysolution_grouping.mdx +++ b/api_docs/kbn_securitysolution_grouping.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-grouping title: "@kbn/securitysolution-grouping" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-grouping plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-grouping'] --- import kbnSecuritysolutionGroupingObj from './kbn_securitysolution_grouping.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_hook_utils.mdx b/api_docs/kbn_securitysolution_hook_utils.mdx index 0854b5329922..72daa43ab655 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: 2024-01-04 +date: 2024-01-05 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 acb3294dcff1..1fec8a6afab4 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: 2024-01-04 +date: 2024-01-05 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 ea3f440adbbe..a3bc207155a3 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: 2024-01-04 +date: 2024-01-05 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 4e888725a1da..f267d2864ebb 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: 2024-01-04 +date: 2024-01-05 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 0ffb44db2736..cca115723bef 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: 2024-01-04 +date: 2024-01-05 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 40e6da5004cc..3004e887c712 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: 2024-01-04 +date: 2024-01-05 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 18f0cf1ae0ee..9ef0c846b50e 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: 2024-01-04 +date: 2024-01-05 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 2a3347f55bae..f3422437f90e 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: 2024-01-04 +date: 2024-01-05 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 c1ee608bb1db..641c80338bae 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: 2024-01-04 +date: 2024-01-05 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 afa1e118ebf3..e0b25aa2b53e 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: 2024-01-04 +date: 2024-01-05 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 a87fc0b2ac0e..861b75ea630b 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: 2024-01-04 +date: 2024-01-05 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 95f346357177..4d3732c8fd04 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: 2024-01-04 +date: 2024-01-05 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 ae4b50cd3bb4..435496895bfa 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: 2024-01-04 +date: 2024-01-05 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 937fee8f5756..e602b89e617b 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/server-route-repository'] --- import kbnServerRouteRepositoryObj from './kbn_server_route_repository.devdocs.json'; diff --git a/api_docs/kbn_serverless_common_settings.mdx b/api_docs/kbn_serverless_common_settings.mdx index f81861d2b7a2..c77f381d416d 100644 --- a/api_docs/kbn_serverless_common_settings.mdx +++ b/api_docs/kbn_serverless_common_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-serverless-common-settings title: "@kbn/serverless-common-settings" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/serverless-common-settings plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/serverless-common-settings'] --- import kbnServerlessCommonSettingsObj from './kbn_serverless_common_settings.devdocs.json'; diff --git a/api_docs/kbn_serverless_observability_settings.mdx b/api_docs/kbn_serverless_observability_settings.mdx index ae38e144c548..def8a59b63c0 100644 --- a/api_docs/kbn_serverless_observability_settings.mdx +++ b/api_docs/kbn_serverless_observability_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-serverless-observability-settings title: "@kbn/serverless-observability-settings" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/serverless-observability-settings plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/serverless-observability-settings'] --- import kbnServerlessObservabilitySettingsObj from './kbn_serverless_observability_settings.devdocs.json'; diff --git a/api_docs/kbn_serverless_project_switcher.mdx b/api_docs/kbn_serverless_project_switcher.mdx index 2f55b792e84b..8b03d326266b 100644 --- a/api_docs/kbn_serverless_project_switcher.mdx +++ b/api_docs/kbn_serverless_project_switcher.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-serverless-project-switcher title: "@kbn/serverless-project-switcher" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/serverless-project-switcher plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/serverless-project-switcher'] --- import kbnServerlessProjectSwitcherObj from './kbn_serverless_project_switcher.devdocs.json'; diff --git a/api_docs/kbn_serverless_search_settings.mdx b/api_docs/kbn_serverless_search_settings.mdx index c6dc4f07ec72..05330095c4f3 100644 --- a/api_docs/kbn_serverless_search_settings.mdx +++ b/api_docs/kbn_serverless_search_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-serverless-search-settings title: "@kbn/serverless-search-settings" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/serverless-search-settings plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/serverless-search-settings'] --- import kbnServerlessSearchSettingsObj from './kbn_serverless_search_settings.devdocs.json'; diff --git a/api_docs/kbn_serverless_security_settings.mdx b/api_docs/kbn_serverless_security_settings.mdx index 83ebdf1d77e1..7ec53585281d 100644 --- a/api_docs/kbn_serverless_security_settings.mdx +++ b/api_docs/kbn_serverless_security_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-serverless-security-settings title: "@kbn/serverless-security-settings" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/serverless-security-settings plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/serverless-security-settings'] --- import kbnServerlessSecuritySettingsObj from './kbn_serverless_security_settings.devdocs.json'; diff --git a/api_docs/kbn_serverless_storybook_config.mdx b/api_docs/kbn_serverless_storybook_config.mdx index ec1bab55da23..09a17afeb930 100644 --- a/api_docs/kbn_serverless_storybook_config.mdx +++ b/api_docs/kbn_serverless_storybook_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-serverless-storybook-config title: "@kbn/serverless-storybook-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/serverless-storybook-config plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/serverless-storybook-config'] --- import kbnServerlessStorybookConfigObj from './kbn_serverless_storybook_config.devdocs.json'; diff --git a/api_docs/kbn_shared_svg.mdx b/api_docs/kbn_shared_svg.mdx index 5431f9e16773..823411fdbf8f 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: 2024-01-04 +date: 2024-01-05 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_solution.mdx b/api_docs/kbn_shared_ux_avatar_solution.mdx index 066131a53df6..c409b690c645 100644 --- a/api_docs/kbn_shared_ux_avatar_solution.mdx +++ b/api_docs/kbn_shared_ux_avatar_solution.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-avatar-solution title: "@kbn/shared-ux-avatar-solution" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-avatar-solution plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-avatar-solution'] --- import kbnSharedUxAvatarSolutionObj from './kbn_shared_ux_avatar_solution.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_button_exit_full_screen.mdx b/api_docs/kbn_shared_ux_button_exit_full_screen.mdx index 393886779359..cac9a71252c5 100644 --- a/api_docs/kbn_shared_ux_button_exit_full_screen.mdx +++ b/api_docs/kbn_shared_ux_button_exit_full_screen.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-button-exit-full-screen title: "@kbn/shared-ux-button-exit-full-screen" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-button-exit-full-screen plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-button-exit-full-screen'] --- import kbnSharedUxButtonExitFullScreenObj from './kbn_shared_ux_button_exit_full_screen.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_button_toolbar.mdx b/api_docs/kbn_shared_ux_button_toolbar.mdx index ef44ec1d7e58..88dded75428d 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: 2024-01-04 +date: 2024-01-05 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 c3f456f227f0..aa75fb31f0aa 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: 2024-01-04 +date: 2024-01-05 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 5d15ab603ca6..6f7b65aac95b 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: 2024-01-04 +date: 2024-01-05 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_chrome_navigation.mdx b/api_docs/kbn_shared_ux_chrome_navigation.mdx index bc6f88412940..5d17a765d230 100644 --- a/api_docs/kbn_shared_ux_chrome_navigation.mdx +++ b/api_docs/kbn_shared_ux_chrome_navigation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-chrome-navigation title: "@kbn/shared-ux-chrome-navigation" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-chrome-navigation plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-chrome-navigation'] --- import kbnSharedUxChromeNavigationObj from './kbn_shared_ux_chrome_navigation.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_error_boundary.mdx b/api_docs/kbn_shared_ux_error_boundary.mdx index 54073921400a..d78f20c30eaf 100644 --- a/api_docs/kbn_shared_ux_error_boundary.mdx +++ b/api_docs/kbn_shared_ux_error_boundary.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-error-boundary title: "@kbn/shared-ux-error-boundary" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-error-boundary plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-error-boundary'] --- import kbnSharedUxErrorBoundaryObj from './kbn_shared_ux_error_boundary.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_context.mdx b/api_docs/kbn_shared_ux_file_context.mdx index bc71b9ad9324..d64d3da11302 100644 --- a/api_docs/kbn_shared_ux_file_context.mdx +++ b/api_docs/kbn_shared_ux_file_context.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-context title: "@kbn/shared-ux-file-context" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-context plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-context'] --- import kbnSharedUxFileContextObj from './kbn_shared_ux_file_context.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_image.mdx b/api_docs/kbn_shared_ux_file_image.mdx index 5bf4b8888bcf..33f63c702108 100644 --- a/api_docs/kbn_shared_ux_file_image.mdx +++ b/api_docs/kbn_shared_ux_file_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-image title: "@kbn/shared-ux-file-image" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-image plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-image'] --- import kbnSharedUxFileImageObj from './kbn_shared_ux_file_image.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_image_mocks.mdx b/api_docs/kbn_shared_ux_file_image_mocks.mdx index b0657728c183..a76fa0df487e 100644 --- a/api_docs/kbn_shared_ux_file_image_mocks.mdx +++ b/api_docs/kbn_shared_ux_file_image_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-image-mocks title: "@kbn/shared-ux-file-image-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-image-mocks plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-image-mocks'] --- import kbnSharedUxFileImageMocksObj from './kbn_shared_ux_file_image_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_mocks.mdx b/api_docs/kbn_shared_ux_file_mocks.mdx index a3c5b0c967b4..683855969b41 100644 --- a/api_docs/kbn_shared_ux_file_mocks.mdx +++ b/api_docs/kbn_shared_ux_file_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-mocks title: "@kbn/shared-ux-file-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-mocks plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-mocks'] --- import kbnSharedUxFileMocksObj from './kbn_shared_ux_file_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_picker.mdx b/api_docs/kbn_shared_ux_file_picker.mdx index f4a8ac64778b..55fa022e4335 100644 --- a/api_docs/kbn_shared_ux_file_picker.mdx +++ b/api_docs/kbn_shared_ux_file_picker.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-picker title: "@kbn/shared-ux-file-picker" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-picker plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-picker'] --- import kbnSharedUxFilePickerObj from './kbn_shared_ux_file_picker.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_types.mdx b/api_docs/kbn_shared_ux_file_types.mdx index 5a36f4e70f4b..40068d1b30a1 100644 --- a/api_docs/kbn_shared_ux_file_types.mdx +++ b/api_docs/kbn_shared_ux_file_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-types title: "@kbn/shared-ux-file-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-types plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-types'] --- import kbnSharedUxFileTypesObj from './kbn_shared_ux_file_types.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_upload.mdx b/api_docs/kbn_shared_ux_file_upload.mdx index 214d49cacc56..52af2912e499 100644 --- a/api_docs/kbn_shared_ux_file_upload.mdx +++ b/api_docs/kbn_shared_ux_file_upload.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-upload title: "@kbn/shared-ux-file-upload" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-upload plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-upload'] --- import kbnSharedUxFileUploadObj from './kbn_shared_ux_file_upload.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_util.mdx b/api_docs/kbn_shared_ux_file_util.mdx index 55a174557b7b..329b66574c6c 100644 --- a/api_docs/kbn_shared_ux_file_util.mdx +++ b/api_docs/kbn_shared_ux_file_util.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-util title: "@kbn/shared-ux-file-util" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-util plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-util'] --- import kbnSharedUxFileUtilObj from './kbn_shared_ux_file_util.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_link_redirect_app.mdx b/api_docs/kbn_shared_ux_link_redirect_app.mdx index dfd6ed1999a2..c120f8c1c345 100644 --- a/api_docs/kbn_shared_ux_link_redirect_app.mdx +++ b/api_docs/kbn_shared_ux_link_redirect_app.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-link-redirect-app title: "@kbn/shared-ux-link-redirect-app" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-link-redirect-app plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-link-redirect-app'] --- import kbnSharedUxLinkRedirectAppObj from './kbn_shared_ux_link_redirect_app.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 8352f4b366f7..9a7ce12cf8ac 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: 2024-01-04 +date: 2024-01-05 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_markdown.mdx b/api_docs/kbn_shared_ux_markdown.mdx index 099046c2f5f2..4c79a852c390 100644 --- a/api_docs/kbn_shared_ux_markdown.mdx +++ b/api_docs/kbn_shared_ux_markdown.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-markdown title: "@kbn/shared-ux-markdown" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-markdown plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-markdown'] --- import kbnSharedUxMarkdownObj from './kbn_shared_ux_markdown.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_markdown_mocks.mdx b/api_docs/kbn_shared_ux_markdown_mocks.mdx index 99d0a0fe58b5..1a12232e0b2f 100644 --- a/api_docs/kbn_shared_ux_markdown_mocks.mdx +++ b/api_docs/kbn_shared_ux_markdown_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-markdown-mocks title: "@kbn/shared-ux-markdown-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-markdown-mocks plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-markdown-mocks'] --- import kbnSharedUxMarkdownMocksObj from './kbn_shared_ux_markdown_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 93d84a4d6090..d9d3673bd3bb 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: 2024-01-04 +date: 2024-01-05 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 b7b893d353ce..97714d7b5422 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: 2024-01-04 +date: 2024-01-05 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 b2e2082bf682..6600b947fe2e 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: 2024-01-04 +date: 2024-01-05 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 7886c18d6e14..aa6aaa03ebf8 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: 2024-01-04 +date: 2024-01-05 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 6a5df38fdb42..87657ae6f190 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: 2024-01-04 +date: 2024-01-05 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 cfc33d147658..6bf28994f3b3 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: 2024-01-04 +date: 2024-01-05 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 9039fd3d9dda..737dabad08b5 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: 2024-01-04 +date: 2024-01-05 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 6b510fb7bb1d..525aef5e95ca 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: 2024-01-04 +date: 2024-01-05 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 f71530cb9c8e..17c1929004f3 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: 2024-01-04 +date: 2024-01-05 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 538aa87c1394..40a7869373d1 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: 2024-01-04 +date: 2024-01-05 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 40b76ca9599e..891feab6e4df 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: 2024-01-04 +date: 2024-01-05 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 b5c76b7869f4..caa3acb9fbf2 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: 2024-01-04 +date: 2024-01-05 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 40ea019a88d4..d3bafe9772ef 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: 2024-01-04 +date: 2024-01-05 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_prompt_not_found.mdx b/api_docs/kbn_shared_ux_prompt_not_found.mdx index 38f5104395b4..a7d8129d6771 100644 --- a/api_docs/kbn_shared_ux_prompt_not_found.mdx +++ b/api_docs/kbn_shared_ux_prompt_not_found.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-prompt-not-found title: "@kbn/shared-ux-prompt-not-found" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-prompt-not-found plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-prompt-not-found'] --- import kbnSharedUxPromptNotFoundObj from './kbn_shared_ux_prompt_not_found.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_router.mdx b/api_docs/kbn_shared_ux_router.mdx index 339bdfe6f8a4..bab20d3ae174 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: 2024-01-04 +date: 2024-01-05 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 7389373f0159..2dbcdccbdae4 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: 2024-01-04 +date: 2024-01-05 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 f79153567297..e5ceb4b1d0b3 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: 2024-01-04 +date: 2024-01-05 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 3f305dba05a8..6c3d9e5432ce 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: 2024-01-04 +date: 2024-01-05 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 6eefeea597ad..66229d6d6b75 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-utility'] --- import kbnSharedUxUtilityObj from './kbn_shared_ux_utility.devdocs.json'; diff --git a/api_docs/kbn_slo_schema.mdx b/api_docs/kbn_slo_schema.mdx index ebc02e018b76..91fe7f815a77 100644 --- a/api_docs/kbn_slo_schema.mdx +++ b/api_docs/kbn_slo_schema.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-slo-schema title: "@kbn/slo-schema" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/slo-schema plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/slo-schema'] --- import kbnSloSchemaObj from './kbn_slo_schema.devdocs.json'; diff --git a/api_docs/kbn_some_dev_log.mdx b/api_docs/kbn_some_dev_log.mdx index 4e4bcfdef739..172a66d34cd4 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/some-dev-log'] --- import kbnSomeDevLogObj from './kbn_some_dev_log.devdocs.json'; diff --git a/api_docs/kbn_std.mdx b/api_docs/kbn_std.mdx index e41f4e72b5f4..903d80598025 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: 2024-01-04 +date: 2024-01-05 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 a59d24d575dd..5a819a2483e7 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: 2024-01-04 +date: 2024-01-05 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 463a6ccd8e6b..ddf60813b3e6 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: 2024-01-04 +date: 2024-01-05 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 d017bcc4387d..d357765de093 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: 2024-01-04 +date: 2024-01-05 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 dbc578273baf..deef6f2d8bfa 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: 2024-01-04 +date: 2024-01-05 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 90ad352d2430..ee0a17dd56e4 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: 2024-01-04 +date: 2024-01-05 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 d2a83bfeb582..8d65942208d8 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test-subj-selector'] --- import kbnTestSubjSelectorObj from './kbn_test_subj_selector.devdocs.json'; diff --git a/api_docs/kbn_text_based_editor.mdx b/api_docs/kbn_text_based_editor.mdx index 6fbbedbb4060..1a147019c623 100644 --- a/api_docs/kbn_text_based_editor.mdx +++ b/api_docs/kbn_text_based_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-text-based-editor title: "@kbn/text-based-editor" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/text-based-editor plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/text-based-editor'] --- import kbnTextBasedEditorObj from './kbn_text_based_editor.devdocs.json'; diff --git a/api_docs/kbn_tooling_log.mdx b/api_docs/kbn_tooling_log.mdx index 8394bd0a1bed..0bcb9d298d2a 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/tooling-log'] --- import kbnToolingLogObj from './kbn_tooling_log.devdocs.json'; diff --git a/api_docs/kbn_triggers_actions_ui_types.mdx b/api_docs/kbn_triggers_actions_ui_types.mdx index 588370be25eb..8c143f9b47d4 100644 --- a/api_docs/kbn_triggers_actions_ui_types.mdx +++ b/api_docs/kbn_triggers_actions_ui_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-triggers-actions-ui-types title: "@kbn/triggers-actions-ui-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/triggers-actions-ui-types plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/triggers-actions-ui-types'] --- import kbnTriggersActionsUiTypesObj from './kbn_triggers_actions_ui_types.devdocs.json'; diff --git a/api_docs/kbn_ts_projects.mdx b/api_docs/kbn_ts_projects.mdx index a6f14944025e..0bcc134f3bd7 100644 --- a/api_docs/kbn_ts_projects.mdx +++ b/api_docs/kbn_ts_projects.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ts-projects title: "@kbn/ts-projects" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ts-projects plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ts-projects'] --- import kbnTsProjectsObj from './kbn_ts_projects.devdocs.json'; diff --git a/api_docs/kbn_typed_react_router_config.mdx b/api_docs/kbn_typed_react_router_config.mdx index a98d6266b66b..08cde87cb3cf 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: 2024-01-04 +date: 2024-01-05 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_actions_browser.mdx b/api_docs/kbn_ui_actions_browser.mdx index 46ba6f2227f3..153d573a373e 100644 --- a/api_docs/kbn_ui_actions_browser.mdx +++ b/api_docs/kbn_ui_actions_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ui-actions-browser title: "@kbn/ui-actions-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ui-actions-browser plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ui-actions-browser'] --- import kbnUiActionsBrowserObj from './kbn_ui_actions_browser.devdocs.json'; diff --git a/api_docs/kbn_ui_shared_deps_src.mdx b/api_docs/kbn_ui_shared_deps_src.mdx index 01f1a1b95e1f..fb710c473e0b 100644 --- a/api_docs/kbn_ui_shared_deps_src.mdx +++ b/api_docs/kbn_ui_shared_deps_src.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ui-shared-deps-src title: "@kbn/ui-shared-deps-src" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ui-shared-deps-src plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ui-shared-deps-src'] --- import kbnUiSharedDepsSrcObj from './kbn_ui_shared_deps_src.devdocs.json'; diff --git a/api_docs/kbn_ui_theme.mdx b/api_docs/kbn_ui_theme.mdx index 2054df010326..7454b53b0e2f 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ui-theme'] --- import kbnUiThemeObj from './kbn_ui_theme.devdocs.json'; diff --git a/api_docs/kbn_unified_data_table.mdx b/api_docs/kbn_unified_data_table.mdx index 32098ef44350..2380b7372f2f 100644 --- a/api_docs/kbn_unified_data_table.mdx +++ b/api_docs/kbn_unified_data_table.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-unified-data-table title: "@kbn/unified-data-table" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/unified-data-table plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/unified-data-table'] --- import kbnUnifiedDataTableObj from './kbn_unified_data_table.devdocs.json'; diff --git a/api_docs/kbn_unified_doc_viewer.mdx b/api_docs/kbn_unified_doc_viewer.mdx index 99b430eb56fc..79db7c5bfe3d 100644 --- a/api_docs/kbn_unified_doc_viewer.mdx +++ b/api_docs/kbn_unified_doc_viewer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-unified-doc-viewer title: "@kbn/unified-doc-viewer" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/unified-doc-viewer plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/unified-doc-viewer'] --- import kbnUnifiedDocViewerObj from './kbn_unified_doc_viewer.devdocs.json'; diff --git a/api_docs/kbn_unified_field_list.mdx b/api_docs/kbn_unified_field_list.mdx index 52be5cce1383..000295820d1c 100644 --- a/api_docs/kbn_unified_field_list.mdx +++ b/api_docs/kbn_unified_field_list.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-unified-field-list title: "@kbn/unified-field-list" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/unified-field-list plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/unified-field-list'] --- import kbnUnifiedFieldListObj from './kbn_unified_field_list.devdocs.json'; diff --git a/api_docs/kbn_unsaved_changes_badge.mdx b/api_docs/kbn_unsaved_changes_badge.mdx index aae4e0e6b721..455d75bd1f3d 100644 --- a/api_docs/kbn_unsaved_changes_badge.mdx +++ b/api_docs/kbn_unsaved_changes_badge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-unsaved-changes-badge title: "@kbn/unsaved-changes-badge" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/unsaved-changes-badge plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/unsaved-changes-badge'] --- import kbnUnsavedChangesBadgeObj from './kbn_unsaved_changes_badge.devdocs.json'; diff --git a/api_docs/kbn_url_state.mdx b/api_docs/kbn_url_state.mdx index 52085bb35f2b..530559e8179f 100644 --- a/api_docs/kbn_url_state.mdx +++ b/api_docs/kbn_url_state.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-url-state title: "@kbn/url-state" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/url-state plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/url-state'] --- import kbnUrlStateObj from './kbn_url_state.devdocs.json'; diff --git a/api_docs/kbn_use_tracked_promise.mdx b/api_docs/kbn_use_tracked_promise.mdx index 20ffe3d59787..12971d1114d2 100644 --- a/api_docs/kbn_use_tracked_promise.mdx +++ b/api_docs/kbn_use_tracked_promise.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-use-tracked-promise title: "@kbn/use-tracked-promise" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/use-tracked-promise plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/use-tracked-promise'] --- import kbnUseTrackedPromiseObj from './kbn_use_tracked_promise.devdocs.json'; diff --git a/api_docs/kbn_user_profile_components.mdx b/api_docs/kbn_user_profile_components.mdx index 10edf6016074..dc8b88022e02 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: 2024-01-04 +date: 2024-01-05 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 7d3fc106dac2..202d72ad321f 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: 2024-01-04 +date: 2024-01-05 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 c276f12da1e5..fad43a7ed0bd 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: 2024-01-04 +date: 2024-01-05 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 f069f54e5d8c..9835772148f7 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utils'] --- import kbnUtilsObj from './kbn_utils.devdocs.json'; diff --git a/api_docs/kbn_visualization_ui_components.mdx b/api_docs/kbn_visualization_ui_components.mdx index f5580d57a021..844311235ca6 100644 --- a/api_docs/kbn_visualization_ui_components.mdx +++ b/api_docs/kbn_visualization_ui_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-visualization-ui-components title: "@kbn/visualization-ui-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/visualization-ui-components plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/visualization-ui-components'] --- import kbnVisualizationUiComponentsObj from './kbn_visualization_ui_components.devdocs.json'; diff --git a/api_docs/kbn_visualization_utils.mdx b/api_docs/kbn_visualization_utils.mdx index 7f270fa1d36f..daba78a1274f 100644 --- a/api_docs/kbn_visualization_utils.mdx +++ b/api_docs/kbn_visualization_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-visualization-utils title: "@kbn/visualization-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/visualization-utils plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/visualization-utils'] --- import kbnVisualizationUtilsObj from './kbn_visualization_utils.devdocs.json'; diff --git a/api_docs/kbn_xstate_utils.mdx b/api_docs/kbn_xstate_utils.mdx index ef70cc8f32ac..ad4d3d9ec23a 100644 --- a/api_docs/kbn_xstate_utils.mdx +++ b/api_docs/kbn_xstate_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-xstate-utils title: "@kbn/xstate-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/xstate-utils plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/xstate-utils'] --- import kbnXstateUtilsObj from './kbn_xstate_utils.devdocs.json'; diff --git a/api_docs/kbn_yarn_lock_validator.mdx b/api_docs/kbn_yarn_lock_validator.mdx index 0c633dc5c27d..a46de2706bd4 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/yarn-lock-validator'] --- import kbnYarnLockValidatorObj from './kbn_yarn_lock_validator.devdocs.json'; diff --git a/api_docs/kbn_zod_helpers.mdx b/api_docs/kbn_zod_helpers.mdx index a418ec701d6c..80db9667d58e 100644 --- a/api_docs/kbn_zod_helpers.mdx +++ b/api_docs/kbn_zod_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-zod-helpers title: "@kbn/zod-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/zod-helpers plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/zod-helpers'] --- import kbnZodHelpersObj from './kbn_zod_helpers.devdocs.json'; diff --git a/api_docs/kibana_overview.mdx b/api_docs/kibana_overview.mdx index f856e3a8ce37..ae784410c387 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: 2024-01-04 +date: 2024-01-05 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 b24f96cb3444..a2a3d5c5ce4b 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: 2024-01-04 +date: 2024-01-05 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 b5c7372638bc..5ab86f6c3e6b 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: 2024-01-04 +date: 2024-01-05 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 a5ffb3a455b9..91f61d77ce8d 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kubernetesSecurity'] --- import kubernetesSecurityObj from './kubernetes_security.devdocs.json'; diff --git a/api_docs/lens.mdx b/api_docs/lens.mdx index 162d4ed72ae9..a85196d52290 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'lens'] --- import lensObj from './lens.devdocs.json'; diff --git a/api_docs/license_api_guard.mdx b/api_docs/license_api_guard.mdx index ea890b5957f2..d4a4818992a9 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: 2024-01-04 +date: 2024-01-05 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 e3b420f9e5b1..43deddf57865 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: 2024-01-04 +date: 2024-01-05 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 14e73c2998c7..435dff6429fe 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licensing'] --- import licensingObj from './licensing.devdocs.json'; diff --git a/api_docs/links.mdx b/api_docs/links.mdx index cf0d1eed7664..8961e4efc4e7 100644 --- a/api_docs/links.mdx +++ b/api_docs/links.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/links title: "links" image: https://source.unsplash.com/400x175/?github description: API docs for the links plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'links'] --- import linksObj from './links.devdocs.json'; diff --git a/api_docs/lists.mdx b/api_docs/lists.mdx index 010957d4e13d..e528494c28b5 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'lists'] --- import listsObj from './lists.devdocs.json'; diff --git a/api_docs/log_explorer.mdx b/api_docs/log_explorer.mdx index 7cfcac8ae5cf..61e28f7dd904 100644 --- a/api_docs/log_explorer.mdx +++ b/api_docs/log_explorer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/logExplorer title: "logExplorer" image: https://source.unsplash.com/400x175/?github description: API docs for the logExplorer plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'logExplorer'] --- import logExplorerObj from './log_explorer.devdocs.json'; diff --git a/api_docs/logs_shared.mdx b/api_docs/logs_shared.mdx index 0353663c316d..5df148d5030a 100644 --- a/api_docs/logs_shared.mdx +++ b/api_docs/logs_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/logsShared title: "logsShared" image: https://source.unsplash.com/400x175/?github description: API docs for the logsShared plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'logsShared'] --- import logsSharedObj from './logs_shared.devdocs.json'; diff --git a/api_docs/management.mdx b/api_docs/management.mdx index eea3cf75d854..97c2448a4a60 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'management'] --- import managementObj from './management.devdocs.json'; diff --git a/api_docs/maps.mdx b/api_docs/maps.mdx index 816acd820239..8249fbd21928 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: 2024-01-04 +date: 2024-01-05 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 e7e002205a35..2cb6c52f8029 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'mapsEms'] --- import mapsEmsObj from './maps_ems.devdocs.json'; diff --git a/api_docs/metrics_data_access.mdx b/api_docs/metrics_data_access.mdx index 9fd89853595b..f47cdcc79238 100644 --- a/api_docs/metrics_data_access.mdx +++ b/api_docs/metrics_data_access.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/metricsDataAccess title: "metricsDataAccess" image: https://source.unsplash.com/400x175/?github description: API docs for the metricsDataAccess plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'metricsDataAccess'] --- import metricsDataAccessObj from './metrics_data_access.devdocs.json'; diff --git a/api_docs/ml.mdx b/api_docs/ml.mdx index 682e2bdebbdf..7147bfdacb01 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ml'] --- import mlObj from './ml.devdocs.json'; diff --git a/api_docs/mock_idp_plugin.mdx b/api_docs/mock_idp_plugin.mdx index d4b39b356cba..fdadf8f97a19 100644 --- a/api_docs/mock_idp_plugin.mdx +++ b/api_docs/mock_idp_plugin.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/mockIdpPlugin title: "mockIdpPlugin" image: https://source.unsplash.com/400x175/?github description: API docs for the mockIdpPlugin plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'mockIdpPlugin'] --- import mockIdpPluginObj from './mock_idp_plugin.devdocs.json'; diff --git a/api_docs/monitoring.mdx b/api_docs/monitoring.mdx index 2f971fff8ff4..de35753b2b77 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: 2024-01-04 +date: 2024-01-05 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 be8ae0637856..6755ee6a39ee 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: 2024-01-04 +date: 2024-01-05 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 9356cae6383b..46c8c85aa128 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: 2024-01-04 +date: 2024-01-05 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 9947a396715b..48caf17193c0 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'newsfeed'] --- import newsfeedObj from './newsfeed.devdocs.json'; diff --git a/api_docs/no_data_page.mdx b/api_docs/no_data_page.mdx index 3031839874fc..e45789a08243 100644 --- a/api_docs/no_data_page.mdx +++ b/api_docs/no_data_page.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/noDataPage title: "noDataPage" image: https://source.unsplash.com/400x175/?github description: API docs for the noDataPage plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'noDataPage'] --- import noDataPageObj from './no_data_page.devdocs.json'; diff --git a/api_docs/notifications.mdx b/api_docs/notifications.mdx index 68875d62f9d6..f5e5b2f68ea4 100644 --- a/api_docs/notifications.mdx +++ b/api_docs/notifications.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/notifications title: "notifications" image: https://source.unsplash.com/400x175/?github description: API docs for the notifications plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'notifications'] --- import notificationsObj from './notifications.devdocs.json'; diff --git a/api_docs/observability.mdx b/api_docs/observability.mdx index bbb951a816d2..1aabd1bace5e 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observability'] --- import observabilityObj from './observability.devdocs.json'; diff --git a/api_docs/observability_a_i_assistant.mdx b/api_docs/observability_a_i_assistant.mdx index 3f95923dd0f9..4ebd383be199 100644 --- a/api_docs/observability_a_i_assistant.mdx +++ b/api_docs/observability_a_i_assistant.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observabilityAIAssistant title: "observabilityAIAssistant" image: https://source.unsplash.com/400x175/?github description: API docs for the observabilityAIAssistant plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observabilityAIAssistant'] --- import observabilityAIAssistantObj from './observability_a_i_assistant.devdocs.json'; diff --git a/api_docs/observability_log_explorer.mdx b/api_docs/observability_log_explorer.mdx index 302ac71a55f4..f6df8e368882 100644 --- a/api_docs/observability_log_explorer.mdx +++ b/api_docs/observability_log_explorer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observabilityLogExplorer title: "observabilityLogExplorer" image: https://source.unsplash.com/400x175/?github description: API docs for the observabilityLogExplorer plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observabilityLogExplorer'] --- import observabilityLogExplorerObj from './observability_log_explorer.devdocs.json'; diff --git a/api_docs/observability_onboarding.mdx b/api_docs/observability_onboarding.mdx index da8442b82ed0..41404c514c31 100644 --- a/api_docs/observability_onboarding.mdx +++ b/api_docs/observability_onboarding.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observabilityOnboarding title: "observabilityOnboarding" image: https://source.unsplash.com/400x175/?github description: API docs for the observabilityOnboarding plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observabilityOnboarding'] --- import observabilityOnboardingObj from './observability_onboarding.devdocs.json'; diff --git a/api_docs/observability_shared.mdx b/api_docs/observability_shared.mdx index 74848aaa6f3f..e625482424d6 100644 --- a/api_docs/observability_shared.mdx +++ b/api_docs/observability_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observabilityShared title: "observabilityShared" image: https://source.unsplash.com/400x175/?github description: API docs for the observabilityShared plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observabilityShared'] --- import observabilitySharedObj from './observability_shared.devdocs.json'; diff --git a/api_docs/osquery.mdx b/api_docs/osquery.mdx index be0ab0aceff4..0506487c4bb8 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'osquery'] --- import osqueryObj from './osquery.devdocs.json'; diff --git a/api_docs/painless_lab.mdx b/api_docs/painless_lab.mdx index be7778b29462..6514a7ff90bc 100644 --- a/api_docs/painless_lab.mdx +++ b/api_docs/painless_lab.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/painlessLab title: "painlessLab" image: https://source.unsplash.com/400x175/?github description: API docs for the painlessLab plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'painlessLab'] --- import painlessLabObj from './painless_lab.devdocs.json'; diff --git a/api_docs/plugin_directory.mdx b/api_docs/plugin_directory.mdx index c93080b72b3a..c3f83b74fae4 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -21,7 +21,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | API Count | Any Count | Missing comments | Missing exports | |--------------|----------|-----------------|--------| -| 78161 | 234 | 66877 | 1696 | +| 78586 | 237 | 67267 | 1696 | ## Plugin Directory @@ -70,7 +70,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | - | 37 | 0 | 35 | 2 | | | [@elastic/security-threat-hunting-investigations](https://github.com/orgs/elastic/teams/security-threat-hunting-investigations) | APIs used to assess the quality of data in Elasticsearch indexes | 2 | 0 | 0 | 0 | | | [@elastic/security-solution](https://github.com/orgs/elastic/teams/security-solution) | Server APIs for the Elastic AI Assistant | 36 | 0 | 28 | 0 | -| | [@elastic/kibana-presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Adds embeddables service to Kibana | 547 | 1 | 446 | 8 | +| | [@elastic/kibana-presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Adds embeddables service to Kibana | 541 | 1 | 440 | 7 | | | [@elastic/kibana-presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Extends embeddable plugin with more functionality | 14 | 0 | 14 | 0 | | | [@elastic/kibana-security](https://github.com/orgs/elastic/teams/kibana-security) | This plugin provides encryption and decryption utilities for saved objects containing sensitive information. | 53 | 0 | 46 | 1 | | | [@elastic/enterprise-search-frontend](https://github.com/orgs/elastic/teams/enterprise-search-frontend) | Adds dashboards for discovering and managing Enterprise Search products. | 5 | 0 | 5 | 0 | @@ -469,7 +469,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | - | 37 | 0 | 29 | 1 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 2 | 0 | 0 | 0 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 29 | 0 | 29 | 1 | -| | [@elastic/appex-qa](https://github.com/orgs/elastic/teams/appex-qa) | - | 4 | 0 | 4 | 0 | +| | [@elastic/appex-qa](https://github.com/orgs/elastic/teams/appex-qa) | - | 435 | 3 | 400 | 1 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 1 | 0 | 0 | 0 | | | [@elastic/platform-deployment-management](https://github.com/orgs/elastic/teams/platform-deployment-management) | - | 1 | 0 | 1 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 10 | 0 | 10 | 1 | diff --git a/api_docs/presentation_util.mdx b/api_docs/presentation_util.mdx index 6e6c5741a6ec..74e6e10decd0 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: 2024-01-04 +date: 2024-01-05 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 399dd6418335..29f635109fcc 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'profiling'] --- import profilingObj from './profiling.devdocs.json'; diff --git a/api_docs/profiling_data_access.mdx b/api_docs/profiling_data_access.mdx index f6311d7c5448..d4b71e053ed6 100644 --- a/api_docs/profiling_data_access.mdx +++ b/api_docs/profiling_data_access.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/profilingDataAccess title: "profilingDataAccess" image: https://source.unsplash.com/400x175/?github description: API docs for the profilingDataAccess plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'profilingDataAccess'] --- import profilingDataAccessObj from './profiling_data_access.devdocs.json'; diff --git a/api_docs/remote_clusters.mdx b/api_docs/remote_clusters.mdx index 78c2e5aa4aa5..44d743b543ed 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: 2024-01-04 +date: 2024-01-05 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 40ad623e1af4..3329e5263415 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: 2024-01-04 +date: 2024-01-05 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 250319a684a6..06ebfce04171 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'rollup'] --- import rollupObj from './rollup.devdocs.json'; diff --git a/api_docs/rule_registry.mdx b/api_docs/rule_registry.mdx index c951acaa232d..62e7671dd989 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: 2024-01-04 +date: 2024-01-05 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 9db85c536b5c..0fb857e63008 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: 2024-01-04 +date: 2024-01-05 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 603b1a75edb6..0892b8561c11 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: 2024-01-04 +date: 2024-01-05 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 9597a8287cc3..246e8be6725e 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: 2024-01-04 +date: 2024-01-05 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 a437d3b666ce..8a92cc621676 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: 2024-01-04 +date: 2024-01-05 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 e72d964311e9..cbaba9681304 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: 2024-01-04 +date: 2024-01-05 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 903def8f53d0..8089744a3da7 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: 2024-01-04 +date: 2024-01-05 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 7ce63486b6cf..122cd18cbcdc 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: 2024-01-04 +date: 2024-01-05 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 87cc479ecea9..68c9adfa10b5 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: 2024-01-04 +date: 2024-01-05 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 fb382915fbd0..10361f87a534 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: 2024-01-04 +date: 2024-01-05 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 8fd74810bb99..9bf5b994cc40 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'security'] --- import securityObj from './security.devdocs.json'; diff --git a/api_docs/security_solution.devdocs.json b/api_docs/security_solution.devdocs.json index c50901f256ca..816001e8e21b 100644 --- a/api_docs/security_solution.devdocs.json +++ b/api_docs/security_solution.devdocs.json @@ -114,7 +114,7 @@ "label": "experimentalFeatures", "description": [], "signature": [ - "{ readonly tGridEnabled: boolean; readonly tGridEventRenderedViewEnabled: boolean; readonly excludePoliciesInFilterEnabled: boolean; readonly kubernetesEnabled: boolean; readonly chartEmbeddablesEnabled: boolean; readonly donutChartEmbeddablesEnabled: boolean; readonly alertsPreviewChartEmbeddablesEnabled: boolean; readonly previewTelemetryUrlEnabled: boolean; readonly insightsRelatedAlertsByProcessAncestry: boolean; readonly extendedRuleExecutionLoggingEnabled: boolean; readonly assistantStreamingEnabled: boolean; readonly socTrendsEnabled: boolean; readonly responseActionsEnabled: boolean; readonly endpointResponseActionsEnabled: boolean; readonly responseActionUploadEnabled: boolean; readonly responseActionsSentinelOneV1Enabled: boolean; readonly alertsPageChartsEnabled: boolean; readonly alertTypeEnabled: boolean; readonly expandableFlyoutInCreateRuleEnabled: boolean; readonly alertsPageFiltersEnabled: boolean; readonly assistantModelEvaluation: boolean; readonly newUserDetailsFlyout: boolean; readonly riskScoringPersistence: boolean; readonly riskScoringRoutesEnabled: boolean; readonly esqlRulesDisabled: boolean; readonly protectionUpdatesEnabled: boolean; readonly disableTimelineSaveTour: boolean; readonly riskEnginePrivilegesRouteEnabled: boolean; readonly entityAnalyticsAssetCriticalityEnabled: boolean; readonly sentinelOneDataInAnalyzerEnabled: boolean; readonly sentinelOneManualHostActionsEnabled: boolean; readonly jsonPrebuiltRulesDiffingEnabled: boolean; readonly timelineEsqlTabDisabled: boolean; }" + "{ readonly tGridEnabled: boolean; readonly tGridEventRenderedViewEnabled: boolean; readonly excludePoliciesInFilterEnabled: boolean; readonly kubernetesEnabled: boolean; readonly chartEmbeddablesEnabled: boolean; readonly donutChartEmbeddablesEnabled: boolean; readonly alertsPreviewChartEmbeddablesEnabled: boolean; readonly previewTelemetryUrlEnabled: boolean; readonly insightsRelatedAlertsByProcessAncestry: boolean; readonly extendedRuleExecutionLoggingEnabled: boolean; readonly assistantStreamingEnabled: boolean; readonly socTrendsEnabled: boolean; readonly responseActionsEnabled: boolean; readonly endpointResponseActionsEnabled: boolean; readonly responseActionUploadEnabled: boolean; readonly responseActionsSentinelOneV1Enabled: boolean; readonly alertsPageChartsEnabled: boolean; readonly alertTypeEnabled: boolean; readonly expandableFlyoutInCreateRuleEnabled: boolean; readonly alertsPageFiltersEnabled: boolean; readonly assistantModelEvaluation: boolean; readonly newUserDetailsFlyout: boolean; readonly newHostDetailsFlyout: boolean; readonly riskScoringPersistence: boolean; readonly riskScoringRoutesEnabled: boolean; readonly esqlRulesDisabled: boolean; readonly protectionUpdatesEnabled: boolean; readonly disableTimelineSaveTour: boolean; readonly riskEnginePrivilegesRouteEnabled: boolean; readonly entityAnalyticsAssetCriticalityEnabled: boolean; readonly sentinelOneDataInAnalyzerEnabled: boolean; readonly sentinelOneManualHostActionsEnabled: boolean; readonly jsonPrebuiltRulesDiffingEnabled: boolean; readonly timelineEsqlTabDisabled: boolean; }" ], "path": "x-pack/plugins/security_solution/public/plugin.tsx", "deprecated": false, @@ -568,7 +568,7 @@ "\nExperimental flag needed to enable the link" ], "signature": [ - "\"tGridEnabled\" | \"tGridEventRenderedViewEnabled\" | \"excludePoliciesInFilterEnabled\" | \"kubernetesEnabled\" | \"chartEmbeddablesEnabled\" | \"donutChartEmbeddablesEnabled\" | \"alertsPreviewChartEmbeddablesEnabled\" | \"previewTelemetryUrlEnabled\" | \"insightsRelatedAlertsByProcessAncestry\" | \"extendedRuleExecutionLoggingEnabled\" | \"assistantStreamingEnabled\" | \"socTrendsEnabled\" | \"responseActionsEnabled\" | \"endpointResponseActionsEnabled\" | \"responseActionUploadEnabled\" | \"responseActionsSentinelOneV1Enabled\" | \"alertsPageChartsEnabled\" | \"alertTypeEnabled\" | \"expandableFlyoutInCreateRuleEnabled\" | \"alertsPageFiltersEnabled\" | \"assistantModelEvaluation\" | \"newUserDetailsFlyout\" | \"riskScoringPersistence\" | \"riskScoringRoutesEnabled\" | \"esqlRulesDisabled\" | \"protectionUpdatesEnabled\" | \"disableTimelineSaveTour\" | \"riskEnginePrivilegesRouteEnabled\" | \"entityAnalyticsAssetCriticalityEnabled\" | \"sentinelOneDataInAnalyzerEnabled\" | \"sentinelOneManualHostActionsEnabled\" | \"jsonPrebuiltRulesDiffingEnabled\" | \"timelineEsqlTabDisabled\" | undefined" + "\"tGridEnabled\" | \"tGridEventRenderedViewEnabled\" | \"excludePoliciesInFilterEnabled\" | \"kubernetesEnabled\" | \"chartEmbeddablesEnabled\" | \"donutChartEmbeddablesEnabled\" | \"alertsPreviewChartEmbeddablesEnabled\" | \"previewTelemetryUrlEnabled\" | \"insightsRelatedAlertsByProcessAncestry\" | \"extendedRuleExecutionLoggingEnabled\" | \"assistantStreamingEnabled\" | \"socTrendsEnabled\" | \"responseActionsEnabled\" | \"endpointResponseActionsEnabled\" | \"responseActionUploadEnabled\" | \"responseActionsSentinelOneV1Enabled\" | \"alertsPageChartsEnabled\" | \"alertTypeEnabled\" | \"expandableFlyoutInCreateRuleEnabled\" | \"alertsPageFiltersEnabled\" | \"assistantModelEvaluation\" | \"newUserDetailsFlyout\" | \"newHostDetailsFlyout\" | \"riskScoringPersistence\" | \"riskScoringRoutesEnabled\" | \"esqlRulesDisabled\" | \"protectionUpdatesEnabled\" | \"disableTimelineSaveTour\" | \"riskEnginePrivilegesRouteEnabled\" | \"entityAnalyticsAssetCriticalityEnabled\" | \"sentinelOneDataInAnalyzerEnabled\" | \"sentinelOneManualHostActionsEnabled\" | \"jsonPrebuiltRulesDiffingEnabled\" | \"timelineEsqlTabDisabled\" | undefined" ], "path": "x-pack/plugins/security_solution/public/common/links/types.ts", "deprecated": false, @@ -648,7 +648,7 @@ "\nExperimental flag needed to disable the link. Opposite of experimentalKey" ], "signature": [ - "\"tGridEnabled\" | \"tGridEventRenderedViewEnabled\" | \"excludePoliciesInFilterEnabled\" | \"kubernetesEnabled\" | \"chartEmbeddablesEnabled\" | \"donutChartEmbeddablesEnabled\" | \"alertsPreviewChartEmbeddablesEnabled\" | \"previewTelemetryUrlEnabled\" | \"insightsRelatedAlertsByProcessAncestry\" | \"extendedRuleExecutionLoggingEnabled\" | \"assistantStreamingEnabled\" | \"socTrendsEnabled\" | \"responseActionsEnabled\" | \"endpointResponseActionsEnabled\" | \"responseActionUploadEnabled\" | \"responseActionsSentinelOneV1Enabled\" | \"alertsPageChartsEnabled\" | \"alertTypeEnabled\" | \"expandableFlyoutInCreateRuleEnabled\" | \"alertsPageFiltersEnabled\" | \"assistantModelEvaluation\" | \"newUserDetailsFlyout\" | \"riskScoringPersistence\" | \"riskScoringRoutesEnabled\" | \"esqlRulesDisabled\" | \"protectionUpdatesEnabled\" | \"disableTimelineSaveTour\" | \"riskEnginePrivilegesRouteEnabled\" | \"entityAnalyticsAssetCriticalityEnabled\" | \"sentinelOneDataInAnalyzerEnabled\" | \"sentinelOneManualHostActionsEnabled\" | \"jsonPrebuiltRulesDiffingEnabled\" | \"timelineEsqlTabDisabled\" | undefined" + "\"tGridEnabled\" | \"tGridEventRenderedViewEnabled\" | \"excludePoliciesInFilterEnabled\" | \"kubernetesEnabled\" | \"chartEmbeddablesEnabled\" | \"donutChartEmbeddablesEnabled\" | \"alertsPreviewChartEmbeddablesEnabled\" | \"previewTelemetryUrlEnabled\" | \"insightsRelatedAlertsByProcessAncestry\" | \"extendedRuleExecutionLoggingEnabled\" | \"assistantStreamingEnabled\" | \"socTrendsEnabled\" | \"responseActionsEnabled\" | \"endpointResponseActionsEnabled\" | \"responseActionUploadEnabled\" | \"responseActionsSentinelOneV1Enabled\" | \"alertsPageChartsEnabled\" | \"alertTypeEnabled\" | \"expandableFlyoutInCreateRuleEnabled\" | \"alertsPageFiltersEnabled\" | \"assistantModelEvaluation\" | \"newUserDetailsFlyout\" | \"newHostDetailsFlyout\" | \"riskScoringPersistence\" | \"riskScoringRoutesEnabled\" | \"esqlRulesDisabled\" | \"protectionUpdatesEnabled\" | \"disableTimelineSaveTour\" | \"riskEnginePrivilegesRouteEnabled\" | \"entityAnalyticsAssetCriticalityEnabled\" | \"sentinelOneDataInAnalyzerEnabled\" | \"sentinelOneManualHostActionsEnabled\" | \"jsonPrebuiltRulesDiffingEnabled\" | \"timelineEsqlTabDisabled\" | undefined" ], "path": "x-pack/plugins/security_solution/public/common/links/types.ts", "deprecated": false, @@ -1913,7 +1913,7 @@ "label": "experimentalFeatures", "description": [], "signature": [ - "{ readonly tGridEnabled: boolean; readonly tGridEventRenderedViewEnabled: boolean; readonly excludePoliciesInFilterEnabled: boolean; readonly kubernetesEnabled: boolean; readonly chartEmbeddablesEnabled: boolean; readonly donutChartEmbeddablesEnabled: boolean; readonly alertsPreviewChartEmbeddablesEnabled: boolean; readonly previewTelemetryUrlEnabled: boolean; readonly insightsRelatedAlertsByProcessAncestry: boolean; readonly extendedRuleExecutionLoggingEnabled: boolean; readonly assistantStreamingEnabled: boolean; readonly socTrendsEnabled: boolean; readonly responseActionsEnabled: boolean; readonly endpointResponseActionsEnabled: boolean; readonly responseActionUploadEnabled: boolean; readonly responseActionsSentinelOneV1Enabled: boolean; readonly alertsPageChartsEnabled: boolean; readonly alertTypeEnabled: boolean; readonly expandableFlyoutInCreateRuleEnabled: boolean; readonly alertsPageFiltersEnabled: boolean; readonly assistantModelEvaluation: boolean; readonly newUserDetailsFlyout: boolean; readonly riskScoringPersistence: boolean; readonly riskScoringRoutesEnabled: boolean; readonly esqlRulesDisabled: boolean; readonly protectionUpdatesEnabled: boolean; readonly disableTimelineSaveTour: boolean; readonly riskEnginePrivilegesRouteEnabled: boolean; readonly entityAnalyticsAssetCriticalityEnabled: boolean; readonly sentinelOneDataInAnalyzerEnabled: boolean; readonly sentinelOneManualHostActionsEnabled: boolean; readonly jsonPrebuiltRulesDiffingEnabled: boolean; readonly timelineEsqlTabDisabled: boolean; }" + "{ readonly tGridEnabled: boolean; readonly tGridEventRenderedViewEnabled: boolean; readonly excludePoliciesInFilterEnabled: boolean; readonly kubernetesEnabled: boolean; readonly chartEmbeddablesEnabled: boolean; readonly donutChartEmbeddablesEnabled: boolean; readonly alertsPreviewChartEmbeddablesEnabled: boolean; readonly previewTelemetryUrlEnabled: boolean; readonly insightsRelatedAlertsByProcessAncestry: boolean; readonly extendedRuleExecutionLoggingEnabled: boolean; readonly assistantStreamingEnabled: boolean; readonly socTrendsEnabled: boolean; readonly responseActionsEnabled: boolean; readonly endpointResponseActionsEnabled: boolean; readonly responseActionUploadEnabled: boolean; readonly responseActionsSentinelOneV1Enabled: boolean; readonly alertsPageChartsEnabled: boolean; readonly alertTypeEnabled: boolean; readonly expandableFlyoutInCreateRuleEnabled: boolean; readonly alertsPageFiltersEnabled: boolean; readonly assistantModelEvaluation: boolean; readonly newUserDetailsFlyout: boolean; readonly newHostDetailsFlyout: boolean; readonly riskScoringPersistence: boolean; readonly riskScoringRoutesEnabled: boolean; readonly esqlRulesDisabled: boolean; readonly protectionUpdatesEnabled: boolean; readonly disableTimelineSaveTour: boolean; readonly riskEnginePrivilegesRouteEnabled: boolean; readonly entityAnalyticsAssetCriticalityEnabled: boolean; readonly sentinelOneDataInAnalyzerEnabled: boolean; readonly sentinelOneManualHostActionsEnabled: boolean; readonly jsonPrebuiltRulesDiffingEnabled: boolean; readonly timelineEsqlTabDisabled: boolean; }" ], "path": "x-pack/plugins/security_solution/public/types.ts", "deprecated": false, @@ -3018,7 +3018,7 @@ "\nThe security solution generic experimental features" ], "signature": [ - "{ readonly tGridEnabled: boolean; readonly tGridEventRenderedViewEnabled: boolean; readonly excludePoliciesInFilterEnabled: boolean; readonly kubernetesEnabled: boolean; readonly chartEmbeddablesEnabled: boolean; readonly donutChartEmbeddablesEnabled: boolean; readonly alertsPreviewChartEmbeddablesEnabled: boolean; readonly previewTelemetryUrlEnabled: boolean; readonly insightsRelatedAlertsByProcessAncestry: boolean; readonly extendedRuleExecutionLoggingEnabled: boolean; readonly assistantStreamingEnabled: boolean; readonly socTrendsEnabled: boolean; readonly responseActionsEnabled: boolean; readonly endpointResponseActionsEnabled: boolean; readonly responseActionUploadEnabled: boolean; readonly responseActionsSentinelOneV1Enabled: boolean; readonly alertsPageChartsEnabled: boolean; readonly alertTypeEnabled: boolean; readonly expandableFlyoutInCreateRuleEnabled: boolean; readonly alertsPageFiltersEnabled: boolean; readonly assistantModelEvaluation: boolean; readonly newUserDetailsFlyout: boolean; readonly riskScoringPersistence: boolean; readonly riskScoringRoutesEnabled: boolean; readonly esqlRulesDisabled: boolean; readonly protectionUpdatesEnabled: boolean; readonly disableTimelineSaveTour: boolean; readonly riskEnginePrivilegesRouteEnabled: boolean; readonly entityAnalyticsAssetCriticalityEnabled: boolean; readonly sentinelOneDataInAnalyzerEnabled: boolean; readonly sentinelOneManualHostActionsEnabled: boolean; readonly jsonPrebuiltRulesDiffingEnabled: boolean; readonly timelineEsqlTabDisabled: boolean; }" + "{ readonly tGridEnabled: boolean; readonly tGridEventRenderedViewEnabled: boolean; readonly excludePoliciesInFilterEnabled: boolean; readonly kubernetesEnabled: boolean; readonly chartEmbeddablesEnabled: boolean; readonly donutChartEmbeddablesEnabled: boolean; readonly alertsPreviewChartEmbeddablesEnabled: boolean; readonly previewTelemetryUrlEnabled: boolean; readonly insightsRelatedAlertsByProcessAncestry: boolean; readonly extendedRuleExecutionLoggingEnabled: boolean; readonly assistantStreamingEnabled: boolean; readonly socTrendsEnabled: boolean; readonly responseActionsEnabled: boolean; readonly endpointResponseActionsEnabled: boolean; readonly responseActionUploadEnabled: boolean; readonly responseActionsSentinelOneV1Enabled: boolean; readonly alertsPageChartsEnabled: boolean; readonly alertTypeEnabled: boolean; readonly expandableFlyoutInCreateRuleEnabled: boolean; readonly alertsPageFiltersEnabled: boolean; readonly assistantModelEvaluation: boolean; readonly newUserDetailsFlyout: boolean; readonly newHostDetailsFlyout: boolean; readonly riskScoringPersistence: boolean; readonly riskScoringRoutesEnabled: boolean; readonly esqlRulesDisabled: boolean; readonly protectionUpdatesEnabled: boolean; readonly disableTimelineSaveTour: boolean; readonly riskEnginePrivilegesRouteEnabled: boolean; readonly entityAnalyticsAssetCriticalityEnabled: boolean; readonly sentinelOneDataInAnalyzerEnabled: boolean; readonly sentinelOneManualHostActionsEnabled: boolean; readonly jsonPrebuiltRulesDiffingEnabled: boolean; readonly timelineEsqlTabDisabled: boolean; }" ], "path": "x-pack/plugins/security_solution/server/plugin_contract.ts", "deprecated": false, @@ -3194,7 +3194,7 @@ "label": "ExperimentalFeatures", "description": [], "signature": [ - "{ readonly tGridEnabled: boolean; readonly tGridEventRenderedViewEnabled: boolean; readonly excludePoliciesInFilterEnabled: boolean; readonly kubernetesEnabled: boolean; readonly chartEmbeddablesEnabled: boolean; readonly donutChartEmbeddablesEnabled: boolean; readonly alertsPreviewChartEmbeddablesEnabled: boolean; readonly previewTelemetryUrlEnabled: boolean; readonly insightsRelatedAlertsByProcessAncestry: boolean; readonly extendedRuleExecutionLoggingEnabled: boolean; readonly assistantStreamingEnabled: boolean; readonly socTrendsEnabled: boolean; readonly responseActionsEnabled: boolean; readonly endpointResponseActionsEnabled: boolean; readonly responseActionUploadEnabled: boolean; readonly responseActionsSentinelOneV1Enabled: boolean; readonly alertsPageChartsEnabled: boolean; readonly alertTypeEnabled: boolean; readonly expandableFlyoutInCreateRuleEnabled: boolean; readonly alertsPageFiltersEnabled: boolean; readonly assistantModelEvaluation: boolean; readonly newUserDetailsFlyout: boolean; readonly riskScoringPersistence: boolean; readonly riskScoringRoutesEnabled: boolean; readonly esqlRulesDisabled: boolean; readonly protectionUpdatesEnabled: boolean; readonly disableTimelineSaveTour: boolean; readonly riskEnginePrivilegesRouteEnabled: boolean; readonly entityAnalyticsAssetCriticalityEnabled: boolean; readonly sentinelOneDataInAnalyzerEnabled: boolean; readonly sentinelOneManualHostActionsEnabled: boolean; readonly jsonPrebuiltRulesDiffingEnabled: boolean; readonly timelineEsqlTabDisabled: boolean; }" + "{ readonly tGridEnabled: boolean; readonly tGridEventRenderedViewEnabled: boolean; readonly excludePoliciesInFilterEnabled: boolean; readonly kubernetesEnabled: boolean; readonly chartEmbeddablesEnabled: boolean; readonly donutChartEmbeddablesEnabled: boolean; readonly alertsPreviewChartEmbeddablesEnabled: boolean; readonly previewTelemetryUrlEnabled: boolean; readonly insightsRelatedAlertsByProcessAncestry: boolean; readonly extendedRuleExecutionLoggingEnabled: boolean; readonly assistantStreamingEnabled: boolean; readonly socTrendsEnabled: boolean; readonly responseActionsEnabled: boolean; readonly endpointResponseActionsEnabled: boolean; readonly responseActionUploadEnabled: boolean; readonly responseActionsSentinelOneV1Enabled: boolean; readonly alertsPageChartsEnabled: boolean; readonly alertTypeEnabled: boolean; readonly expandableFlyoutInCreateRuleEnabled: boolean; readonly alertsPageFiltersEnabled: boolean; readonly assistantModelEvaluation: boolean; readonly newUserDetailsFlyout: boolean; readonly newHostDetailsFlyout: boolean; readonly riskScoringPersistence: boolean; readonly riskScoringRoutesEnabled: boolean; readonly esqlRulesDisabled: boolean; readonly protectionUpdatesEnabled: boolean; readonly disableTimelineSaveTour: boolean; readonly riskEnginePrivilegesRouteEnabled: boolean; readonly entityAnalyticsAssetCriticalityEnabled: boolean; readonly sentinelOneDataInAnalyzerEnabled: boolean; readonly sentinelOneManualHostActionsEnabled: boolean; readonly jsonPrebuiltRulesDiffingEnabled: boolean; readonly timelineEsqlTabDisabled: boolean; }" ], "path": "x-pack/plugins/security_solution/common/experimental_features.ts", "deprecated": false, @@ -3243,7 +3243,7 @@ "\nA list of allowed values that can be used in `xpack.securitySolution.enableExperimental`.\nThis object is then used to validate and parse the value entered." ], "signature": [ - "{ readonly tGridEnabled: boolean; readonly tGridEventRenderedViewEnabled: boolean; readonly excludePoliciesInFilterEnabled: boolean; readonly kubernetesEnabled: boolean; readonly chartEmbeddablesEnabled: boolean; readonly donutChartEmbeddablesEnabled: boolean; readonly alertsPreviewChartEmbeddablesEnabled: boolean; readonly previewTelemetryUrlEnabled: boolean; readonly insightsRelatedAlertsByProcessAncestry: boolean; readonly extendedRuleExecutionLoggingEnabled: boolean; readonly assistantStreamingEnabled: boolean; readonly socTrendsEnabled: boolean; readonly responseActionsEnabled: boolean; readonly endpointResponseActionsEnabled: boolean; readonly responseActionUploadEnabled: boolean; readonly responseActionsSentinelOneV1Enabled: boolean; readonly alertsPageChartsEnabled: boolean; readonly alertTypeEnabled: boolean; readonly expandableFlyoutInCreateRuleEnabled: boolean; readonly alertsPageFiltersEnabled: boolean; readonly assistantModelEvaluation: boolean; readonly newUserDetailsFlyout: boolean; readonly riskScoringPersistence: boolean; readonly riskScoringRoutesEnabled: boolean; readonly esqlRulesDisabled: boolean; readonly protectionUpdatesEnabled: boolean; readonly disableTimelineSaveTour: boolean; readonly riskEnginePrivilegesRouteEnabled: boolean; readonly entityAnalyticsAssetCriticalityEnabled: boolean; readonly sentinelOneDataInAnalyzerEnabled: boolean; readonly sentinelOneManualHostActionsEnabled: boolean; readonly jsonPrebuiltRulesDiffingEnabled: boolean; readonly timelineEsqlTabDisabled: boolean; }" + "{ readonly tGridEnabled: boolean; readonly tGridEventRenderedViewEnabled: boolean; readonly excludePoliciesInFilterEnabled: boolean; readonly kubernetesEnabled: boolean; readonly chartEmbeddablesEnabled: boolean; readonly donutChartEmbeddablesEnabled: boolean; readonly alertsPreviewChartEmbeddablesEnabled: boolean; readonly previewTelemetryUrlEnabled: boolean; readonly insightsRelatedAlertsByProcessAncestry: boolean; readonly extendedRuleExecutionLoggingEnabled: boolean; readonly assistantStreamingEnabled: boolean; readonly socTrendsEnabled: boolean; readonly responseActionsEnabled: boolean; readonly endpointResponseActionsEnabled: boolean; readonly responseActionUploadEnabled: boolean; readonly responseActionsSentinelOneV1Enabled: boolean; readonly alertsPageChartsEnabled: boolean; readonly alertTypeEnabled: boolean; readonly expandableFlyoutInCreateRuleEnabled: boolean; readonly alertsPageFiltersEnabled: boolean; readonly assistantModelEvaluation: boolean; readonly newUserDetailsFlyout: boolean; readonly newHostDetailsFlyout: boolean; readonly riskScoringPersistence: boolean; readonly riskScoringRoutesEnabled: boolean; readonly esqlRulesDisabled: boolean; readonly protectionUpdatesEnabled: boolean; readonly disableTimelineSaveTour: boolean; readonly riskEnginePrivilegesRouteEnabled: boolean; readonly entityAnalyticsAssetCriticalityEnabled: boolean; readonly sentinelOneDataInAnalyzerEnabled: boolean; readonly sentinelOneManualHostActionsEnabled: boolean; readonly jsonPrebuiltRulesDiffingEnabled: boolean; readonly timelineEsqlTabDisabled: boolean; }" ], "path": "x-pack/plugins/security_solution/common/experimental_features.ts", "deprecated": false, diff --git a/api_docs/security_solution.mdx b/api_docs/security_solution.mdx index 8eef95d5129c..ba6c70b16455 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'securitySolution'] --- import securitySolutionObj from './security_solution.devdocs.json'; diff --git a/api_docs/security_solution_ess.mdx b/api_docs/security_solution_ess.mdx index ffa55031142c..25f68ee7e551 100644 --- a/api_docs/security_solution_ess.mdx +++ b/api_docs/security_solution_ess.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/securitySolutionEss title: "securitySolutionEss" image: https://source.unsplash.com/400x175/?github description: API docs for the securitySolutionEss plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'securitySolutionEss'] --- import securitySolutionEssObj from './security_solution_ess.devdocs.json'; diff --git a/api_docs/security_solution_serverless.mdx b/api_docs/security_solution_serverless.mdx index 1424cf991355..c3e1d15be89e 100644 --- a/api_docs/security_solution_serverless.mdx +++ b/api_docs/security_solution_serverless.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/securitySolutionServerless title: "securitySolutionServerless" image: https://source.unsplash.com/400x175/?github description: API docs for the securitySolutionServerless plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'securitySolutionServerless'] --- import securitySolutionServerlessObj from './security_solution_serverless.devdocs.json'; diff --git a/api_docs/serverless.mdx b/api_docs/serverless.mdx index 2e7a6aadd704..077333a053df 100644 --- a/api_docs/serverless.mdx +++ b/api_docs/serverless.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/serverless title: "serverless" image: https://source.unsplash.com/400x175/?github description: API docs for the serverless plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'serverless'] --- import serverlessObj from './serverless.devdocs.json'; diff --git a/api_docs/serverless_observability.mdx b/api_docs/serverless_observability.mdx index 1bf96e28966e..534e533edab5 100644 --- a/api_docs/serverless_observability.mdx +++ b/api_docs/serverless_observability.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/serverlessObservability title: "serverlessObservability" image: https://source.unsplash.com/400x175/?github description: API docs for the serverlessObservability plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'serverlessObservability'] --- import serverlessObservabilityObj from './serverless_observability.devdocs.json'; diff --git a/api_docs/serverless_search.mdx b/api_docs/serverless_search.mdx index fc4b453d0c79..102604d95ab7 100644 --- a/api_docs/serverless_search.mdx +++ b/api_docs/serverless_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/serverlessSearch title: "serverlessSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the serverlessSearch plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'serverlessSearch'] --- import serverlessSearchObj from './serverless_search.devdocs.json'; diff --git a/api_docs/session_view.mdx b/api_docs/session_view.mdx index 2f8c9f437ccb..763ca419fed8 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'sessionView'] --- import sessionViewObj from './session_view.devdocs.json'; diff --git a/api_docs/share.mdx b/api_docs/share.mdx index a0d28e5a26b0..339d6c508087 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: 2024-01-04 +date: 2024-01-05 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 dba4bc4e7e8b..21f5f0258bc2 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: 2024-01-04 +date: 2024-01-05 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 f638dca83f95..4c7128a9930d 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: 2024-01-04 +date: 2024-01-05 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 88a3c55dc67b..27324a3195cd 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: 2024-01-04 +date: 2024-01-05 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 86f2c02b5155..fad3a15191dc 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: 2024-01-04 +date: 2024-01-05 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 56924fd41320..b73de4d4a8f8 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'taskManager'] --- import taskManagerObj from './task_manager.devdocs.json'; diff --git a/api_docs/telemetry.mdx b/api_docs/telemetry.mdx index 4fad05863370..adbb8316668a 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetry'] --- import telemetryObj from './telemetry.devdocs.json'; diff --git a/api_docs/telemetry_collection_manager.mdx b/api_docs/telemetry_collection_manager.mdx index a690d153a545..dac5b90d56c3 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: 2024-01-04 +date: 2024-01-05 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 1a6dadc567f6..d4800130c11e 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: 2024-01-04 +date: 2024-01-05 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 d280cb1dbe2d..b802885ce63c 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryManagementSection'] --- import telemetryManagementSectionObj from './telemetry_management_section.devdocs.json'; diff --git a/api_docs/text_based_languages.mdx b/api_docs/text_based_languages.mdx index cc12aff43841..90f4c737ef5d 100644 --- a/api_docs/text_based_languages.mdx +++ b/api_docs/text_based_languages.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/textBasedLanguages title: "textBasedLanguages" image: https://source.unsplash.com/400x175/?github description: API docs for the textBasedLanguages plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'textBasedLanguages'] --- import textBasedLanguagesObj from './text_based_languages.devdocs.json'; diff --git a/api_docs/threat_intelligence.mdx b/api_docs/threat_intelligence.mdx index b2400c6a5605..e65d055c5015 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: 2024-01-04 +date: 2024-01-05 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 089062e66831..623a249277ff 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: 2024-01-04 +date: 2024-01-05 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 e1380a11e5fb..c8d87b3d53b1 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'transform'] --- import transformObj from './transform.devdocs.json'; diff --git a/api_docs/triggers_actions_ui.mdx b/api_docs/triggers_actions_ui.mdx index 34d9b1ae953b..a88344d51d8f 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'triggersActionsUi'] --- import triggersActionsUiObj from './triggers_actions_ui.devdocs.json'; diff --git a/api_docs/ui_actions.mdx b/api_docs/ui_actions.mdx index 14ec4d033c75..0588c01b591f 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: 2024-01-04 +date: 2024-01-05 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 06ed1525dd17..be083bd8db8b 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'uiActionsEnhanced'] --- import uiActionsEnhancedObj from './ui_actions_enhanced.devdocs.json'; diff --git a/api_docs/unified_doc_viewer.mdx b/api_docs/unified_doc_viewer.mdx index 9a912ac1027c..0bd5ea3e3204 100644 --- a/api_docs/unified_doc_viewer.mdx +++ b/api_docs/unified_doc_viewer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedDocViewer title: "unifiedDocViewer" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedDocViewer plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedDocViewer'] --- import unifiedDocViewerObj from './unified_doc_viewer.devdocs.json'; diff --git a/api_docs/unified_histogram.mdx b/api_docs/unified_histogram.mdx index 9bec81e68ad5..bcbef43c6e33 100644 --- a/api_docs/unified_histogram.mdx +++ b/api_docs/unified_histogram.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedHistogram title: "unifiedHistogram" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedHistogram plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedHistogram'] --- import unifiedHistogramObj from './unified_histogram.devdocs.json'; diff --git a/api_docs/unified_search.mdx b/api_docs/unified_search.mdx index b98e1e61aa27..3b4027f728d8 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: 2024-01-04 +date: 2024-01-05 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 1d7c6f9317df..5d9fe8a04f0c 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedSearch.autocomplete'] --- import unifiedSearchAutocompleteObj from './unified_search_autocomplete.devdocs.json'; diff --git a/api_docs/uptime.mdx b/api_docs/uptime.mdx index 92ee3d44518d..779a7b84fe52 100644 --- a/api_docs/uptime.mdx +++ b/api_docs/uptime.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/uptime title: "uptime" image: https://source.unsplash.com/400x175/?github description: API docs for the uptime plugin -date: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'uptime'] --- import uptimeObj from './uptime.devdocs.json'; diff --git a/api_docs/url_forwarding.mdx b/api_docs/url_forwarding.mdx index d7d4d5e1139d..5a91922a20ba 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'urlForwarding'] --- import urlForwardingObj from './url_forwarding.devdocs.json'; diff --git a/api_docs/usage_collection.mdx b/api_docs/usage_collection.mdx index 5672f86c23a0..1938ebf53a75 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: 2024-01-04 +date: 2024-01-05 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 024cb7178668..669c55c297b0 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: 2024-01-04 +date: 2024-01-05 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 18110a2986cd..65878ec3d271 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: 2024-01-04 +date: 2024-01-05 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 6d093cb710b7..c89a81f47259 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: 2024-01-04 +date: 2024-01-05 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 1320fe72ef08..5390a71f9dd2 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: 2024-01-04 +date: 2024-01-05 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 19d7fa2ba0e2..4f11ecdc9ace 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: 2024-01-04 +date: 2024-01-05 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 358e0aa109bf..888f28ef64f7 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: 2024-01-04 +date: 2024-01-05 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 8e70657f3210..dcd8f9dc2e15 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: 2024-01-04 +date: 2024-01-05 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 8df27109a130..9df8977c8abe 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: 2024-01-04 +date: 2024-01-05 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 0c5734a0dbf2..b675520306dd 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: 2024-01-04 +date: 2024-01-05 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 4e0db374f948..e75e83e13f70 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: 2024-01-04 +date: 2024-01-05 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 193a6c9b0e2c..cf476fb5dc48 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeXy'] --- import visTypeXyObj from './vis_type_xy.devdocs.json'; diff --git a/api_docs/visualizations.mdx b/api_docs/visualizations.mdx index 7232243e38c1..22233095d28e 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: 2024-01-04 +date: 2024-01-05 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visualizations'] --- import visualizationsObj from './visualizations.devdocs.json'; From 35514f7fec7119f3d1dc60ab804776c867d6ec29 Mon Sep 17 00:00:00 2001 From: Julia Bardi <90178898+juliaElastic@users.noreply.github.com> Date: Fri, 5 Jan 2024 09:19:51 +0100 Subject: [PATCH 25/57] [Fleet] fix kafka ssl key secret update (#174261) ## Summary Closes https://github.com/elastic/kibana/issues/174227 Fix wrong field used for kafka ssl key secret input which broke ssl key on kafka output update. To verify: - create a kafka output with Authentication: SSL, fill out cert and key - verify that the value of the key is stored as secret in `.fleet-secrets` - update kafka output (e.g. change name) - verify that the ssl key is unchanged image --- .../settings/components/edit_output_flyout/use_output_form.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/edit_output_flyout/use_output_form.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/edit_output_flyout/use_output_form.tsx index a1d0fb484b44..81753d9c56c3 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/edit_output_flyout/use_output_form.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/edit_output_flyout/use_output_form.tsx @@ -399,7 +399,7 @@ export function useOutputForm(onSucess: () => void, output?: Output) { ); const kafkaSslKeySecretInput = useSecretInput( - kafkaOutput?.ssl?.certificate, + kafkaOutput?.secrets?.ssl?.key, kafkaAuthMethodInput.value === kafkaAuthType.Ssl ? validateSSLKeySecret : undefined, isSSLEditable ); From 702b207d2d93019e9efa3f00fdd48c9328c2f893 Mon Sep 17 00:00:00 2001 From: Maryam Saeidi Date: Fri, 5 Jan 2024 11:30:10 +0100 Subject: [PATCH 26/57] [Custom threshold] Add log rate analysis to the alert details page for one document count aggregation (#174031) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes #171163 ## Summary This PR adds log rate analysis to the alert details page for one document count aggregation if the user has a license above platinum. This is a similar implementation in the log threshold alert details page. ![image](https://github.com/elastic/kibana/assets/12370520/29cd29bf-ead5-4574-8121-739d3ed11fe7) ## 🧪 How to test? - Create a Custom threshold rule with only one document count aggregation - Optional filter, document count aggregation filter, and group by information will be applied to the query of this component. - Go to the alert details page, you should see the log rate analysis on this page --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../common/custom_threshold_rule/types.ts | 5 + .../utils/get_interval_in_seconds.test.ts | 28 +++ .../common/utils/get_interval_in_seconds.ts | 32 +++ x-pack/plugins/observability/kibana.jsonc | 1 + .../alert_search_bar/alert_search_bar.tsx | 22 +- .../alert_details_app_section.test.tsx.snap | 0 .../alert_details_app_section.test.tsx | 8 +- .../alert_details_app_section.tsx | 28 ++- .../log_rate_analysis_query.test.ts.snap | 222 ++++++++++++++++ .../helpers/get_initial_analysis_start.ts | 58 +++++ .../helpers/log_rate_analysis_query.test.ts | 98 ++++++++ .../helpers/log_rate_analysis_query.ts | 62 +++++ .../log_rate_analysis.tsx | 238 ++++++++++++++++++ .../mocks/custom_threshold_rule.ts | 5 +- .../observability/public/hooks/use_license.ts | 4 +- .../public/pages/overview/overview.tsx | 18 +- x-pack/plugins/observability/public/plugin.ts | 3 + .../register_observability_rule_types.ts | 5 +- .../build_es_query/build_es_query.test.ts | 2 +- .../utils/build_es_query/build_es_query.ts | 14 +- .../custom_threshold/lib/evaluate_rule.ts | 3 +- .../lib/rules/custom_threshold/utils.ts | 26 -- x-pack/plugins/observability/tsconfig.json | 4 +- 23 files changed, 816 insertions(+), 70 deletions(-) create mode 100644 x-pack/plugins/observability/common/utils/get_interval_in_seconds.test.ts create mode 100644 x-pack/plugins/observability/common/utils/get_interval_in_seconds.ts rename x-pack/plugins/observability/public/components/custom_threshold/components/{ => alert_details_app_section}/__snapshots__/alert_details_app_section.test.tsx.snap (100%) rename x-pack/plugins/observability/public/components/custom_threshold/components/{ => alert_details_app_section}/alert_details_app_section.test.tsx (94%) rename x-pack/plugins/observability/public/components/custom_threshold/components/{ => alert_details_app_section}/alert_details_app_section.tsx (86%) create mode 100644 x-pack/plugins/observability/public/components/custom_threshold/components/alert_details_app_section/helpers/__snapshots__/log_rate_analysis_query.test.ts.snap create mode 100644 x-pack/plugins/observability/public/components/custom_threshold/components/alert_details_app_section/helpers/get_initial_analysis_start.ts create mode 100644 x-pack/plugins/observability/public/components/custom_threshold/components/alert_details_app_section/helpers/log_rate_analysis_query.test.ts create mode 100644 x-pack/plugins/observability/public/components/custom_threshold/components/alert_details_app_section/helpers/log_rate_analysis_query.ts create mode 100644 x-pack/plugins/observability/public/components/custom_threshold/components/alert_details_app_section/log_rate_analysis.tsx diff --git a/x-pack/plugins/observability/common/custom_threshold_rule/types.ts b/x-pack/plugins/observability/common/custom_threshold_rule/types.ts index 7668e19dc390..67849df1b59d 100644 --- a/x-pack/plugins/observability/common/custom_threshold_rule/types.ts +++ b/x-pack/plugins/observability/common/custom_threshold_rule/types.ts @@ -107,6 +107,11 @@ export enum InfraFormatterType { percent = 'percent', } +// Custom threshold alert types + +// Alert fields['kibana.alert.group] type +export type GroupBy = Array<{ field: string; value: string }>; + /* * Utils * diff --git a/x-pack/plugins/observability/common/utils/get_interval_in_seconds.test.ts b/x-pack/plugins/observability/common/utils/get_interval_in_seconds.test.ts new file mode 100644 index 000000000000..f2654a224ae8 --- /dev/null +++ b/x-pack/plugins/observability/common/utils/get_interval_in_seconds.test.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 { getIntervalInSeconds } from './get_interval_in_seconds'; + +describe('getIntervalInSeconds', () => { + const testData = [ + { interval: '5ms', result: 0.005 }, + { interval: '70s', result: 70 }, + { interval: '25m', result: 1500 }, + { interval: '10h', result: 36000 }, + { interval: '3d', result: 259200 }, + { interval: '1w', result: 604800 }, + { interval: '1y', result: 30758400 }, + ]; + + it.each(testData)('getIntervalInSeconds($interval) = $result', ({ interval, result }) => { + expect(getIntervalInSeconds(interval)).toBe(result); + }); + + it('Throws error if interval is not valid', () => { + expect(() => getIntervalInSeconds('invalid')).toThrow('Invalid interval string format.'); + }); +}); diff --git a/x-pack/plugins/observability/common/utils/get_interval_in_seconds.ts b/x-pack/plugins/observability/common/utils/get_interval_in_seconds.ts new file mode 100644 index 000000000000..6ebdbb83bdc6 --- /dev/null +++ b/x-pack/plugins/observability/common/utils/get_interval_in_seconds.ts @@ -0,0 +1,32 @@ +/* + * 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 intervalUnits = ['y', 'M', 'w', 'd', 'h', 'm', 's', 'ms']; +const INTERVAL_STRING_RE = new RegExp('^([0-9\\.]*)\\s*(' + intervalUnits.join('|') + ')$'); + +interface UnitsToSeconds { + [unit: string]: number; +} + +const units: UnitsToSeconds = { + ms: 0.001, + s: 1, + m: 60, + h: 3600, + d: 86400, + w: 86400 * 7, + M: 86400 * 30, + y: 86400 * 356, +}; + +export const getIntervalInSeconds = (interval: string): number => { + const matches = interval.match(INTERVAL_STRING_RE); + if (matches) { + return parseFloat(matches[1]) * units[matches[2]]; + } + throw new Error('Invalid interval string format.'); +}; diff --git a/x-pack/plugins/observability/kibana.jsonc b/x-pack/plugins/observability/kibana.jsonc index 526c283c0f0b..c7fdb22b5f79 100644 --- a/x-pack/plugins/observability/kibana.jsonc +++ b/x-pack/plugins/observability/kibana.jsonc @@ -20,6 +20,7 @@ "dataViews", "dataViewEditor", "embeddable", + "fieldFormats", "uiActions", "presentationUtil", "exploratoryView", diff --git a/x-pack/plugins/observability/public/components/alert_search_bar/alert_search_bar.tsx b/x-pack/plugins/observability/public/components/alert_search_bar/alert_search_bar.tsx index d27e32970f2f..ff69c8e2ff2c 100644 --- a/x-pack/plugins/observability/public/components/alert_search_bar/alert_search_bar.tsx +++ b/x-pack/plugins/observability/public/components/alert_search_bar/alert_search_bar.tsx @@ -47,15 +47,15 @@ export function ObservabilityAlertSearchBar({ (alertStatus: AlertStatus) => { try { onEsQueryChange( - buildEsQuery( - { + buildEsQuery({ + timeRange: { to: rangeTo, from: rangeFrom, }, kuery, - [...getAlertStatusQuery(alertStatus), ...defaultSearchQueries], - getEsQueryConfig(uiSettings) - ) + queries: [...getAlertStatusQuery(alertStatus), ...defaultSearchQueries], + config: getEsQueryConfig(uiSettings), + }) ); } catch (error) { toasts.addError(error, { @@ -89,15 +89,15 @@ export function ObservabilityAlertSearchBar({ ({ dateRange, query }) => { try { // First try to create es query to make sure query is valid, then save it in state - const esQuery = buildEsQuery( - { + const esQuery = buildEsQuery({ + timeRange: { to: dateRange.to, from: dateRange.from, }, - query, - [...getAlertStatusQuery(status), ...defaultSearchQueries], - getEsQueryConfig(uiSettings) - ); + kuery: query, + queries: [...getAlertStatusQuery(status), ...defaultSearchQueries], + config: getEsQueryConfig(uiSettings), + }); if (query) onKueryChange(query); timeFilterService.setTime(dateRange); onRangeFromChange(dateRange.from); diff --git a/x-pack/plugins/observability/public/components/custom_threshold/components/__snapshots__/alert_details_app_section.test.tsx.snap b/x-pack/plugins/observability/public/components/custom_threshold/components/alert_details_app_section/__snapshots__/alert_details_app_section.test.tsx.snap similarity index 100% rename from x-pack/plugins/observability/public/components/custom_threshold/components/__snapshots__/alert_details_app_section.test.tsx.snap rename to x-pack/plugins/observability/public/components/custom_threshold/components/alert_details_app_section/__snapshots__/alert_details_app_section.test.tsx.snap diff --git a/x-pack/plugins/observability/public/components/custom_threshold/components/alert_details_app_section.test.tsx b/x-pack/plugins/observability/public/components/custom_threshold/components/alert_details_app_section/alert_details_app_section.test.tsx similarity index 94% rename from x-pack/plugins/observability/public/components/custom_threshold/components/alert_details_app_section.test.tsx rename to x-pack/plugins/observability/public/components/custom_threshold/components/alert_details_app_section/alert_details_app_section.test.tsx index 8747558251da..c623d9aa1504 100644 --- a/x-pack/plugins/observability/public/components/custom_threshold/components/alert_details_app_section.test.tsx +++ b/x-pack/plugins/observability/public/components/custom_threshold/components/alert_details_app_section/alert_details_app_section.test.tsx @@ -15,9 +15,9 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { buildCustomThresholdAlert, buildCustomThresholdRule, -} from '../mocks/custom_threshold_rule'; +} from '../../mocks/custom_threshold_rule'; import AlertDetailsAppSection from './alert_details_app_section'; -import { ExpressionChart } from './expression_chart'; +import { ExpressionChart } from '../expression_chart'; const mockedChartStartContract = chartPluginMock.createStartContract(); @@ -33,11 +33,11 @@ jest.mock('@kbn/observability-get-padded-alert-time-range-util', () => ({ }), })); -jest.mock('./expression_chart', () => ({ +jest.mock('../expression_chart', () => ({ ExpressionChart: jest.fn(() =>
    ), })); -jest.mock('../../../utils/kibana_react', () => ({ +jest.mock('../../../../utils/kibana_react', () => ({ useKibana: () => ({ services: { ...mockCoreMock.createStart(), diff --git a/x-pack/plugins/observability/public/components/custom_threshold/components/alert_details_app_section.tsx b/x-pack/plugins/observability/public/components/custom_threshold/components/alert_details_app_section/alert_details_app_section.tsx similarity index 86% rename from x-pack/plugins/observability/public/components/custom_threshold/components/alert_details_app_section.tsx rename to x-pack/plugins/observability/public/components/custom_threshold/components/alert_details_app_section/alert_details_app_section.tsx index ce9a651a7a1e..3c95f0d6677b 100644 --- a/x-pack/plugins/observability/public/components/custom_threshold/components/alert_details_app_section.tsx +++ b/x-pack/plugins/observability/public/components/custom_threshold/components/alert_details_app_section/alert_details_app_section.tsx @@ -25,15 +25,16 @@ import { Rule, RuleTypeParams } from '@kbn/alerting-plugin/common'; import { AlertAnnotation, AlertActiveTimeRangeAnnotation } from '@kbn/observability-alert-details'; import { getPaddedAlertTimeRange } from '@kbn/observability-get-padded-alert-time-range-util'; import { DataView } from '@kbn/data-views-plugin/common'; -import { MetricsExplorerChartType } from '../../../../common/custom_threshold_rule/types'; -import { useKibana } from '../../../utils/kibana_react'; -import { metricValueFormatter } from '../../../../common/custom_threshold_rule/metric_value_formatter'; -import { AlertSummaryField, TopAlert } from '../../..'; - -import { ExpressionChart } from './expression_chart'; -import { TIME_LABELS } from './criterion_preview_chart/criterion_preview_chart'; -import { Threshold } from './custom_threshold'; -import { AlertParams, CustomThresholdRuleTypeParams } from '../types'; +import { MetricsExplorerChartType } from '../../../../../common/custom_threshold_rule/types'; +import { useLicense } from '../../../../hooks/use_license'; +import { useKibana } from '../../../../utils/kibana_react'; +import { metricValueFormatter } from '../../../../../common/custom_threshold_rule/metric_value_formatter'; +import { AlertSummaryField, TopAlert } from '../../../..'; +import { AlertParams, CustomThresholdRuleTypeParams } from '../../types'; +import { ExpressionChart } from '../expression_chart'; +import { TIME_LABELS } from '../criterion_preview_chart/criterion_preview_chart'; +import { Threshold } from '../custom_threshold'; +import { LogRateAnalysis } from './log_rate_analysis'; // TODO Use a generic props for app sections https://github.com/elastic/kibana/issues/152690 export type CustomThresholdRule = Rule; @@ -57,8 +58,11 @@ export default function AlertDetailsAppSection({ ruleLink, setAlertSummaryFields, }: AppSectionProps) { - const { uiSettings, charts, data } = useKibana().services; + const services = useKibana().services; + const { uiSettings, charts, data } = services; const { euiTheme } = useEuiTheme(); + const { hasAtLeast } = useLicense(); + const hasLogRateAnalysisLicense = hasAtLeast('platinum'); const [dataView, setDataView] = useState(); const [, setDataViewError] = useState(); const ruleParams = rule.params as RuleTypeParams & AlertParams; @@ -83,6 +87,7 @@ export default function AlertDetailsAppSection({ key={ALERT_TIME_RANGE_ANNOTATION_ID} />, ]; + useEffect(() => { setAlertSummaryFields([ { @@ -181,6 +186,9 @@ export default function AlertDetailsAppSection({ ))} + {hasLogRateAnalysisLicense && ( + + )} ) : null; diff --git a/x-pack/plugins/observability/public/components/custom_threshold/components/alert_details_app_section/helpers/__snapshots__/log_rate_analysis_query.test.ts.snap b/x-pack/plugins/observability/public/components/custom_threshold/components/alert_details_app_section/helpers/__snapshots__/log_rate_analysis_query.test.ts.snap new file mode 100644 index 000000000000..9a9eb4122422 --- /dev/null +++ b/x-pack/plugins/observability/public/components/custom_threshold/components/alert_details_app_section/helpers/__snapshots__/log_rate_analysis_query.test.ts.snap @@ -0,0 +1,222 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`buildEsQuery should generate correct es query for rule with multiple metrics 1`] = `undefined`; + +exports[`buildEsQuery should generate correct es query for rule with optional filer, count filter and WITHOUT group by 1`] = ` +Object { + "bool": Object { + "filter": Array [ + Object { + "bool": Object { + "filter": Array [ + Object { + "bool": Object { + "minimum_should_match": 1, + "should": Array [ + Object { + "match": Object { + "optionalFilter": "container-1", + }, + }, + ], + }, + }, + Object { + "bool": Object { + "minimum_should_match": 1, + "should": Array [ + Object { + "bool": Object { + "minimum_should_match": 1, + "should": Array [ + Object { + "match": Object { + "host.name": "host-1", + }, + }, + ], + }, + }, + Object { + "bool": Object { + "minimum_should_match": 1, + "should": Array [ + Object { + "match": Object { + "host.name": "host-2", + }, + }, + ], + }, + }, + ], + }, + }, + ], + }, + }, + ], + "must": Array [], + "must_not": Array [], + "should": Array [], + }, +} +`; + +exports[`buildEsQuery should generate correct es query for rule with optional filer, count filter and group by 1`] = ` +Object { + "bool": Object { + "filter": Array [ + Object { + "bool": Object { + "filter": Array [ + Object { + "bool": Object { + "minimum_should_match": 1, + "should": Array [ + Object { + "match": Object { + "optionalFilter": "container-1", + }, + }, + ], + }, + }, + Object { + "bool": Object { + "minimum_should_match": 1, + "should": Array [ + Object { + "bool": Object { + "minimum_should_match": 1, + "should": Array [ + Object { + "match": Object { + "host.name": "host-1", + }, + }, + ], + }, + }, + Object { + "bool": Object { + "minimum_should_match": 1, + "should": Array [ + Object { + "match": Object { + "host.name": "host-2", + }, + }, + ], + }, + }, + ], + }, + }, + Object { + "bool": Object { + "minimum_should_match": 1, + "should": Array [ + Object { + "match": Object { + "groupByField": "groupByValue", + }, + }, + ], + }, + }, + ], + }, + }, + ], + "must": Array [], + "must_not": Array [], + "should": Array [], + }, +} +`; + +exports[`buildEsQuery should generate correct es query for rule with optional filer, count filter and multiple group by 1`] = ` +Object { + "bool": Object { + "filter": Array [ + Object { + "bool": Object { + "filter": Array [ + Object { + "bool": Object { + "minimum_should_match": 1, + "should": Array [ + Object { + "match": Object { + "optionalFilter": "container-1", + }, + }, + ], + }, + }, + Object { + "bool": Object { + "minimum_should_match": 1, + "should": Array [ + Object { + "bool": Object { + "minimum_should_match": 1, + "should": Array [ + Object { + "match": Object { + "host.name": "host-1", + }, + }, + ], + }, + }, + Object { + "bool": Object { + "minimum_should_match": 1, + "should": Array [ + Object { + "match": Object { + "host.name": "host-2", + }, + }, + ], + }, + }, + ], + }, + }, + Object { + "bool": Object { + "minimum_should_match": 1, + "should": Array [ + Object { + "match": Object { + "groupByField": "groupByValue", + }, + }, + ], + }, + }, + Object { + "bool": Object { + "minimum_should_match": 1, + "should": Array [ + Object { + "match": Object { + "secondGroupByField": "secondGroupByValue", + }, + }, + ], + }, + }, + ], + }, + }, + ], + "must": Array [], + "must_not": Array [], + "should": Array [], + }, +} +`; diff --git a/x-pack/plugins/observability/public/components/custom_threshold/components/alert_details_app_section/helpers/get_initial_analysis_start.ts b/x-pack/plugins/observability/public/components/custom_threshold/components/alert_details_app_section/helpers/get_initial_analysis_start.ts new file mode 100644 index 000000000000..08bc835b7f43 --- /dev/null +++ b/x-pack/plugins/observability/public/components/custom_threshold/components/alert_details_app_section/helpers/get_initial_analysis_start.ts @@ -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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import moment, { Moment } from 'moment'; + +export interface GetInitialAnalysisStartArgs { + alertStart: Moment; + intervalFactor: number; + alertEnd?: Moment; +} + +export const getDeviationMax = ({ + alertStart, + intervalFactor, + alertEnd, +}: GetInitialAnalysisStartArgs) => { + if (alertEnd) { + return alertEnd + .clone() + .subtract(1 * intervalFactor, 'minutes') + .valueOf(); + } else if ( + alertStart + .clone() + .add(10 * intervalFactor, 'minutes') + .isAfter(moment(new Date())) + ) { + return moment(new Date()).valueOf(); + } else { + return alertStart + .clone() + .add(10 * intervalFactor, 'minutes') + .valueOf(); + } +}; + +export const getInitialAnalysisStart = (args: GetInitialAnalysisStartArgs) => { + const { alertStart, intervalFactor } = args; + return { + baselineMin: alertStart + .clone() + .subtract(13 * intervalFactor, 'minutes') + .valueOf(), + baselineMax: alertStart + .clone() + .subtract(2 * intervalFactor, 'minutes') + .valueOf(), + deviationMin: alertStart + .clone() + .subtract(1 * intervalFactor, 'minutes') + .valueOf(), + deviationMax: getDeviationMax(args), + }; +}; diff --git a/x-pack/plugins/observability/public/components/custom_threshold/components/alert_details_app_section/helpers/log_rate_analysis_query.test.ts b/x-pack/plugins/observability/public/components/custom_threshold/components/alert_details_app_section/helpers/log_rate_analysis_query.test.ts new file mode 100644 index 000000000000..8169816800e4 --- /dev/null +++ b/x-pack/plugins/observability/public/components/custom_threshold/components/alert_details_app_section/helpers/log_rate_analysis_query.test.ts @@ -0,0 +1,98 @@ +/* + * 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 { Aggregators, Comparator } from '../../../../../../common/custom_threshold_rule/types'; +import { CustomThresholdRuleTypeParams } from '../../../types'; +import { getLogRateAnalysisEQQuery } from './log_rate_analysis_query'; + +describe('buildEsQuery', () => { + const index = 'changedMockedIndex'; + const mockedParams: CustomThresholdRuleTypeParams = { + groupBy: ['host.hostname'], + searchConfiguration: { + index, + query: { query: 'optionalFilter: container-1', language: 'kuery' }, + }, + criteria: [ + { + metrics: [ + { + name: 'A', + aggType: Aggregators.COUNT, + filter: 'host.name: host-1 or host.name: host-2', + }, + ], + timeSize: 1, + timeUnit: 'm', + threshold: [90], + comparator: Comparator.GT, + }, + ], + }; + const mockedAlertWithMultipleGroups = { + fields: { + 'kibana.alert.group': [ + { + field: 'groupByField', + value: 'groupByValue', + }, + { + field: 'secondGroupByField', + value: 'secondGroupByValue', + }, + ], + }, + }; + const testData: Array<{ + title: string; + params: CustomThresholdRuleTypeParams; + alert: any; + }> = [ + { + title: 'rule with optional filer, count filter and group by', + params: mockedParams, + alert: { + fields: { + 'kibana.alert.group': [mockedAlertWithMultipleGroups.fields['kibana.alert.group'][0]], + }, + }, + }, + { + title: 'rule with optional filer, count filter and multiple group by', + params: mockedParams, + alert: mockedAlertWithMultipleGroups, + }, + { + title: 'rule with optional filer, count filter and WITHOUT group by', + params: mockedParams, + alert: {}, + }, + { + title: 'rule with multiple metrics', + params: { + ...mockedParams, + criteria: [ + { + metrics: [ + { name: 'A', aggType: Aggregators.COUNT, filter: 'host.name: host-1' }, + { name: 'B', aggType: Aggregators.AVERAGE, field: 'system.load.1' }, + ], + timeSize: 1, + timeUnit: 'm', + threshold: [90], + comparator: Comparator.GT, + }, + ], + }, + alert: {}, + }, + ]; + + test.each(testData)('should generate correct es query for $title', ({ alert, params }) => { + expect(getLogRateAnalysisEQQuery(alert, params)).toMatchSnapshot(); + }); +}); diff --git a/x-pack/plugins/observability/public/components/custom_threshold/components/alert_details_app_section/helpers/log_rate_analysis_query.ts b/x-pack/plugins/observability/public/components/custom_threshold/components/alert_details_app_section/helpers/log_rate_analysis_query.ts new file mode 100644 index 000000000000..b9eef4643802 --- /dev/null +++ b/x-pack/plugins/observability/public/components/custom_threshold/components/alert_details_app_section/helpers/log_rate_analysis_query.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 { get } from 'lodash'; +import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types'; +import { Aggregators, GroupBy } from '../../../../../../common/custom_threshold_rule/types'; +import { buildEsQuery } from '../../../../../utils/build_es_query'; +import type { TopAlert } from '../../../../../typings/alerts'; +import type { CustomThresholdRuleTypeParams } from '../../../types'; +import type { CustomThresholdExpressionMetric } from '../../../../../../common/custom_threshold_rule/types'; + +const getKuery = ( + metrics: CustomThresholdExpressionMetric[], + filter?: string, + groupBy?: GroupBy +) => { + let query = ''; + const isOneCountConditionWithFilter = + metrics.length === 1 && metrics[0].aggType === 'count' && metrics[0].filter; + + if (filter && isOneCountConditionWithFilter) { + query = `(${filter}) and (${metrics[0].filter})`; + } else if (isOneCountConditionWithFilter) { + query = `(${metrics[0].filter!})`; + } else if (filter) { + query = `(${filter})`; + } + + if (groupBy) { + groupBy.forEach(({ field, value }) => { + query += ` and ${field}: ${value}`; + }); + } + + return query; +}; + +export const getLogRateAnalysisEQQuery = ( + alert: TopAlert>, + params: CustomThresholdRuleTypeParams +): QueryDslQueryContainer | undefined => { + // We only show log rate analysis for one condition with one count aggregation + if ( + params.criteria.length !== 1 || + params.criteria[0].metrics.length !== 1 || + params.criteria[0].metrics[0].aggType !== Aggregators.COUNT + ) { + return; + } + + const groupBy: GroupBy | undefined = get(alert, 'fields["kibana.alert.group"]'); + const optionalFilter: string | undefined = get(params.searchConfiguration, 'query.query'); + const boolQuery = buildEsQuery({ + kuery: getKuery(params.criteria[0].metrics, optionalFilter, groupBy), + }); + + return boolQuery; +}; diff --git a/x-pack/plugins/observability/public/components/custom_threshold/components/alert_details_app_section/log_rate_analysis.tsx b/x-pack/plugins/observability/public/components/custom_threshold/components/alert_details_app_section/log_rate_analysis.tsx new file mode 100644 index 000000000000..7578f0979907 --- /dev/null +++ b/x-pack/plugins/observability/public/components/custom_threshold/components/alert_details_app_section/log_rate_analysis.tsx @@ -0,0 +1,238 @@ +/* + * 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 { pick, orderBy } from 'lodash'; +import moment from 'moment'; +import React, { useEffect, useMemo, useState } from 'react'; +import { EuiFlexGroup, EuiFlexItem, EuiPanel, EuiTitle } from '@elastic/eui'; +import { + LOG_RATE_ANALYSIS_TYPE, + type LogRateAnalysisType, +} from '@kbn/aiops-utils/log_rate_analysis_type'; +import { LogRateAnalysisContent, type LogRateAnalysisResultsData } from '@kbn/aiops-plugin/public'; +import { Rule } from '@kbn/alerting-plugin/common'; +import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n-react'; +import { type Message, MessageRole } from '@kbn/observability-ai-assistant-plugin/public'; +import { ALERT_END } from '@kbn/rule-data-utils'; +import { CustomThresholdRuleTypeParams } from '../../types'; +import { TopAlert } from '../../../..'; +import { Color, colorTransformer } from '../../../../../common/custom_threshold_rule/color_palette'; +import { getLogRateAnalysisEQQuery } from './helpers/log_rate_analysis_query'; +import { getInitialAnalysisStart } from './helpers/get_initial_analysis_start'; + +export interface AlertDetailsLogRateAnalysisProps { + alert: TopAlert>; + dataView: any; + rule: Rule; + services: any; +} + +interface SignificantFieldValue { + field: string; + value: string | number; + docCount: number; + pValue: number | null; +} + +export function LogRateAnalysis({ + alert, + dataView, + rule, + services, +}: AlertDetailsLogRateAnalysisProps) { + const { + observabilityAIAssistant: { ObservabilityAIAssistantContextualInsight }, + } = services; + const [esSearchQuery, setEsSearchQuery] = useState(); + const [logRateAnalysisParams, setLogRateAnalysisParams] = useState< + | { logRateAnalysisType: LogRateAnalysisType; significantFieldValues: SignificantFieldValue[] } + | undefined + >(); + + useEffect(() => { + const esSearchRequest = getLogRateAnalysisEQQuery(alert, rule.params); + + if (esSearchRequest) { + setEsSearchQuery(esSearchRequest); + } + }, [alert, rule.params]); + + // Identify `intervalFactor` to adjust time ranges based on alert settings. + // The default time ranges for `initialAnalysisStart` are suitable for a `1m` lookback. + // If an alert would have a `5m` lookback, this would result in a factor of `5`. + const lookbackDuration = + alert.fields['kibana.alert.rule.parameters'] && + alert.fields['kibana.alert.rule.parameters'].timeSize && + alert.fields['kibana.alert.rule.parameters'].timeUnit + ? moment.duration( + alert.fields['kibana.alert.rule.parameters'].timeSize as number, + alert.fields['kibana.alert.rule.parameters'].timeUnit as any + ) + : moment.duration(1, 'm'); + const intervalFactor = Math.max(1, lookbackDuration.asSeconds() / 60); + + const alertStart = moment(alert.start); + const alertEnd = alert.fields[ALERT_END] ? moment(alert.fields[ALERT_END]) : undefined; + + const timeRange = { + min: alertStart.clone().subtract(15 * intervalFactor, 'minutes'), + max: alertEnd ? alertEnd.clone().add(1 * intervalFactor, 'minutes') : moment(new Date()), + }; + + const logRateAnalysisTitle = i18n.translate( + 'xpack.observability.customThreshold.alertDetails.logRateAnalysisTitle', + { + defaultMessage: 'Possible causes and remediations', + } + ); + + const onAnalysisCompleted = (analysisResults: LogRateAnalysisResultsData | undefined) => { + const significantFieldValues = orderBy( + analysisResults?.significantItems?.map((item) => ({ + field: item.fieldName, + value: item.fieldValue, + docCount: item.doc_count, + pValue: item.pValue, + })), + ['pValue', 'docCount'], + ['asc', 'asc'] + ).slice(0, 50); + + const logRateAnalysisType = analysisResults?.analysisType; + setLogRateAnalysisParams( + significantFieldValues && logRateAnalysisType + ? { logRateAnalysisType, significantFieldValues } + : undefined + ); + }; + + const messages = useMemo(() => { + const hasLogRateAnalysisParams = + logRateAnalysisParams && logRateAnalysisParams.significantFieldValues?.length > 0; + + if (!hasLogRateAnalysisParams) { + return undefined; + } + + const { logRateAnalysisType } = logRateAnalysisParams; + + const header = 'Field name,Field value,Doc count,p-value'; + const rows = logRateAnalysisParams.significantFieldValues + .map((item) => Object.values(item).join(',')) + .join('\n'); + + const content = `You are an observability expert using Elastic Observability Suite on call being consulted about a log threshold alert that got triggered by a ${logRateAnalysisType} in log messages. Your job is to take immediate action and proceed with both urgency and precision. + "Log Rate Analysis" is an AIOps feature that uses advanced statistical methods to identify reasons for increases and decreases in log rates. It makes it easy to find and investigate causes of unusual spikes or dips by using the analysis workflow view. + You are using "Log Rate Analysis" and ran the statistical analysis on the log messages which occured during the alert. + You received the following analysis results from "Log Rate Analysis" which list statistically significant co-occuring field/value combinations sorted from most significant (lower p-values) to least significant (higher p-values) that ${ + logRateAnalysisType === LOG_RATE_ANALYSIS_TYPE.SPIKE + ? 'contribute to the log rate spike' + : 'are less or not present in the log rate dip' + }: + + ${ + logRateAnalysisType === LOG_RATE_ANALYSIS_TYPE.SPIKE + ? 'The median log rate in the selected deviation time range is higher than the baseline. Therefore, the results shows statistically significant items within the deviation time range that are contributors to the spike. The "doc count" column refers to the amount of documents in the deviation time range.' + : 'The median log rate in the selected deviation time range is lower than the baseline. Therefore, the analysis results table shows statistically significant items within the baseline time range that are less in number or missing within the deviation time range. The "doc count" column refers to the amount of documents in the baseline time range.' + } + + ${header} + ${rows} + + Based on the above analysis results and your observability expert knowledge, output the following: + Analyse the type of these logs and explain their usual purpose (1 paragraph). + ${ + logRateAnalysisType === LOG_RATE_ANALYSIS_TYPE.SPIKE + ? 'Based on the type of these logs do a root cause analysis on why the field and value combinations from the analysis results are causing this log rate spike (2 parapraphs)' + : 'Based on the type of these logs explain why the statistically significant field and value combinations are less in number or missing from the log rate dip with concrete examples based on the analysis results data which contains items that are present in the baseline time range and are missing or less in number in the deviation time range (2 paragraphs)' + }. + ${ + logRateAnalysisType === LOG_RATE_ANALYSIS_TYPE.SPIKE + ? 'Recommend concrete remediations to resolve the root cause (3 bullet points).' + : '' + } + + Do not mention individual p-values from the analysis results. + Do not repeat the full list of field names and field values back to the user. + Do not guess, just say what you are sure of. Do not repeat the given instructions in your output.`; + + const now = new Date().toISOString(); + + return [ + { + '@timestamp': now, + message: { + content, + role: MessageRole.User, + }, + }, + ]; + }, [logRateAnalysisParams]); + + if (!dataView || !esSearchQuery) return null; + + return ( + + + + +

    + +

    +
    +
    + + + +
    + + {ObservabilityAIAssistantContextualInsight && messages ? ( + + + + ) : null} + +
    + ); +} diff --git a/x-pack/plugins/observability/public/components/custom_threshold/mocks/custom_threshold_rule.ts b/x-pack/plugins/observability/public/components/custom_threshold/mocks/custom_threshold_rule.ts index cfe41b6bd9d0..817e5dbadb97 100644 --- a/x-pack/plugins/observability/public/components/custom_threshold/mocks/custom_threshold_rule.ts +++ b/x-pack/plugins/observability/public/components/custom_threshold/mocks/custom_threshold_rule.ts @@ -8,7 +8,10 @@ import { v4 as uuidv4 } from 'uuid'; import { Aggregators, Comparator } from '../../../../common/custom_threshold_rule/types'; -import { CustomThresholdAlert, CustomThresholdRule } from '../components/alert_details_app_section'; +import { + CustomThresholdAlert, + CustomThresholdRule, +} from '../components/alert_details_app_section/alert_details_app_section'; export const buildCustomThresholdRule = ( rule: Partial = {} diff --git a/x-pack/plugins/observability/public/hooks/use_license.ts b/x-pack/plugins/observability/public/hooks/use_license.ts index f666dcd025bd..f6ed1ebf8bab 100644 --- a/x-pack/plugins/observability/public/hooks/use_license.ts +++ b/x-pack/plugins/observability/public/hooks/use_license.ts @@ -14,7 +14,7 @@ import { useKibana } from '../utils/kibana_react'; interface UseLicenseReturnValue { getLicense: () => ILicense | null; - hasAtLeast: (level: LicenseType) => boolean | undefined; + hasAtLeast: (level: LicenseType) => boolean; } export const useLicense = (): UseLicenseReturnValue => { @@ -25,7 +25,7 @@ export const useLicense = (): UseLicenseReturnValue => { getLicense: () => license, hasAtLeast: useCallback( (level: LicenseType) => { - if (!license) return; + if (!license) return false; return !!license && license.isAvailable && license.isActive && license.hasAtLeast(level); }, diff --git a/x-pack/plugins/observability/public/pages/overview/overview.tsx b/x-pack/plugins/observability/public/pages/overview/overview.tsx index 17121be51c66..5cc5e2ac967e 100644 --- a/x-pack/plugins/observability/public/pages/overview/overview.tsx +++ b/x-pack/plugins/observability/public/pages/overview/overview.tsx @@ -73,8 +73,10 @@ export function OverviewPage() { const [esQuery, setEsQuery] = useState<{ bool: BoolQuery }>( buildEsQuery({ - from: relativeStart, - to: relativeEnd, + timeRange: { + from: relativeStart, + to: relativeEnd, + }, }) ); @@ -108,8 +110,10 @@ export function OverviewPage() { useEffect(() => { setEsQuery( buildEsQuery({ - from: relativeStart, - to: relativeEnd, + timeRange: { + from: relativeStart, + to: relativeEnd, + }, }) ); }, [relativeEnd, relativeStart]); @@ -117,8 +121,10 @@ export function OverviewPage() { const handleTimeRangeRefresh = useCallback(() => { setEsQuery( buildEsQuery({ - from: relativeStart, - to: relativeEnd, + timeRange: { + from: relativeStart, + to: relativeEnd, + }, }) ); }, [relativeEnd, relativeStart]); diff --git a/x-pack/plugins/observability/public/plugin.ts b/x-pack/plugins/observability/public/plugin.ts index 808573579cb9..03322f781728 100644 --- a/x-pack/plugins/observability/public/plugin.ts +++ b/x-pack/plugins/observability/public/plugin.ts @@ -28,6 +28,7 @@ import type { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public'; import { LOG_EXPLORER_LOCATOR_ID, LogExplorerLocatorParams } from '@kbn/deeplinks-observability'; import type { DiscoverStart } from '@kbn/discover-plugin/public'; import type { EmbeddableStart } from '@kbn/embeddable-plugin/public'; +import type { FieldFormatsSetup, FieldFormatsStart } from '@kbn/field-formats-plugin/public'; import type { HomePublicPluginSetup, HomePublicPluginStart } from '@kbn/home-plugin/public'; import { i18n } from '@kbn/i18n'; import type { LensPublicStart } from '@kbn/lens-plugin/public'; @@ -114,6 +115,7 @@ export interface ConfigSchema { export type ObservabilityPublicSetup = ReturnType; export interface ObservabilityPublicPluginsSetup { data: DataPublicPluginSetup; + fieldFormats: FieldFormatsSetup; observabilityShared: ObservabilitySharedPluginSetup; observabilityAIAssistant: ObservabilityAIAssistantPluginSetup; share: SharePluginSetup; @@ -137,6 +139,7 @@ export interface ObservabilityPublicPluginsStart { discover: DiscoverStart; embeddable: EmbeddableStart; exploratoryView: ExploratoryViewPublicStart; + fieldFormats: FieldFormatsStart; guidedOnboarding?: GuidedOnboardingPluginStart; lens: LensPublicStart; licensing: LicensingPluginStart; diff --git a/x-pack/plugins/observability/public/rules/register_observability_rule_types.ts b/x-pack/plugins/observability/public/rules/register_observability_rule_types.ts index c9079991bdf4..04519eba23d5 100644 --- a/x-pack/plugins/observability/public/rules/register_observability_rule_types.ts +++ b/x-pack/plugins/observability/public/rules/register_observability_rule_types.ts @@ -156,7 +156,10 @@ export const registerObservabilityRuleTypes = async ( }; }, alertDetailsAppSection: lazy( - () => import('../components/custom_threshold/components/alert_details_app_section') + () => + import( + '../components/custom_threshold/components/alert_details_app_section/alert_details_app_section' + ) ), priority: 5, }); diff --git a/x-pack/plugins/observability/public/utils/build_es_query/build_es_query.test.ts b/x-pack/plugins/observability/public/utils/build_es_query/build_es_query.test.ts index 4bbacaa7bb1a..3cb37893e616 100644 --- a/x-pack/plugins/observability/public/utils/build_es_query/build_es_query.test.ts +++ b/x-pack/plugins/observability/public/utils/build_es_query/build_es_query.test.ts @@ -37,6 +37,6 @@ describe('buildEsQuery', () => { ]; test.each(testData)('should generate correct es query for %j', ({ kuery, timeRange }) => { - expect(buildEsQuery(timeRange, kuery)).toMatchSnapshot(); + expect(buildEsQuery({ timeRange, kuery })).toMatchSnapshot(); }); }); diff --git a/x-pack/plugins/observability/public/utils/build_es_query/build_es_query.ts b/x-pack/plugins/observability/public/utils/build_es_query/build_es_query.ts index 1fd26690f86d..acf6b4cfc4a7 100644 --- a/x-pack/plugins/observability/public/utils/build_es_query/build_es_query.ts +++ b/x-pack/plugins/observability/public/utils/build_es_query/build_es_query.ts @@ -9,12 +9,14 @@ import { buildEsQuery as kbnBuildEsQuery, TimeRange, Query, EsQueryConfig } from import { ALERT_TIME_RANGE } from '@kbn/rule-data-utils'; import { getTime } from '@kbn/data-plugin/common'; -export function buildEsQuery( - timeRange: TimeRange, - kuery?: string, - queries: Query[] = [], - config: EsQueryConfig = {} -) { +interface BuildEsQueryArgs { + timeRange?: TimeRange; + kuery?: string; + queries?: Query[]; + config?: EsQueryConfig; +} + +export function buildEsQuery({ timeRange, kuery, queries = [], config = {} }: BuildEsQueryArgs) { const timeFilter = timeRange && getTime(undefined, timeRange, { diff --git a/x-pack/plugins/observability/server/lib/rules/custom_threshold/lib/evaluate_rule.ts b/x-pack/plugins/observability/server/lib/rules/custom_threshold/lib/evaluate_rule.ts index b1f790da9d14..f5b3f0adf1bd 100644 --- a/x-pack/plugins/observability/server/lib/rules/custom_threshold/lib/evaluate_rule.ts +++ b/x-pack/plugins/observability/server/lib/rules/custom_threshold/lib/evaluate_rule.ts @@ -9,7 +9,8 @@ import moment from 'moment'; import { ElasticsearchClient } from '@kbn/core/server'; import type { Logger } from '@kbn/logging'; import { CustomMetricExpressionParams } from '../../../../../common/custom_threshold_rule/types'; -import { AdditionalContext, getIntervalInSeconds } from '../utils'; +import { getIntervalInSeconds } from '../../../../../common/utils/get_interval_in_seconds'; +import { AdditionalContext } from '../utils'; import { SearchConfigurationType } from '../types'; import { createTimerange } from './create_timerange'; import { getData } from './get_data'; diff --git a/x-pack/plugins/observability/server/lib/rules/custom_threshold/utils.ts b/x-pack/plugins/observability/server/lib/rules/custom_threshold/utils.ts index 66049ab431c5..59d7cf93e0ea 100644 --- a/x-pack/plugins/observability/server/lib/rules/custom_threshold/utils.ts +++ b/x-pack/plugins/observability/server/lib/rules/custom_threshold/utils.ts @@ -257,32 +257,6 @@ export const isTooManyBucketsPreviewException = ( ): value is TooManyBucketsPreviewExceptionMetadata => Boolean(value && value.TOO_MANY_BUCKETS_PREVIEW_EXCEPTION); -const intervalUnits = ['y', 'M', 'w', 'd', 'h', 'm', 's', 'ms']; -const INTERVAL_STRING_RE = new RegExp('^([0-9\\.]*)\\s*(' + intervalUnits.join('|') + ')$'); - -interface UnitsToSeconds { - [unit: string]: number; -} - -const units: UnitsToSeconds = { - ms: 0.001, - s: 1, - m: 60, - h: 3600, - d: 86400, - w: 86400 * 7, - M: 86400 * 30, - y: 86400 * 356, -}; - -export const getIntervalInSeconds = (interval: string): number => { - const matches = interval.match(INTERVAL_STRING_RE); - if (matches) { - return parseFloat(matches[1]) * units[matches[2]]; - } - throw new Error('Invalid interval string format.'); -}; - export const calculateRateTimeranges = (timerange: { to: number; from: number }) => { // This is the total number of milliseconds for the entire timerange const totalTime = timerange.to - timerange.from; diff --git a/x-pack/plugins/observability/tsconfig.json b/x-pack/plugins/observability/tsconfig.json index ba9ac59725ad..04f853572085 100644 --- a/x-pack/plugins/observability/tsconfig.json +++ b/x-pack/plugins/observability/tsconfig.json @@ -102,7 +102,9 @@ "@kbn/core-elasticsearch-client-server-mocks", "@kbn/ingest-pipelines-plugin", "@kbn/core-saved-objects-api-server-mocks", - "@kbn/core-ui-settings-browser-mocks" + "@kbn/core-ui-settings-browser-mocks", + "@kbn/field-formats-plugin", + "@kbn/aiops-utils" ], "exclude": [ "target/**/*" From 42272f90c05616e1ea6bc4f80bc140f3a4979910 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loix?= Date: Fri, 5 Jan 2024 11:08:38 +0000 Subject: [PATCH 27/57] [Serverless Sidenav] Order active paths by tree depth (#174184) --- .../src/project_navigation/utils.test.ts | 55 ++++++++++--------- .../src/project_navigation/utils.ts | 3 + .../components/side_navigation/index.tsx | 2 - 3 files changed, 32 insertions(+), 28 deletions(-) diff --git a/packages/core/chrome/core-chrome-browser-internal/src/project_navigation/utils.test.ts b/packages/core/chrome/core-chrome-browser-internal/src/project_navigation/utils.test.ts index a207162e060c..d886ee3a5d6a 100644 --- a/packages/core/chrome/core-chrome-browser-internal/src/project_navigation/utils.test.ts +++ b/packages/core/chrome/core-chrome-browser-internal/src/project_navigation/utils.test.ts @@ -133,33 +133,36 @@ describe('findActiveNodes', () => { title: 'Root', path: 'root', }, + // Group 1 '[0][0]': { id: 'group1', title: 'Group 1', - deepLink: getDeepLink('group1', 'group1'), path: 'root.group1', }, '[0][0][0]': { - id: 'group1A', - title: 'Group 1A', - path: 'root.group1.group1A', - }, - '[0][0][0][0]': { id: 'item1', title: 'Item 1', - deepLink: getDeepLink('item1', 'item1'), - path: 'root.group1.group1A.item1', + deepLink: getDeepLink('item1', 'item1'), // First match + path: 'root.group1.item1', }, + // Group 2 '[0][1]': { id: 'group2', title: 'Group 2', + deepLink: getDeepLink('group2', 'group2'), path: 'root.group2', }, '[0][1][0]': { + id: 'group2A', + title: 'Group 2A', + path: 'root.group2.group2A', + }, + '[0][1][0][0]': { id: 'item2', title: 'Item 2', - deepLink: getDeepLink('item1', 'item1'), // Same link as above, should match both - path: 'root.group2.item2', + // Second match --> should come first as it is the longest match of the 2 + deepLink: getDeepLink('item1', 'item1'), + path: 'root.group2.group2A.item2', }, }; @@ -172,21 +175,21 @@ describe('findActiveNodes', () => { path: 'root', }, { - id: 'group1', - title: 'Group 1', - deepLink: getDeepLink('group1', 'group1'), - path: 'root.group1', + id: 'group2', + title: 'Group 2', + deepLink: getDeepLink('group2', 'group2'), + path: 'root.group2', }, { - id: 'group1A', - title: 'Group 1A', - path: 'root.group1.group1A', + id: 'group2A', + title: 'Group 2A', + path: 'root.group2.group2A', }, { - id: 'item1', - title: 'Item 1', + id: 'item2', + title: 'Item 2', deepLink: getDeepLink('item1', 'item1'), - path: 'root.group1.group1A.item1', + path: 'root.group2.group2A.item2', }, ], [ @@ -196,15 +199,15 @@ describe('findActiveNodes', () => { path: 'root', }, { - id: 'group2', - title: 'Group 2', - path: 'root.group2', + id: 'group1', + title: 'Group 1', + path: 'root.group1', }, { - id: 'item2', - title: 'Item 2', + id: 'item1', + title: 'Item 1', deepLink: getDeepLink('item1', 'item1'), - path: 'root.group2.item2', + path: 'root.group1.item1', }, ], ]); diff --git a/packages/core/chrome/core-chrome-browser-internal/src/project_navigation/utils.ts b/packages/core/chrome/core-chrome-browser-internal/src/project_navigation/utils.ts index 63f7f8e612c2..c025872d736b 100644 --- a/packages/core/chrome/core-chrome-browser-internal/src/project_navigation/utils.ts +++ b/packages/core/chrome/core-chrome-browser-internal/src/project_navigation/utils.ts @@ -137,6 +137,9 @@ export const findActiveNodes = ( matches[length] = []; } matches[length].push(key); + // If there are multiple node matches of the same URL path length, we want to order them by + // tree depth, so that the longest match (deepest node) comes first. + matches[length].sort((a, b) => b.length - a.length); } } }); diff --git a/x-pack/plugins/serverless_observability/public/components/side_navigation/index.tsx b/x-pack/plugins/serverless_observability/public/components/side_navigation/index.tsx index 5be456cfd5f3..87e6dc3c7b56 100644 --- a/x-pack/plugins/serverless_observability/public/components/side_navigation/index.tsx +++ b/x-pack/plugins/serverless_observability/public/components/side_navigation/index.tsx @@ -33,8 +33,6 @@ const navigationTree: NavigationTreeDefinition = { defaultMessage: 'Discover', }), link: 'observability-log-explorer', - // prevent this entry from ever becoming active, effectively falling through to the obs-log-explorer child - getIsActive: () => false, // avoid duplicate "Discover" breadcrumbs breadcrumbStatus: 'hidden', renderAs: 'item', From 403a8d0604c1a3310470c7219a05c53017f27816 Mon Sep 17 00:00:00 2001 From: Carlos Crespo Date: Fri, 5 Jan 2024 12:30:12 +0100 Subject: [PATCH 28/57] [APM] Fix max bucket error in Dependencies pages (#173083) fixes: https://github.com/elastic/kibana/issues/161239 ## Summary This PR changes how dependencies data is fetched. To mitigate the max bucket error risk, and, at the same time, keep the compatibility with the dependencies-related pages that consume the `get_connection_stats` query, it now paginates the composite aggregation, using smaller batches of 1k items per pagination. **10k dependencies** image **500 dependencies per service** image **Notes:** Fetching 1k on each iteration might make the page slower; The max bucket error might still happen depending on the date range or how services are instrumented. ### How to test 1. Run synthtrace ``` node scripts/synthtrace service_many_dependencies.ts --from=now-15m --to=now --clean ``` 2. Navigate to the Dependencies Inventory page 3. Navigate to a service overview and then to the dependency tab --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../scenarios/service_many_dependencies.ts | 67 +++++++++ .../e2e/{ => dependencies}/dependencies.cy.ts | 50 ++++++- .../generate_many_dependencies.ts | 69 +++++++++ .../get_connection_stats/get_stats.ts | 140 ++++++++++-------- 4 files changed, 265 insertions(+), 61 deletions(-) create mode 100644 packages/kbn-apm-synthtrace/src/scenarios/service_many_dependencies.ts rename x-pack/plugins/apm/ftr_e2e/cypress/e2e/{ => dependencies}/dependencies.cy.ts (73%) create mode 100644 x-pack/plugins/apm/ftr_e2e/cypress/e2e/dependencies/generate_many_dependencies.ts diff --git a/packages/kbn-apm-synthtrace/src/scenarios/service_many_dependencies.ts b/packages/kbn-apm-synthtrace/src/scenarios/service_many_dependencies.ts new file mode 100644 index 000000000000..a548e55f575a --- /dev/null +++ b/packages/kbn-apm-synthtrace/src/scenarios/service_many_dependencies.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 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 { ApmFields, Instance } from '@kbn/apm-synthtrace-client'; +import { service } from '@kbn/apm-synthtrace-client/src/lib/apm/service'; +import { Scenario } from '../cli/scenario'; +import { RunOptions } from '../cli/utils/parse_run_cli_flags'; +import { getSynthtraceEnvironment } from '../lib/utils/get_synthtrace_environment'; +import { withClient } from '../lib/utils/with_client'; + +const ENVIRONMENT = getSynthtraceEnvironment(__filename); +const MAX_DEPENDENCIES = 10000; +const MAX_DEPENDENCIES_PER_SERVICE = 500; +const MAX_SERVICES = 20; + +const scenario: Scenario = async (runOptions: RunOptions) => { + return { + generate: ({ range, clients: { apmEsClient } }) => { + const javaInstances = Array.from({ length: MAX_SERVICES }).map((_, index) => + service(`opbeans-java-${index}`, ENVIRONMENT, 'java').instance(`java-instance-${index}`) + ); + + const instanceDependencies = (instance: Instance, startIndex: number) => { + const rate = range.ratePerMinute(60); + + return rate.generator((timestamp, index) => { + const currentIndex = index % MAX_DEPENDENCIES_PER_SERVICE; + const destination = (startIndex + currentIndex) % MAX_DEPENDENCIES; + + const span = instance + .transaction({ transactionName: 'GET /java' }) + .timestamp(timestamp) + .duration(400) + .success() + .children( + instance + .span({ + spanName: 'GET apm-*/_search', + spanType: 'db', + spanSubtype: 'elasticsearch', + }) + .destination(`elasticsearch/${destination}`) + .timestamp(timestamp) + .duration(200) + .success() + ); + + return span; + }); + }; + + return withClient( + apmEsClient, + javaInstances.map((instance, index) => + instanceDependencies(instance, (index * MAX_DEPENDENCIES_PER_SERVICE) % MAX_DEPENDENCIES) + ) + ); + }, + }; +}; + +export default scenario; diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/e2e/dependencies.cy.ts b/x-pack/plugins/apm/ftr_e2e/cypress/e2e/dependencies/dependencies.cy.ts similarity index 73% rename from x-pack/plugins/apm/ftr_e2e/cypress/e2e/dependencies.cy.ts rename to x-pack/plugins/apm/ftr_e2e/cypress/e2e/dependencies/dependencies.cy.ts index 3200ba846fc7..11741c3d3066 100644 --- a/x-pack/plugins/apm/ftr_e2e/cypress/e2e/dependencies.cy.ts +++ b/x-pack/plugins/apm/ftr_e2e/cypress/e2e/dependencies/dependencies.cy.ts @@ -4,9 +4,10 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { synthtrace } from '../../synthtrace'; -import { opbeans } from '../fixtures/synthtrace/opbeans'; -import { checkA11y } from '../support/commands'; +import { synthtrace } from '../../../synthtrace'; +import { opbeans } from '../../fixtures/synthtrace/opbeans'; +import { checkA11y } from '../../support/commands'; +import { generateManyDependencies } from './generate_many_dependencies'; const start = '2021-10-10T00:00:00.000Z'; const end = '2021-10-10T00:15:00.000Z'; @@ -120,3 +121,46 @@ describe('Dependencies', () => { }); }); }); + +describe('Dependencies with high volume of data', () => { + before(() => { + synthtrace.index( + generateManyDependencies({ + from: new Date(start).getTime(), + to: new Date(end).getTime(), + }) + ); + }); + + after(() => { + synthtrace.clean(); + }); + + beforeEach(() => { + cy.loginAsViewerUser(); + }); + + it('shows dependencies inventory page', () => { + cy.visitKibana( + `/app/apm/dependencies/inventory?${new URLSearchParams({ + ...timeRange, + kuery: 'elasticsearch*', + })}` + ); + + cy.getByTestSubj('dependenciesTable'); + cy.contains('nav', 'Page 1 of 60'); + }); + + it('shows service dependencies', () => { + cy.visitKibana( + `/app/apm/services/synth-java-0/dependencies?${new URLSearchParams({ + ...timeRange, + })}` + ); + + cy.getByTestSubj('serviceDependenciesBreakdownChart').get('canvas'); + cy.getByTestSubj('dependenciesTable'); + cy.contains('nav', 'Page 1 of 100'); + }); +}); diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/e2e/dependencies/generate_many_dependencies.ts b/x-pack/plugins/apm/ftr_e2e/cypress/e2e/dependencies/generate_many_dependencies.ts new file mode 100644 index 000000000000..0389cd7f90b2 --- /dev/null +++ b/x-pack/plugins/apm/ftr_e2e/cypress/e2e/dependencies/generate_many_dependencies.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 { apm, Instance, timerange } from '@kbn/apm-synthtrace-client'; + +const MAX_DEPENDENCIES = 10000; +const MAX_DEPENDENCIES_PER_SERVICE = 500; +const MAX_SERVICES = 20; + +export function generateManyDependencies({ + from, + to, +}: { + from: number; + to: number; +}) { + const instances = Array.from({ length: MAX_SERVICES }).map((_, index) => + apm + .service({ + name: `synth-java-${index}`, + environment: 'production', + agentName: 'java', + }) + .instance(`java-instance-${index}`) + ); + + const instanceDependencies = (instance: Instance, startIndex: number) => { + return Array.from( + timerange(new Date(from), new Date(to)) + .interval('1m') + .rate(60) + .generator((timestamp, index) => { + const currentIndex = index % MAX_DEPENDENCIES_PER_SERVICE; + const destination = (startIndex + currentIndex) % MAX_DEPENDENCIES; + + const span = instance + .transaction({ transactionName: 'GET /java' }) + .timestamp(timestamp) + .duration(400) + .success() + .children( + instance + .span({ + spanName: 'GET apm-*/_search', + spanType: 'db', + spanSubtype: 'elasticsearch', + }) + .destination(`elasticsearch/${destination}`) + .timestamp(timestamp) + .duration(200) + .success() + ); + + return span; + }) + ); + }; + + return instances.flatMap((instance, index) => + instanceDependencies( + instance, + (index * MAX_DEPENDENCIES_PER_SERVICE) % MAX_DEPENDENCIES + ) + ); +} diff --git a/x-pack/plugins/apm/server/lib/connections/get_connection_stats/get_stats.ts b/x-pack/plugins/apm/server/lib/connections/get_connection_stats/get_stats.ts index 4524d5121b78..7dc038ef744c 100644 --- a/x-pack/plugins/apm/server/lib/connections/get_connection_stats/get_stats.ts +++ b/x-pack/plugins/apm/server/lib/connections/get_connection_stats/get_stats.ts @@ -33,6 +33,7 @@ import { excludeRumExitSpansQuery } from '../exclude_rum_exit_spans_query'; import { APMEventClient } from '../../helpers/create_es_client/create_apm_event_client'; import { getDocumentTypeFilterForServiceDestinationStatistics } from '../../helpers/spans/get_is_using_service_destination_metrics'; +const MAX_ITEMS = 1500; export const getStats = async ({ apmEventClient, start, @@ -54,7 +55,85 @@ export const getStats = async ({ offset, }); - const response = await apmEventClient.search('get_connection_stats', { + const response = await getConnectionStats({ + apmEventClient, + startWithOffset, + endWithOffset, + filter, + numBuckets, + }); + + return ( + response.aggregations?.connections.buckets.map((bucket) => { + const sample = bucket.sample.top[0].metrics; + const serviceName = bucket.key.serviceName as string; + const dependencyName = bucket.key.dependencyName as string; + + return { + from: { + id: objectHash({ serviceName }), + serviceName, + environment: (sample[SERVICE_ENVIRONMENT] || + ENVIRONMENT_NOT_DEFINED.value) as string, + agentName: sample[AGENT_NAME] as AgentName, + type: NodeType.service as const, + }, + to: { + id: objectHash({ dependencyName }), + dependencyName, + spanType: sample[SPAN_TYPE] as string, + spanSubtype: (sample[SPAN_SUBTYPE] || '') as string, + type: NodeType.dependency as const, + }, + value: { + count: sum( + bucket.timeseries.buckets.map( + (dateBucket) => dateBucket.count.value ?? 0 + ) + ), + latency_sum: sum( + bucket.timeseries.buckets.map( + (dateBucket) => dateBucket.latency_sum.value ?? 0 + ) + ), + error_count: sum( + bucket.timeseries.buckets.flatMap( + (dateBucket) => + dateBucket[EVENT_OUTCOME].buckets.find( + (outcomeBucket) => outcomeBucket.key === EventOutcome.failure + )?.count.value ?? 0 + ) + ), + }, + timeseries: bucket.timeseries.buckets.map((dateBucket) => ({ + x: dateBucket.key + offsetInMs, + count: dateBucket.count.value ?? 0, + latency_sum: dateBucket.latency_sum.value ?? 0, + error_count: + dateBucket[EVENT_OUTCOME].buckets.find( + (outcomeBucket) => outcomeBucket.key === EventOutcome.failure + )?.count.value ?? 0, + })), + }; + }) ?? [] + ); +}; + +async function getConnectionStats({ + apmEventClient, + startWithOffset, + endWithOffset, + filter, + numBuckets, +}: { + apmEventClient: APMEventClient; + startWithOffset: number; + endWithOffset: number; + filter: QueryDslQueryContainer[]; + numBuckets: number; + after?: { serviceName: string | number; dependencyName: string | number }; +}) { + return apmEventClient.search('get_connection_stats', { apm: { sources: [ { @@ -79,7 +158,7 @@ export const getStats = async ({ aggs: { connections: { composite: { - size: 10000, + size: MAX_ITEMS, sources: asMutableArray([ { serviceName: { @@ -174,59 +253,4 @@ export const getStats = async ({ }, }, }); - - return ( - response.aggregations?.connections.buckets.map((bucket) => { - const sample = bucket.sample.top[0].metrics; - const serviceName = bucket.key.serviceName as string; - const dependencyName = bucket.key.dependencyName as string; - - return { - from: { - id: objectHash({ serviceName }), - serviceName, - environment: (sample[SERVICE_ENVIRONMENT] || - ENVIRONMENT_NOT_DEFINED.value) as string, - agentName: sample[AGENT_NAME] as AgentName, - type: NodeType.service as const, - }, - to: { - id: objectHash({ dependencyName }), - dependencyName, - spanType: sample[SPAN_TYPE] as string, - spanSubtype: (sample[SPAN_SUBTYPE] || '') as string, - type: NodeType.dependency as const, - }, - value: { - count: sum( - bucket.timeseries.buckets.map( - (dateBucket) => dateBucket.count.value ?? 0 - ) - ), - latency_sum: sum( - bucket.timeseries.buckets.map( - (dateBucket) => dateBucket.latency_sum.value ?? 0 - ) - ), - error_count: sum( - bucket.timeseries.buckets.flatMap( - (dateBucket) => - dateBucket[EVENT_OUTCOME].buckets.find( - (outcomeBucket) => outcomeBucket.key === EventOutcome.failure - )?.count.value ?? 0 - ) - ), - }, - timeseries: bucket.timeseries.buckets.map((dateBucket) => ({ - x: dateBucket.key + offsetInMs, - count: dateBucket.count.value ?? 0, - latency_sum: dateBucket.latency_sum.value ?? 0, - error_count: - dateBucket[EVENT_OUTCOME].buckets.find( - (outcomeBucket) => outcomeBucket.key === EventOutcome.failure - )?.count.value ?? 0, - })), - }; - }) ?? [] - ); -}; +} From 71db3d93e767645767c6df2d1b269fb83e7961c8 Mon Sep 17 00:00:00 2001 From: Katerina Date: Fri, 5 Jan 2024 13:58:46 +0200 Subject: [PATCH 29/57] [APM] Enable dashboard tab in mobile template (#174255) closes https://github.com/elastic/kibana/issues/174251 it should be consistent with the backend services. image --- .../actions/edit_dashboard.tsx | 3 +++ .../actions/link_dashboard.tsx | 3 +++ .../actions/save_dashboard_modal.tsx | 7 ++----- .../app/service_dashboards/index.tsx | 15 ++++++++++++--- .../routing/mobile_service_detail/index.tsx | 16 +++++++++++++++- .../mobile_service_template/index.tsx | 18 ++++++++++++++++-- 6 files changed, 51 insertions(+), 11 deletions(-) diff --git a/x-pack/plugins/apm/public/components/app/service_dashboards/actions/edit_dashboard.tsx b/x-pack/plugins/apm/public/components/app/service_dashboards/actions/edit_dashboard.tsx index e3a6619b446d..c880a912a5b5 100644 --- a/x-pack/plugins/apm/public/components/app/service_dashboards/actions/edit_dashboard.tsx +++ b/x-pack/plugins/apm/public/components/app/service_dashboards/actions/edit_dashboard.tsx @@ -13,9 +13,11 @@ import { MergedServiceDashboard } from '..'; export function EditDashboard({ onRefresh, currentDashboard, + serviceName, }: { onRefresh: () => void; currentDashboard: MergedServiceDashboard; + serviceName: string; }) { const [isModalVisible, setIsModalVisible] = useState(false); return ( @@ -37,6 +39,7 @@ export function EditDashboard({ onClose={() => setIsModalVisible(!isModalVisible)} onRefresh={onRefresh} currentDashboard={currentDashboard} + serviceName={serviceName} /> )} diff --git a/x-pack/plugins/apm/public/components/app/service_dashboards/actions/link_dashboard.tsx b/x-pack/plugins/apm/public/components/app/service_dashboards/actions/link_dashboard.tsx index 7b652c21039d..0db2654c1d66 100644 --- a/x-pack/plugins/apm/public/components/app/service_dashboards/actions/link_dashboard.tsx +++ b/x-pack/plugins/apm/public/components/app/service_dashboards/actions/link_dashboard.tsx @@ -14,10 +14,12 @@ export function LinkDashboard({ onRefresh, emptyButton = false, serviceDashboards, + serviceName, }: { onRefresh: () => void; emptyButton?: boolean; serviceDashboards?: MergedServiceDashboard[]; + serviceName: string; }) { const [isModalVisible, setIsModalVisible] = useState(false); @@ -51,6 +53,7 @@ export function LinkDashboard({ onClose={() => setIsModalVisible(false)} onRefresh={onRefresh} serviceDashboards={serviceDashboards} + serviceName={serviceName} /> )} diff --git a/x-pack/plugins/apm/public/components/app/service_dashboards/actions/save_dashboard_modal.tsx b/x-pack/plugins/apm/public/components/app/service_dashboards/actions/save_dashboard_modal.tsx index 3083e41c2dac..6872b0d2cc80 100644 --- a/x-pack/plugins/apm/public/components/app/service_dashboards/actions/save_dashboard_modal.tsx +++ b/x-pack/plugins/apm/public/components/app/service_dashboards/actions/save_dashboard_modal.tsx @@ -28,7 +28,6 @@ import { callApmApi } from '../../../../services/rest/create_call_apm_api'; import { useDashboardFetcher } from '../../../../hooks/use_dashboards_fetcher'; import { FETCH_STATUS } from '../../../../hooks/use_fetcher'; import { useApmPluginContext } from '../../../../context/apm_plugin/use_apm_plugin_context'; -import { useApmParams } from '../../../../hooks/use_apm_params'; import { SERVICE_NAME } from '../../../../../common/es_fields/apm'; import { fromQuery, toQuery } from '../../../shared/links/url_helpers'; import { MergedServiceDashboard } from '..'; @@ -38,6 +37,7 @@ interface Props { onRefresh: () => void; currentDashboard?: MergedServiceDashboard; serviceDashboards?: MergedServiceDashboard[]; + serviceName: string; } export function SaveDashboardModal({ @@ -45,6 +45,7 @@ export function SaveDashboardModal({ onRefresh, currentDashboard, serviceDashboards, + serviceName, }: Props) { const { core: { notifications }, @@ -71,10 +72,6 @@ export function SaveDashboardModal({ const isEditMode = !!currentDashboard?.id; - const { - path: { serviceName }, - } = useApmParams('/services/{serviceName}/dashboards'); - const reloadCustomDashboards = useCallback(() => { onRefresh(); }, [onRefresh]); diff --git a/x-pack/plugins/apm/public/components/app/service_dashboards/index.tsx b/x-pack/plugins/apm/public/components/app/service_dashboards/index.tsx index fe44d62c2388..7426ec382b87 100644 --- a/x-pack/plugins/apm/public/components/app/service_dashboards/index.tsx +++ b/x-pack/plugins/apm/public/components/app/service_dashboards/index.tsx @@ -28,7 +28,7 @@ import { SerializableRecord } from '@kbn/utility-types'; import { EmptyDashboards } from './empty_dashboards'; import { GotoDashboard, LinkDashboard } from './actions'; import { FETCH_STATUS, useFetcher } from '../../../hooks/use_fetcher'; -import { useApmParams } from '../../../hooks/use_apm_params'; +import { useAnyOfApmParams } from '../../../hooks/use_apm_params'; import { SavedApmCustomDashboard } from '../../../../common/custom_dashboards'; import { ContextMenu } from './context_menu'; import { UnlinkDashboard } from './actions/unlink_dashboard'; @@ -49,7 +49,10 @@ export function ServiceDashboards() { const { path: { serviceName }, query: { environment, kuery, rangeFrom, rangeTo, dashboardId }, - } = useApmParams('/services/{serviceName}/dashboards'); + } = useAnyOfApmParams( + '/services/{serviceName}/dashboards', + '/mobile-services/{serviceName}/dashboards' + ); const [dashboard, setDashboard] = useState(); const [serviceDashboards, setServiceDashboards] = useState< MergedServiceDashboard[] @@ -209,11 +212,13 @@ export function ServiceDashboards() { emptyButton={true} onRefresh={refetch} serviceDashboards={serviceDashboards} + serviceName={serviceName} />, , , ) : ( - } /> + + } + /> )} ); diff --git a/x-pack/plugins/apm/public/components/routing/mobile_service_detail/index.tsx b/x-pack/plugins/apm/public/components/routing/mobile_service_detail/index.tsx index 11a365e0d832..fa8e7ee0323a 100644 --- a/x-pack/plugins/apm/public/components/routing/mobile_service_detail/index.tsx +++ b/x-pack/plugins/apm/public/components/routing/mobile_service_detail/index.tsx @@ -26,7 +26,7 @@ import { ErrorGroupDetails } from '../../app/mobile/errors_and_crashes_group_det import { CrashGroupDetails } from '../../app/mobile/errors_and_crashes_group_details/crash_group_details'; import { MobileErrorCrashesOverview } from '../../app/mobile/errors_and_crashes_overview'; import { ServiceDependencies } from '../../app/service_dependencies'; - +import { ServiceDashboards } from '../../app/service_dashboards'; export function page({ title, tabKey, @@ -270,6 +270,20 @@ export const mobileServiceDetailRoute = { }), }), }, + '/mobile-services/{serviceName}/dashboards': { + ...page({ + tabKey: 'dashboards', + title: i18n.translate('xpack.apm.views.dashboard.title', { + defaultMessage: 'Dashboards', + }), + element: , + }), + params: t.partial({ + query: t.partial({ + dashboardId: t.string, + }), + }), + }, '/mobile-services/{serviceName}/': { element: , }, diff --git a/x-pack/plugins/apm/public/components/routing/templates/mobile_service_template/index.tsx b/x-pack/plugins/apm/public/components/routing/templates/mobile_service_template/index.tsx index 3c9bde66ff3a..b5ce69d9c1d0 100644 --- a/x-pack/plugins/apm/public/components/routing/templates/mobile_service_template/index.tsx +++ b/x-pack/plugins/apm/public/components/routing/templates/mobile_service_template/index.tsx @@ -35,7 +35,8 @@ type Tab = NonNullable[0] & { | 'dependencies' | 'errors-and-crashes' | 'service-map' - | 'alerts'; + | 'alerts' + | 'dashboards'; hidden?: boolean; }; @@ -231,12 +232,25 @@ function useTabs({ selectedTabKey }: { selectedTabKey: Tab['key'] }) { path: { serviceName }, query, }), - append: , label: i18n.translate('xpack.apm.mobileServiceDetails.alertsTabLabel', { defaultMessage: 'Alerts', }), hidden: !(isAlertingAvailable && canReadAlerts), }, + { + key: 'dashboards', + href: router.link('/mobile-services/{serviceName}/dashboards', { + path: { serviceName }, + query, + }), + append: , + label: i18n.translate( + 'xpack.apm.mobileServiceDetails.dashboardsTabLabel', + { + defaultMessage: 'Dashboards', + } + ), + }, ]; return tabs From c39fac616b7413cc21fe17838025a443e60fdc69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mike=20C=C3=B4t=C3=A9?= Date: Fri, 5 Jan 2024 08:01:59 -0500 Subject: [PATCH 30/57] Rename connector compatibility for Generative AI so it is split between security and o11y (#174000) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In this PR, I'm renaming `Generative AI` to `Generative AI for Security` in the connectors comatibility list so we have a split on Gen AI for Security and Observability (follow up from https://github.com/elastic/kibana/pull/173826). ## Screenshots Screenshot 2024-01-03 at 11 53 00 AM Screenshot 2024-01-03 at 11 53 32 AM Screenshot 2024-01-03 at 11 53 39 AM ## To verify **Connectors** 1. Startup Kibana in trial mode 2. Open the create Bedrock connector flyout from the connectors page 3. Notice the compatibility is only for Security 4. Create a Bedrock connector (input random text in all fields to pass validation) 5. Open the create OpenAI connector from the connectors page 6. Notice the compatibility is for Security and Observability 7. Create an OpenAI connector (input random text in all fields to pass validation) **Security Solution** 9. Navigate to the Security solution (`/app/security/get_started`) 10. Open the AI Assistant on the top right 11. Open the `Conversation Settings` 12. See OpenAI and Bedrock connectors displaying **Observability** 13. Navigate to the Observability app (`/app/observability/overview`) 14. Open the AI Assistant on the top right 15. Select the actions menu on the top right of the flyout and open `AI Assistant Settings` 16. Open the default connector dropdown 17. Notice only OpenAI connectors displaying --- .../use_load_action_types/index.test.tsx | 2 +- .../use_load_action_types/index.tsx | 4 ++-- .../common/connector_feature_config.test.ts | 6 +++--- .../common/connector_feature_config.ts | 20 +++++++++---------- x-pack/plugins/actions/common/types.ts | 2 +- .../server/connector_types/bedrock/index.ts | 4 ++-- .../server/connector_types/openai/index.ts | 4 ++-- .../translations/translations/fr-FR.json | 1 - .../translations/translations/ja-JP.json | 1 - .../translations/translations/zh-CN.json | 1 - 10 files changed, 21 insertions(+), 24 deletions(-) diff --git a/x-pack/packages/kbn-elastic-assistant/impl/connectorland/use_load_action_types/index.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/connectorland/use_load_action_types/index.test.tsx index 0aa6ed21e2f8..50d3a7379741 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/connectorland/use_load_action_types/index.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/connectorland/use_load_action_types/index.test.tsx @@ -37,7 +37,7 @@ describe('useLoadActionTypes', () => { await waitForNextUpdate(); expect(defaultProps.http.get).toHaveBeenCalledWith('/api/actions/connector_types', { - query: { feature_id: 'generativeAI' }, + query: { feature_id: 'generativeAIForSecurity' }, }); expect(toasts.addError).not.toHaveBeenCalled(); }); diff --git a/x-pack/packages/kbn-elastic-assistant/impl/connectorland/use_load_action_types/index.tsx b/x-pack/packages/kbn-elastic-assistant/impl/connectorland/use_load_action_types/index.tsx index d307f85e43b7..cf62127f286c 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/connectorland/use_load_action_types/index.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/connectorland/use_load_action_types/index.tsx @@ -15,7 +15,7 @@ import type { IHttpFetchError } from '@kbn/core-http-browser'; import type { ActionType } from '@kbn/actions-plugin/common'; import { HttpSetup } from '@kbn/core-http-browser'; import { IToasts } from '@kbn/core-notifications-browser'; -import { GenerativeAIConnectorFeatureId } from '@kbn/actions-plugin/common'; +import { GenerativeAIForSecurityConnectorFeatureId } from '@kbn/actions-plugin/common'; import * as i18n from '../translations'; /** @@ -39,7 +39,7 @@ export const useLoadActionTypes = ({ async () => { const queryResult = await loadActionTypes({ http, - featureId: GenerativeAIConnectorFeatureId, + featureId: GenerativeAIForSecurityConnectorFeatureId, }); const sortedData = queryResult.sort((a, b) => a.name.localeCompare(b.name)); diff --git a/x-pack/plugins/actions/common/connector_feature_config.test.ts b/x-pack/plugins/actions/common/connector_feature_config.test.ts index c12e3db21127..1f18e923593d 100644 --- a/x-pack/plugins/actions/common/connector_feature_config.test.ts +++ b/x-pack/plugins/actions/common/connector_feature_config.test.ts @@ -13,7 +13,7 @@ import { describe('areValidFeatures', () => { it('returns true when all inputs are valid features', () => { - expect(areValidFeatures(['alerting', 'cases', 'generativeAI'])).toBeTruthy(); + expect(areValidFeatures(['alerting', 'cases', 'generativeAIForSecurity'])).toBeTruthy(); }); it('returns true when only one input and it is a valid feature', () => { @@ -43,8 +43,8 @@ describe('getConnectorFeatureName', () => { describe('getConnectorCompatibility', () => { it('returns the compatibility list for valid feature ids', () => { expect( - getConnectorCompatibility(['alerting', 'cases', 'uptime', 'siem', 'generativeAI']) - ).toEqual(['Alerting Rules', 'Cases', 'Generative AI']); + getConnectorCompatibility(['alerting', 'cases', 'uptime', 'siem', 'generativeAIForSecurity']) + ).toEqual(['Alerting Rules', 'Cases', 'Generative AI for Security']); }); it('skips invalid feature ids', () => { diff --git a/x-pack/plugins/actions/common/connector_feature_config.ts b/x-pack/plugins/actions/common/connector_feature_config.ts index fb61ff35da6b..4638387d31c5 100644 --- a/x-pack/plugins/actions/common/connector_feature_config.ts +++ b/x-pack/plugins/actions/common/connector_feature_config.ts @@ -25,20 +25,20 @@ export const AlertingConnectorFeatureId = 'alerting'; export const CasesConnectorFeatureId = 'cases'; export const UptimeConnectorFeatureId = 'uptime'; export const SecurityConnectorFeatureId = 'siem'; -export const GenerativeAIConnectorFeatureId = 'generativeAI'; +export const GenerativeAIForSecurityConnectorFeatureId = 'generativeAIForSecurity'; export const GenerativeAIForObservabilityConnectorFeatureId = 'generativeAIForObservability'; -const compatibilityGenerativeAI = i18n.translate( - 'xpack.actions.availableConnectorFeatures.compatibility.generativeAI', +const compatibilityGenerativeAIForSecurity = i18n.translate( + 'xpack.actions.availableConnectorFeatures.compatibility.generativeAIForSecurity', { - defaultMessage: 'Generative AI', + defaultMessage: 'Generative AI for Security', } ); const compatibilityGenerativeAIForObservability = i18n.translate( 'xpack.actions.availableConnectorFeatures.compatibility.generativeAIForObservability', { - defaultMessage: 'Generative AI For Observability', + defaultMessage: 'Generative AI for Observability', } ); @@ -88,10 +88,10 @@ export const SecuritySolutionFeature: ConnectorFeatureConfig = { compatibility: compatibilityAlertingRules, }; -export const GenerativeAIFeature: ConnectorFeatureConfig = { - id: GenerativeAIConnectorFeatureId, - name: compatibilityGenerativeAI, - compatibility: compatibilityGenerativeAI, +export const GenerativeAIForSecurityFeature: ConnectorFeatureConfig = { + id: GenerativeAIForSecurityConnectorFeatureId, + name: compatibilityGenerativeAIForSecurity, + compatibility: compatibilityGenerativeAIForSecurity, }; export const GenerativeAIForObservabilityFeature: ConnectorFeatureConfig = { @@ -105,7 +105,7 @@ const AllAvailableConnectorFeatures = { [CasesConnectorFeature.id]: CasesConnectorFeature, [UptimeConnectorFeature.id]: UptimeConnectorFeature, [SecuritySolutionFeature.id]: SecuritySolutionFeature, - [GenerativeAIFeature.id]: GenerativeAIFeature, + [GenerativeAIForSecurityFeature.id]: GenerativeAIForSecurityFeature, [GenerativeAIForObservabilityFeature.id]: GenerativeAIForObservabilityFeature, }; diff --git a/x-pack/plugins/actions/common/types.ts b/x-pack/plugins/actions/common/types.ts index 2560cbae3f7e..7420240d71cc 100644 --- a/x-pack/plugins/actions/common/types.ts +++ b/x-pack/plugins/actions/common/types.ts @@ -13,7 +13,7 @@ export { CasesConnectorFeatureId, UptimeConnectorFeatureId, SecurityConnectorFeatureId, - GenerativeAIConnectorFeatureId, + GenerativeAIForSecurityConnectorFeatureId, } from './connector_feature_config'; export interface ActionType { id: string; diff --git a/x-pack/plugins/stack_connectors/server/connector_types/bedrock/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/bedrock/index.ts index e9ab58327728..5f295b8c3936 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/bedrock/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/bedrock/index.ts @@ -10,7 +10,7 @@ import { SubActionConnectorType, ValidatorType, } from '@kbn/actions-plugin/server/sub_action_framework/types'; -import { GenerativeAIConnectorFeatureId } from '@kbn/actions-plugin/common'; +import { GenerativeAIForSecurityConnectorFeatureId } from '@kbn/actions-plugin/common'; import { urlAllowListValidator } from '@kbn/actions-plugin/server'; import { ValidatorServices } from '@kbn/actions-plugin/server/types'; import { assertURL } from '@kbn/actions-plugin/server/sub_action_framework/helpers/validators'; @@ -29,7 +29,7 @@ export const getConnectorType = (): SubActionConnectorType => ( secrets: SecretsSchema, }, validators: [{ type: ValidatorType.CONFIG, validator: configValidator }], - supportedFeatureIds: [GenerativeAIConnectorFeatureId], + supportedFeatureIds: [GenerativeAIForSecurityConnectorFeatureId], minimumLicenseRequired: 'enterprise' as const, renderParameterTemplates, }); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/openai/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/openai/index.ts index 6852a83a9ee3..3fa865209ba5 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/openai/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/openai/index.ts @@ -11,7 +11,7 @@ import { ValidatorType, } from '@kbn/actions-plugin/server/sub_action_framework/types'; import { - GenerativeAIConnectorFeatureId, + GenerativeAIForSecurityConnectorFeatureId, GenerativeAIForObservabilityConnectorFeatureId, } from '@kbn/actions-plugin/common'; import { urlAllowListValidator } from '@kbn/actions-plugin/server'; @@ -37,7 +37,7 @@ export const getConnectorType = (): SubActionConnectorType => ( }, validators: [{ type: ValidatorType.CONFIG, validator: configValidator }], supportedFeatureIds: [ - GenerativeAIConnectorFeatureId, + GenerativeAIForSecurityConnectorFeatureId, GenerativeAIForObservabilityConnectorFeatureId, ], minimumLicenseRequired: 'enterprise' as const, diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index e7fa92aa02a3..e8365d42168a 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -7621,7 +7621,6 @@ "xpack.actions.availableConnectorFeatures.cases": "Cas", "xpack.actions.availableConnectorFeatures.compatibility.alertingRules": "Règles d'alerting", "xpack.actions.availableConnectorFeatures.compatibility.cases": "Cas", - "xpack.actions.availableConnectorFeatures.compatibility.generativeAI": "IA générative", "xpack.actions.availableConnectorFeatures.securitySolution": "Solution de sécurité", "xpack.actions.availableConnectorFeatures.uptime": "Uptime", "xpack.actions.builtin.cases.jiraTitle": "Jira", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 4a23239256f5..bf36677dd19e 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -7636,7 +7636,6 @@ "xpack.actions.availableConnectorFeatures.cases": "ケース", "xpack.actions.availableConnectorFeatures.compatibility.alertingRules": "アラートルール", "xpack.actions.availableConnectorFeatures.compatibility.cases": "ケース", - "xpack.actions.availableConnectorFeatures.compatibility.generativeAI": "生成AI", "xpack.actions.availableConnectorFeatures.securitySolution": "セキュリティソリューション", "xpack.actions.availableConnectorFeatures.uptime": "アップタイム", "xpack.actions.builtin.cases.jiraTitle": "Jira", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index ccce90db35aa..ebc2118a79b7 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -7702,7 +7702,6 @@ "xpack.actions.availableConnectorFeatures.cases": "案例", "xpack.actions.availableConnectorFeatures.compatibility.alertingRules": "告警规则", "xpack.actions.availableConnectorFeatures.compatibility.cases": "案例", - "xpack.actions.availableConnectorFeatures.compatibility.generativeAI": "生成式 AI", "xpack.actions.availableConnectorFeatures.securitySolution": "安全解决方案", "xpack.actions.availableConnectorFeatures.uptime": "运行时间", "xpack.actions.builtin.cases.jiraTitle": "Jira", From b37634d2b70c6ae99a1b3da9f8a529c112f557ef Mon Sep 17 00:00:00 2001 From: Stratoula Kalafateli Date: Fri, 5 Jan 2024 15:19:14 +0200 Subject: [PATCH 31/57] [Lens][Inline editing] Improve the api for the embeddable consumers (#173841) ## Summary Closes https://github.com/elastic/kibana/issues/167632 This PR provides a simpler api for the Lens embeddable consumers who want to provide inline editing capabilities. I added an example to help with the integration. Run kibana with ``` yarn start --run-examples ``` http://localhost:5601/app/lens_embeddable_inline_editing_example image image It also allows the consumers to render the inline editing component in a custom element in case you don't want to open a push flyout. ![custom-container](https://github.com/elastic/kibana/assets/17003240/6ce1b9c6-dab0-4321-b4c0-ae196dfb4a84) I included a readme on how to use the api. ### Note This is the first PR which uses the new Lens config builder so some of the changes are not related to the api improvements but they are fixing some bugs on the builder. --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .github/CODEOWNERS | 1 + package.json | 1 + .../lens_attributes_builder.test.ts | 46 ++--- .../config_builder/charts/gauge.test.ts | 3 - .../config_builder/charts/heatmap.test.ts | 3 - .../config_builder/charts/metric.test.ts | 3 - .../config_builder/charts/partition.test.ts | 3 - .../config_builder/charts/region_map.test.ts | 3 - .../config_builder/charts/table.test.ts | 3 - .../config_builder/charts/tag_cloud.test.ts | 3 - .../config_builder/charts/xy.test.ts | 3 - .../config_builder/utils.test.ts | 3 - .../config_builder/utils.ts | 14 +- packages/kbn-optimizer/limits.yml | 2 +- .../group_preview.test.tsx | 2 +- .../group_editor_flyout/lens_attributes.ts | 2 +- tsconfig.base.json | 2 + .../.eslintrc.json | 5 + .../README.md | 68 +++++++ .../kibana.jsonc | 21 ++ .../public/app.tsx | 182 ++++++++++++++++++ .../public/embeddable.tsx | 161 ++++++++++++++++ .../public/flyout.tsx | 124 ++++++++++++ .../public/image.png | Bin 0 -> 155151 bytes .../public/index.ts | 10 + .../public/mount.tsx | 49 +++++ .../public/plugin.ts | 57 ++++++ .../public/utils.ts | 63 ++++++ .../tsconfig.json | 26 +++ .../configurations/lens_attributes.test.ts | 2 +- .../get_edit_lens_configuration.tsx | 4 + .../lens_configuration_flyout.tsx | 6 + .../shared/edit_on_the_fly/types.ts | 4 + x-pack/plugins/lens/public/async_services.ts | 1 + .../embeddable/embeddable_component.tsx | 2 +- x-pack/plugins/lens/public/index.ts | 2 + x-pack/plugins/lens/public/plugin.ts | 18 ++ .../in_app_embeddable_edit_action.test.tsx | 97 ++++++++++ .../in_app_embeddable_edit_action.tsx | 64 ++++++ .../in_app_embeddable_edit_action_helpers.tsx | 154 +++++++++++++++ .../in_app_embeddable_edit_trigger.ts | 19 ++ .../in_app_embeddable_edit/types.ts | 37 ++++ x-pack/plugins/lens/readme.md | 8 + .../risk_summary_flyout/risk_summary.test.tsx | 8 +- yarn.lock | 3 + 45 files changed, 1223 insertions(+), 69 deletions(-) create mode 100644 x-pack/examples/lens_embeddable_inline_editing_example/.eslintrc.json create mode 100644 x-pack/examples/lens_embeddable_inline_editing_example/README.md create mode 100644 x-pack/examples/lens_embeddable_inline_editing_example/kibana.jsonc create mode 100644 x-pack/examples/lens_embeddable_inline_editing_example/public/app.tsx create mode 100644 x-pack/examples/lens_embeddable_inline_editing_example/public/embeddable.tsx create mode 100644 x-pack/examples/lens_embeddable_inline_editing_example/public/flyout.tsx create mode 100644 x-pack/examples/lens_embeddable_inline_editing_example/public/image.png create mode 100644 x-pack/examples/lens_embeddable_inline_editing_example/public/index.ts create mode 100644 x-pack/examples/lens_embeddable_inline_editing_example/public/mount.tsx create mode 100644 x-pack/examples/lens_embeddable_inline_editing_example/public/plugin.ts create mode 100644 x-pack/examples/lens_embeddable_inline_editing_example/public/utils.ts create mode 100644 x-pack/examples/lens_embeddable_inline_editing_example/tsconfig.json create mode 100644 x-pack/plugins/lens/public/trigger_actions/open_lens_config/in_app_embeddable_edit/in_app_embeddable_edit_action.test.tsx create mode 100644 x-pack/plugins/lens/public/trigger_actions/open_lens_config/in_app_embeddable_edit/in_app_embeddable_edit_action.tsx create mode 100644 x-pack/plugins/lens/public/trigger_actions/open_lens_config/in_app_embeddable_edit/in_app_embeddable_edit_action_helpers.tsx create mode 100644 x-pack/plugins/lens/public/trigger_actions/open_lens_config/in_app_embeddable_edit/in_app_embeddable_edit_trigger.ts create mode 100644 x-pack/plugins/lens/public/trigger_actions/open_lens_config/in_app_embeddable_edit/types.ts diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index b3d2e9cf82ad..4dae217dce6a 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -487,6 +487,7 @@ x-pack/plugins/kubernetes_security @elastic/kibana-cloud-security-posture packages/kbn-language-documentation-popover @elastic/kibana-visualizations packages/kbn-lens-embeddable-utils @elastic/obs-ux-infra_services-team @elastic/kibana-visualizations packages/kbn-lens-formula-docs @elastic/kibana-visualizations +x-pack/examples/lens_embeddable_inline_editing_example @elastic/kibana-visualizations x-pack/plugins/lens @elastic/kibana-visualizations x-pack/plugins/license_api_guard @elastic/platform-deployment-management x-pack/plugins/license_management @elastic/platform-deployment-management diff --git a/package.json b/package.json index 4f6aef817d57..0a4d9ebfcebd 100644 --- a/package.json +++ b/package.json @@ -509,6 +509,7 @@ "@kbn/language-documentation-popover": "link:packages/kbn-language-documentation-popover", "@kbn/lens-embeddable-utils": "link:packages/kbn-lens-embeddable-utils", "@kbn/lens-formula-docs": "link:packages/kbn-lens-formula-docs", + "@kbn/lens-inline-editing-example-plugin": "link:x-pack/examples/lens_embeddable_inline_editing_example", "@kbn/lens-plugin": "link:x-pack/plugins/lens", "@kbn/license-api-guard-plugin": "link:x-pack/plugins/license_api_guard", "@kbn/license-management-plugin": "link:x-pack/plugins/license_management", diff --git a/packages/kbn-lens-embeddable-utils/attribute_builder/lens_attributes_builder.test.ts b/packages/kbn-lens-embeddable-utils/attribute_builder/lens_attributes_builder.test.ts index 199379e74eb9..2f90e0309935 100644 --- a/packages/kbn-lens-embeddable-utils/attribute_builder/lens_attributes_builder.test.ts +++ b/packages/kbn-lens-embeddable-utils/attribute_builder/lens_attributes_builder.test.ts @@ -113,15 +113,13 @@ describe('lens_attributes_builder', () => { formulaAPI, }); const builder = new LensAttributesBuilder({ visualization: metriChart }); + const { - state: { - datasourceStates: { - formBased: { layers }, - }, - visualization, - }, + state: { datasourceStates: datasourceStates, visualization }, } = builder.build(); + const layers = datasourceStates.formBased?.layers; + expect(layers).toEqual({ layer: { columnOrder: ['metric_formula_accessor'], @@ -156,14 +154,11 @@ describe('lens_attributes_builder', () => { }); const builder = new LensAttributesBuilder({ visualization: metriChart }); const { - state: { - datasourceStates: { - formBased: { layers }, - }, - visualization, - }, + state: { datasourceStates: datasourceStates, visualization }, } = builder.build(); + const layers = datasourceStates.formBased?.layers; + expect(layers).toEqual({ layer: { columnOrder: ['metric_formula_accessor'], @@ -215,14 +210,11 @@ describe('lens_attributes_builder', () => { }); const builder = new LensAttributesBuilder({ visualization: xyChart }); const { - state: { - datasourceStates: { - formBased: { layers }, - }, - visualization, - }, + state: { datasourceStates: datasourceStates, visualization }, } = builder.build(); + const layers = datasourceStates.formBased?.layers; + expect(layers).toEqual({ layer_0: { columnOrder: ['x_date_histogram', 'formula_accessor_0_0'], @@ -272,14 +264,11 @@ describe('lens_attributes_builder', () => { }); const builder = new LensAttributesBuilder({ visualization: xyChart }); const { - state: { - datasourceStates: { - formBased: { layers }, - }, - visualization, - }, + state: { datasourceStates: datasourceStates, visualization }, } = builder.build(); + const layers = datasourceStates.formBased?.layers; + expect(layers).toEqual({ layer_0: { columnOrder: ['x_date_histogram', 'formula_accessor_0_0'], @@ -340,14 +329,11 @@ describe('lens_attributes_builder', () => { }); const builder = new LensAttributesBuilder({ visualization: xyChart }); const { - state: { - datasourceStates: { - formBased: { layers }, - }, - visualization, - }, + state: { datasourceStates: datasourceStates, visualization }, } = builder.build(); + const layers = datasourceStates.formBased?.layers; + expect(layers).toEqual({ layer_0: { columnOrder: ['x_date_histogram', 'formula_accessor_0_0', 'formula_accessor_0_1'], diff --git a/packages/kbn-lens-embeddable-utils/config_builder/charts/gauge.test.ts b/packages/kbn-lens-embeddable-utils/config_builder/charts/gauge.test.ts index 5e0e5dc1de2a..aa13813e37b8 100644 --- a/packages/kbn-lens-embeddable-utils/config_builder/charts/gauge.test.ts +++ b/packages/kbn-lens-embeddable-utils/config_builder/charts/gauge.test.ts @@ -79,9 +79,6 @@ test('generates gauge chart config', async () => { "test": Object {}, }, "datasourceStates": Object { - "formBased": Object { - "layers": Object {}, - }, "textBased": Object { "layers": Object { "layer_0": Object { diff --git a/packages/kbn-lens-embeddable-utils/config_builder/charts/heatmap.test.ts b/packages/kbn-lens-embeddable-utils/config_builder/charts/heatmap.test.ts index cfcabb131b45..91786a0b91e2 100644 --- a/packages/kbn-lens-embeddable-utils/config_builder/charts/heatmap.test.ts +++ b/packages/kbn-lens-embeddable-utils/config_builder/charts/heatmap.test.ts @@ -81,9 +81,6 @@ test('generates metric chart config', async () => { "test": Object {}, }, "datasourceStates": Object { - "formBased": Object { - "layers": Object {}, - }, "textBased": Object { "layers": Object { "layer_0": Object { diff --git a/packages/kbn-lens-embeddable-utils/config_builder/charts/metric.test.ts b/packages/kbn-lens-embeddable-utils/config_builder/charts/metric.test.ts index cf82d3a2f5f4..86078332ebb4 100644 --- a/packages/kbn-lens-embeddable-utils/config_builder/charts/metric.test.ts +++ b/packages/kbn-lens-embeddable-utils/config_builder/charts/metric.test.ts @@ -79,9 +79,6 @@ test('generates metric chart config', async () => { "test": Object {}, }, "datasourceStates": Object { - "formBased": Object { - "layers": Object {}, - }, "textBased": Object { "layers": Object { "layer_0": Object { diff --git a/packages/kbn-lens-embeddable-utils/config_builder/charts/partition.test.ts b/packages/kbn-lens-embeddable-utils/config_builder/charts/partition.test.ts index 22ee18f3e5f3..120b3069552d 100644 --- a/packages/kbn-lens-embeddable-utils/config_builder/charts/partition.test.ts +++ b/packages/kbn-lens-embeddable-utils/config_builder/charts/partition.test.ts @@ -80,9 +80,6 @@ test('generates metric chart config', async () => { "test": Object {}, }, "datasourceStates": Object { - "formBased": Object { - "layers": Object {}, - }, "textBased": Object { "layers": Object { "layer_0": Object { diff --git a/packages/kbn-lens-embeddable-utils/config_builder/charts/region_map.test.ts b/packages/kbn-lens-embeddable-utils/config_builder/charts/region_map.test.ts index 0093b03e33bc..4fd97797b69d 100644 --- a/packages/kbn-lens-embeddable-utils/config_builder/charts/region_map.test.ts +++ b/packages/kbn-lens-embeddable-utils/config_builder/charts/region_map.test.ts @@ -80,9 +80,6 @@ test('generates metric chart config', async () => { "test": Object {}, }, "datasourceStates": Object { - "formBased": Object { - "layers": Object {}, - }, "textBased": Object { "layers": Object { "layer_0": Object { diff --git a/packages/kbn-lens-embeddable-utils/config_builder/charts/table.test.ts b/packages/kbn-lens-embeddable-utils/config_builder/charts/table.test.ts index 909f3e737ac9..dbe67d15416c 100644 --- a/packages/kbn-lens-embeddable-utils/config_builder/charts/table.test.ts +++ b/packages/kbn-lens-embeddable-utils/config_builder/charts/table.test.ts @@ -80,9 +80,6 @@ test('generates metric chart config', async () => { "test": Object {}, }, "datasourceStates": Object { - "formBased": Object { - "layers": Object {}, - }, "textBased": Object { "layers": Object { "layer_0": Object { diff --git a/packages/kbn-lens-embeddable-utils/config_builder/charts/tag_cloud.test.ts b/packages/kbn-lens-embeddable-utils/config_builder/charts/tag_cloud.test.ts index 08885ba57ba8..fe94e8f789d4 100644 --- a/packages/kbn-lens-embeddable-utils/config_builder/charts/tag_cloud.test.ts +++ b/packages/kbn-lens-embeddable-utils/config_builder/charts/tag_cloud.test.ts @@ -80,9 +80,6 @@ test('generates metric chart config', async () => { "test": Object {}, }, "datasourceStates": Object { - "formBased": Object { - "layers": Object {}, - }, "textBased": Object { "layers": Object { "layer_0": Object { diff --git a/packages/kbn-lens-embeddable-utils/config_builder/charts/xy.test.ts b/packages/kbn-lens-embeddable-utils/config_builder/charts/xy.test.ts index d1646b4c0ec7..42dc00dc2ba2 100644 --- a/packages/kbn-lens-embeddable-utils/config_builder/charts/xy.test.ts +++ b/packages/kbn-lens-embeddable-utils/config_builder/charts/xy.test.ts @@ -87,9 +87,6 @@ test('generates metric chart config', async () => { "test": Object {}, }, "datasourceStates": Object { - "formBased": Object { - "layers": Object {}, - }, "textBased": Object { "layers": Object { "layer_0": Object { diff --git a/packages/kbn-lens-embeddable-utils/config_builder/utils.test.ts b/packages/kbn-lens-embeddable-utils/config_builder/utils.test.ts index 7709c6969b29..b4b7c7ddc484 100644 --- a/packages/kbn-lens-embeddable-utils/config_builder/utils.test.ts +++ b/packages/kbn-lens-embeddable-utils/config_builder/utils.test.ts @@ -199,9 +199,6 @@ describe('buildDatasourceStates', () => { ); expect(results).toMatchInlineSnapshot(` Object { - "formBased": Object { - "layers": Object {}, - }, "textBased": Object { "layers": Object { "layer_0": Object { diff --git a/packages/kbn-lens-embeddable-utils/config_builder/utils.ts b/packages/kbn-lens-embeddable-utils/config_builder/utils.ts index 21c48ca76a52..78434f8dbb10 100644 --- a/packages/kbn-lens-embeddable-utils/config_builder/utils.ts +++ b/packages/kbn-lens-embeddable-utils/config_builder/utils.ts @@ -191,10 +191,7 @@ export const buildDatasourceStates = async ( getValueColumns: (config: any, i: number) => TextBasedLayerColumn[], dataViewsAPI: DataViewsPublicPluginStart ) => { - const layers: LensAttributes['state']['datasourceStates'] = { - textBased: { layers: {} }, - formBased: { layers: {} }, - }; + let layers: Partial = {}; const mainDataset = config.dataset; const configLayers = 'layers' in config ? config.layers : [config]; @@ -226,7 +223,14 @@ export const buildDatasourceStates = async ( getValueColumns ); if (layerConfig) { - layers[type]!.layers[layerId] = layerConfig; + layers = { + ...layers, + [type]: { + layers: { + [layerId]: layerConfig, + }, + }, + }; } } } diff --git a/packages/kbn-optimizer/limits.yml b/packages/kbn-optimizer/limits.yml index d38e1399ed3a..9c96bfe371df 100644 --- a/packages/kbn-optimizer/limits.yml +++ b/packages/kbn-optimizer/limits.yml @@ -86,7 +86,7 @@ pageLoadAssetSize: kibanaUsageCollection: 16463 kibanaUtils: 79713 kubernetesSecurity: 77234 - lens: 41000 + lens: 42000 licenseManagement: 41817 licensing: 29004 links: 44490 diff --git a/src/plugins/event_annotation_listing/public/components/group_editor_flyout/group_preview.test.tsx b/src/plugins/event_annotation_listing/public/components/group_editor_flyout/group_preview.test.tsx index 09c7c5a26535..386976ac571b 100644 --- a/src/plugins/event_annotation_listing/public/components/group_editor_flyout/group_preview.test.tsx +++ b/src/plugins/event_annotation_listing/public/components/group_editor_flyout/group_preview.test.tsx @@ -237,7 +237,7 @@ describe('group editor preview', () => { const assertTimeField = (fieldName: string, attributes: TypedLensByValueInput['attributes']) => expect( ( - attributes.state.datasourceStates.formBased.layers[DATA_LAYER_ID].columns[ + attributes.state.datasourceStates.formBased?.layers[DATA_LAYER_ID].columns[ DATE_HISTOGRAM_COLUMN_ID ] as FieldBasedIndexPatternColumn ).sourceField diff --git a/src/plugins/event_annotation_listing/public/components/group_editor_flyout/lens_attributes.ts b/src/plugins/event_annotation_listing/public/components/group_editor_flyout/lens_attributes.ts index 7943b1d905b6..f9e56ded409b 100644 --- a/src/plugins/event_annotation_listing/public/components/group_editor_flyout/lens_attributes.ts +++ b/src/plugins/event_annotation_listing/public/components/group_editor_flyout/lens_attributes.ts @@ -146,7 +146,7 @@ export const getLensAttributes = (group: EventAnnotationGroupConfig, timeField: export const getCurrentTimeField = (attributes: TypedLensByValueInput['attributes']) => { return ( - attributes.state.datasourceStates.formBased.layers[DATA_LAYER_ID].columns[ + attributes.state.datasourceStates?.formBased?.layers[DATA_LAYER_ID].columns[ DATE_HISTOGRAM_COLUMN_ID ] as FieldBasedIndexPatternColumn ).sourceField; diff --git a/tsconfig.base.json b/tsconfig.base.json index d241aace3784..78c48a4acaff 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -968,6 +968,8 @@ "@kbn/lens-embeddable-utils/*": ["packages/kbn-lens-embeddable-utils/*"], "@kbn/lens-formula-docs": ["packages/kbn-lens-formula-docs"], "@kbn/lens-formula-docs/*": ["packages/kbn-lens-formula-docs/*"], + "@kbn/lens-inline-editing-example-plugin": ["x-pack/examples/lens_embeddable_inline_editing_example"], + "@kbn/lens-inline-editing-example-plugin/*": ["x-pack/examples/lens_embeddable_inline_editing_example/*"], "@kbn/lens-plugin": ["x-pack/plugins/lens"], "@kbn/lens-plugin/*": ["x-pack/plugins/lens/*"], "@kbn/license-api-guard-plugin": ["x-pack/plugins/license_api_guard"], diff --git a/x-pack/examples/lens_embeddable_inline_editing_example/.eslintrc.json b/x-pack/examples/lens_embeddable_inline_editing_example/.eslintrc.json new file mode 100644 index 000000000000..2aab6c2d9093 --- /dev/null +++ b/x-pack/examples/lens_embeddable_inline_editing_example/.eslintrc.json @@ -0,0 +1,5 @@ +{ + "rules": { + "@typescript-eslint/consistent-type-definitions": 0 + } +} diff --git a/x-pack/examples/lens_embeddable_inline_editing_example/README.md b/x-pack/examples/lens_embeddable_inline_editing_example/README.md new file mode 100644 index 000000000000..ae280f9a4c17 --- /dev/null +++ b/x-pack/examples/lens_embeddable_inline_editing_example/README.md @@ -0,0 +1,68 @@ +# Inline editing of Lens embeddable + +To run this example plugin, use the command `yarn start --run-examples`. + +This plugin contains examples on how to integrate the inline editing capabilities to your Lens embeddable. + +Steps: + * Add UIActions on your start dependencies + * On your embeddable use the onLoad callback to store in the local state the adapters and lensEmbeddableOutput$. + +```tsx + // my Lens embeddable + +``` + +```tsx + const [lensLoadEvent, setLensLoadEvent] = useState(null); + // my onLoad callback + const onLoad = useCallback( + ( + isLoading: boolean, + adapters: LensChartLoadEvent['adapters'] | undefined, + lensEmbeddableOutput$?: LensChartLoadEvent['embeddableOutput$'] + ) => { + const adapterTables = adapters?.tables?.tables; + if (adapterTables && !isLoading) { + setLensLoadEvent({ + adapters, + embeddableOutput$: lensEmbeddableOutput$, + }); + } + }, + [] + ); +``` + * Create the triggerOptions. You will need: + - The attributes of the lens embeddable input + - The lensChartEvent that you retrieved from the onLoad callback + - An onUpdate callback to update the embeddable input with the new attributes + - An optional onApply callback if you want to add an action when the Apply button is clicked + - An optional onCancel callback if you want to add an action when the Cancel button is clicked + +```tsx + // my trigger options + const triggerOptions = { + attributes: embeddableInput?.attributes, + lensEvent: lensLoadEvent, + onUpdate: (newAttributes: TypedLensByValueInput['attributes']) => { + // onUpdate I need to update my embeddableInput.attributes + }, + onApply: () => { + // optional callback when Apply button is clicked + }, + onCancel: () => { + // optional callback when Cancel button is clicked + }, + }; +``` + +* Add a button which will open the editing flyout. Execute the IN_APP_EMBEDDABLE_EDIT_TRIGGER trigger onClick +```tsx +uiActions.getTrigger('IN_APP_EMBEDDABLE_EDIT_TRIGGER').exec(triggerOptions); +``` + +### Important note +In case you don't want to open a push flyout you can pass an html element to the triggerOptions, the `container` property. This is going +to render the inline editing component to this container element. In that case you will need an extra handling on your side. +Check the 3rd example for implementation details. \ No newline at end of file diff --git a/x-pack/examples/lens_embeddable_inline_editing_example/kibana.jsonc b/x-pack/examples/lens_embeddable_inline_editing_example/kibana.jsonc new file mode 100644 index 000000000000..01540fe2de3a --- /dev/null +++ b/x-pack/examples/lens_embeddable_inline_editing_example/kibana.jsonc @@ -0,0 +1,21 @@ +{ + "type": "plugin", + "id": "@kbn/lens-inline-editing-example-plugin", + "owner": "@elastic/kibana-visualizations", + "plugin": { + "id": "inlineEditingLensExample", + "server": false, + "browser": true, + "configPath": [ + "lens_embeddable_inline_editing_example" + ], + "requiredPlugins": [ + "uiActions", + "lens", + "dataViews", + "embeddable", + "developerExamples", + "kibanaReact" + ] + } +} diff --git a/x-pack/examples/lens_embeddable_inline_editing_example/public/app.tsx b/x-pack/examples/lens_embeddable_inline_editing_example/public/app.tsx new file mode 100644 index 000000000000..8ff88af42b52 --- /dev/null +++ b/x-pack/examples/lens_embeddable_inline_editing_example/public/app.tsx @@ -0,0 +1,182 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useMemo, useState } from 'react'; +import ReactDOM from 'react-dom'; +import { css } from '@emotion/react'; +import { + EuiFlexGroup, + EuiFlexItem, + EuiPage, + EuiPageBody, + EuiPageHeader, + EuiPageSection, + EuiPanel, + EuiSpacer, + EuiButton, + EuiTitle, +} from '@elastic/eui'; +import type { CoreStart } from '@kbn/core/public'; +import { LensConfigBuilder } from '@kbn/lens-embeddable-utils/config_builder/config_builder'; +import type { DataView } from '@kbn/data-views-plugin/public'; +import type { LensPublicStart } from '@kbn/lens-plugin/public'; +import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; +import type { StartDependencies } from './plugin'; +import { LensChart } from './embeddable'; +import { MultiPaneFlyout } from './flyout'; + +export const App = (props: { + core: CoreStart; + plugins: StartDependencies; + defaultDataView: DataView; + stateHelpers: Awaited>; +}) => { + const [container, setContainer] = useState(null); + const [isFlyoutVisible, setIsFlyoutVisible] = useState(false); + const [isInlineEditingVisible, setIsinlineEditingVisible] = useState(false); + const [panelActive, setPanelActive] = useState(null); + + const configBuilder = useMemo( + () => new LensConfigBuilder(props.stateHelpers.formula, props.plugins.dataViews), + [props.plugins.dataViews, props.stateHelpers.formula] + ); + + return ( + + + + + + + + + + + + + + + +

    #3: Embeddable inside a flyout

    +
    + + +

    + In case you do not want to use a push flyout, you can check this example.{' '} +
    + In this example, we have a Lens embeddable inside a flyout and we want to + render the inline editing Component in a second slot of the same flyout. +

    +
    + + + + { + setIsFlyoutVisible(true); + setPanelActive(3); + }} + > + Show flyout + + {isFlyoutVisible ? ( + { + setIsinlineEditingVisible(false); + if (container) { + ReactDOM.unmountComponentAtNode(container); + } + }} + onCancelCb={() => { + setIsinlineEditingVisible(false); + if (container) { + ReactDOM.unmountComponentAtNode(container); + } + }} + isESQL + isActive + /> + ), + }} + inlineEditingContent={{ + visible: isInlineEditingVisible, + }} + setContainer={setContainer} + onClose={() => { + setIsFlyoutVisible(false); + setIsinlineEditingVisible(false); + setPanelActive(null); + if (container) { + ReactDOM.unmountComponentAtNode(container); + } + }} + /> + ) : null} + + +
    +
    +
    +
    +
    +
    +
    + ); +}; diff --git a/x-pack/examples/lens_embeddable_inline_editing_example/public/embeddable.tsx b/x-pack/examples/lens_embeddable_inline_editing_example/public/embeddable.tsx new file mode 100644 index 000000000000..717a8b2d20f8 --- /dev/null +++ b/x-pack/examples/lens_embeddable_inline_editing_example/public/embeddable.tsx @@ -0,0 +1,161 @@ +/* + * 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, { useState, useRef, useEffect, useCallback, useMemo } from 'react'; +import type { + TypedLensByValueInput, + InlineEditLensEmbeddableContext, +} from '@kbn/lens-plugin/public'; +import type { DataView } from '@kbn/data-views-plugin/public'; +import { css } from '@emotion/react'; +import { + EuiFlexGroup, + EuiFlexItem, + EuiSpacer, + EuiPanel, + EuiButtonIcon, + EuiTitle, +} from '@elastic/eui'; +import { LensConfigBuilder } from '@kbn/lens-embeddable-utils/config_builder/config_builder'; +import type { StartDependencies } from './plugin'; +import { getConfigOptions } from './utils'; + +export const LensChart = (props: { + configBuilder: LensConfigBuilder; + plugins: StartDependencies; + defaultDataView: DataView; + isESQL?: boolean; + container?: HTMLElement | null; + isActive?: boolean; + setPanelActive?: (panelNum: number | null) => void; + setIsinlineEditingVisible?: (flag: boolean) => void; + onApplyCb?: () => void; + onCancelCb?: () => void; +}) => { + const ref = useRef(false); + const [embeddableInput, setEmbeddableInput] = useState( + undefined + ); + const [lensLoadEvent, setLensLoadEvent] = useState< + InlineEditLensEmbeddableContext['lensEvent'] | null + >(null); + + const { config, options } = useMemo(() => { + return getConfigOptions(props.defaultDataView, props.isESQL); + }, [props.defaultDataView, props.isESQL]); + + useEffect(() => { + ref.current = true; + props.configBuilder.build(config, options).then((input) => { + if (ref.current) { + setEmbeddableInput(input as TypedLensByValueInput); + } + }); + return () => { + ref.current = false; + }; + }, [config, props.configBuilder, options, props.plugins.dataViews]); + + const onLoad = useCallback( + ( + isLoading: boolean, + adapters: InlineEditLensEmbeddableContext['lensEvent']['adapters'] | undefined, + lensEmbeddableOutput$?: InlineEditLensEmbeddableContext['lensEvent']['embeddableOutput$'] + ) => { + const adapterTables = adapters?.tables?.tables; + if (adapterTables && !isLoading) { + setLensLoadEvent({ + adapters, + embeddableOutput$: lensEmbeddableOutput$, + }); + } + }, + [] + ); + + const triggerOptions: InlineEditLensEmbeddableContext | undefined = useMemo(() => { + if (lensLoadEvent && embeddableInput?.attributes) { + return { + attributes: embeddableInput?.attributes, + lensEvent: lensLoadEvent, + onUpdate: (newAttributes: TypedLensByValueInput['attributes']) => { + if (embeddableInput) { + const newInput = { + ...embeddableInput, + attributes: newAttributes, + }; + setEmbeddableInput(newInput); + } + }, + onApply: () => { + 'optional onApply callback!'; + props.onApplyCb?.(); + props.setPanelActive?.(null); + }, + onCancel: () => { + 'optional onCancel callback!'; + props.onCancelCb?.(); + props.setPanelActive?.(null); + }, + container: props.container, + }; + } + }, [embeddableInput, lensLoadEvent, props]); + const LensComponent = props.plugins.lens.EmbeddableComponent; + + return ( + + +

    + {props.isESQL + ? '#1: Inline editing of an ES|QL chart.' + : '#2: Inline editing of a dataview chart.'} +

    +
    + + + + { + props?.setPanelActive?.(props.isESQL ? 1 : 2); + if (triggerOptions) { + props.plugins.uiActions + .getTrigger('IN_APP_EMBEDDABLE_EDIT_TRIGGER') + .exec(triggerOptions); + props?.setIsinlineEditingVisible?.(true); + } + }} + /> + + + {embeddableInput && ( + + )} + + +
    + ); +}; diff --git a/x-pack/examples/lens_embeddable_inline_editing_example/public/flyout.tsx b/x-pack/examples/lens_embeddable_inline_editing_example/public/flyout.tsx new file mode 100644 index 000000000000..f916abbad18f --- /dev/null +++ b/x-pack/examples/lens_embeddable_inline_editing_example/public/flyout.tsx @@ -0,0 +1,124 @@ +/* + * 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, useRef, useState } from 'react'; +import { css } from '@emotion/react'; +import { EuiFlexGroup, EuiFlexItem, EuiFlyout, EuiPanel } from '@elastic/eui'; +import { euiThemeVars } from '@kbn/ui-theme'; + +interface MainContent { + content: JSX.Element; +} + +interface InlineEditingContent { + visible?: boolean; +} + +interface Props { + mainContent: MainContent; + inlineEditingContent: InlineEditingContent; + setContainer?: (element: HTMLDivElement | null) => void; + onClose: () => void; +} + +export function MultiPaneFlyout({ + mainContent, + inlineEditingContent, + onClose, + setContainer, +}: Props) { + const [flexBasisCol1, setFlexBasisCol1] = useState('100%'); + const [flexBasisCol2, setFlexBasisCol2] = useState(!inlineEditingContent?.visible ? '0%' : '30%'); + + useEffect(() => { + setFlexBasisCol1(inlineEditingContent?.visible ? '70%' : '100%'); + setFlexBasisCol2(inlineEditingContent?.visible ? '30%' : '0%'); + }, [inlineEditingContent]); + + return ( + + + + + + + + {inlineEditingContent ? ( + + ) : null} + + + + ); +} + +function InlineEditingContent({ + visible, + setContainer, +}: { + visible?: boolean; + setContainer?: (element: HTMLDivElement | null) => void; +}) { + const containerRef = useRef(null); + const style = css` + padding: 0; + position: relative; + } +`; + + useEffect(() => { + if (containerRef?.current && setContainer) { + setContainer(containerRef.current); + } + }, [setContainer]); + return ( + + + + ); +} + +function MainContent({ content }: { content: JSX.Element }) { + const style = css` + padding-top: 12px; + padding-botton: 12px; + } + `; + + return ( + + {content} + + ); +} diff --git a/x-pack/examples/lens_embeddable_inline_editing_example/public/image.png b/x-pack/examples/lens_embeddable_inline_editing_example/public/image.png new file mode 100644 index 0000000000000000000000000000000000000000..a7b47acc8cac51aaaa6002f6a5e98c27c5008118 GIT binary patch literal 155151 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 literal 0 HcmV?d00001 diff --git a/x-pack/examples/lens_embeddable_inline_editing_example/public/index.ts b/x-pack/examples/lens_embeddable_inline_editing_example/public/index.ts new file mode 100644 index 000000000000..4a3eb7100ffb --- /dev/null +++ b/x-pack/examples/lens_embeddable_inline_editing_example/public/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 { LensInlineEditingPlugin } from './plugin'; + +export const plugin = () => new LensInlineEditingPlugin(); diff --git a/x-pack/examples/lens_embeddable_inline_editing_example/public/mount.tsx b/x-pack/examples/lens_embeddable_inline_editing_example/public/mount.tsx new file mode 100644 index 000000000000..411538e2df2c --- /dev/null +++ b/x-pack/examples/lens_embeddable_inline_editing_example/public/mount.tsx @@ -0,0 +1,49 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import * as React from 'react'; +import { render, unmountComponentAtNode } from 'react-dom'; +import { EuiCallOut } from '@elastic/eui'; + +import type { CoreSetup, AppMountParameters } from '@kbn/core/public'; +import type { StartDependencies } from './plugin'; + +export const mount = + (coreSetup: CoreSetup) => + async ({ element }: AppMountParameters) => { + const [core, plugins] = await coreSetup.getStartServices(); + const { App } = await import('./app'); + + const dataView = await plugins.dataViews.getDefaultDataView(); + const stateHelpers = await plugins.lens.stateHelperApi(); + + const i18nCore = core.i18n; + + const reactElement = ( + + {dataView ? ( + + ) : ( + +

    You need at least one dataview for this demo to work

    +
    + )} +
    + ); + + render(reactElement, element); + return () => unmountComponentAtNode(element); + }; diff --git a/x-pack/examples/lens_embeddable_inline_editing_example/public/plugin.ts b/x-pack/examples/lens_embeddable_inline_editing_example/public/plugin.ts new file mode 100644 index 000000000000..5d970e2667ff --- /dev/null +++ b/x-pack/examples/lens_embeddable_inline_editing_example/public/plugin.ts @@ -0,0 +1,57 @@ +/* + * 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 { Plugin, CoreSetup, AppNavLinkStatus } from '@kbn/core/public'; +import type { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public'; +import type { UiActionsStart } from '@kbn/ui-actions-plugin/public'; +import { LensPublicStart } from '@kbn/lens-plugin/public'; +import { DeveloperExamplesSetup } from '@kbn/developer-examples-plugin/public'; +import { mount } from './mount'; +import image from './image.png'; + +export interface SetupDependencies { + developerExamples: DeveloperExamplesSetup; +} + +export interface StartDependencies { + dataViews: DataViewsPublicPluginStart; + lens: LensPublicStart; + uiActions: UiActionsStart; +} + +export class LensInlineEditingPlugin + implements Plugin +{ + public setup(core: CoreSetup, { developerExamples }: SetupDependencies) { + core.application.register({ + id: 'lens_embeddable_inline_editing_example', + title: 'Lens inline editing embeddable', + navLinkStatus: AppNavLinkStatus.hidden, + mount: mount(core), + }); + + developerExamples.register({ + appId: 'lens_embeddable_inline_editing_example', + title: 'Lens inline editing embeddable', + description: 'Inline editing of a Lens embeddable examples', + links: [ + { + label: 'README', + href: 'https://github.com/elastic/kibana/tree/main/x-pack/examples/lens_embeddable_inline_editing_example', + iconType: 'logoGithub', + size: 's', + target: '_blank', + }, + ], + image, + }); + } + + public start() {} + + public stop() {} +} diff --git a/x-pack/examples/lens_embeddable_inline_editing_example/public/utils.ts b/x-pack/examples/lens_embeddable_inline_editing_example/public/utils.ts new file mode 100644 index 000000000000..f0069a543d36 --- /dev/null +++ b/x-pack/examples/lens_embeddable_inline_editing_example/public/utils.ts @@ -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 type { DataView } from '@kbn/data-views-plugin/public'; +import type { + LensConfig, + LensConfigOptions, +} from '@kbn/lens-embeddable-utils/config_builder/types'; + +export const getConfigOptions = (dataView: DataView, isESQL?: boolean) => { + const index = dataView.getIndexPattern(); + const timeFieldName = dataView.getTimeField()?.name; + if (isESQL) { + return { + config: { + chartType: 'metric', + title: 'metric chart', + dataset: { + esql: `from ${index} | stats count=count()`, + }, + value: 'count', + } as LensConfig, + options: { + embeddable: true, + timeRange: { + from: 'now-30d', + to: 'now', + type: 'relative', + }, + query: { + esql: `from ${index} | stats count=count()`, + }, + } as unknown as LensConfigOptions, + }; + } else { + return { + config: { + chartType: 'heatmap', + title: 'heatmap chart', + dataset: { + index, + timeFieldName, + }, + xAxis: { + type: 'dateHistogram', + field: timeFieldName, + }, + value: 'count()', + } as LensConfig, + options: { + embeddable: true, + timeRange: { + from: 'now-30d', + to: 'now', + type: 'relative', + }, + } as LensConfigOptions, + }; + } +}; diff --git a/x-pack/examples/lens_embeddable_inline_editing_example/tsconfig.json b/x-pack/examples/lens_embeddable_inline_editing_example/tsconfig.json new file mode 100644 index 000000000000..e4727650106b --- /dev/null +++ b/x-pack/examples/lens_embeddable_inline_editing_example/tsconfig.json @@ -0,0 +1,26 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types" + }, + "include": [ + "index.ts", + "public/**/*.ts", + "public/**/*.tsx", + "server/**/*.ts", + "../../../typings/**/*" + ], + "exclude": [ + "target/**/*", + ], + "kbn_references": [ + "@kbn/core", + "@kbn/lens-plugin", + "@kbn/developer-examples-plugin", + "@kbn/data-views-plugin", + "@kbn/ui-actions-plugin", + "@kbn/kibana-react-plugin", + "@kbn/lens-embeddable-utils", + "@kbn/ui-theme", + ] +} diff --git a/x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/configurations/lens_attributes.test.ts b/x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/configurations/lens_attributes.test.ts index bb36de888b40..75a5c42c7644 100644 --- a/x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/configurations/lens_attributes.test.ts +++ b/x-pack/plugins/exploratory_view/public/components/shared/exploratory_view/configurations/lens_attributes.test.ts @@ -118,7 +118,7 @@ describe('Lens Attribute', () => { ReportTypes.KPI ); - expect(lnsAttrKpi.getJSON().state.datasourceStates.formBased.layers.layer0.columns).toEqual({ + expect(lnsAttrKpi.getJSON().state.datasourceStates?.formBased?.layers.layer0.columns).toEqual({ 'x-axis-column-layer0': { dataType: 'date', isBucketed: true, diff --git a/x-pack/plugins/lens/public/app_plugin/shared/edit_on_the_fly/get_edit_lens_configuration.tsx b/x-pack/plugins/lens/public/app_plugin/shared/edit_on_the_fly/get_edit_lens_configuration.tsx index acef8feb6da5..0944326cf43c 100644 --- a/x-pack/plugins/lens/public/app_plugin/shared/edit_on_the_fly/get_edit_lens_configuration.tsx +++ b/x-pack/plugins/lens/public/app_plugin/shared/edit_on_the_fly/get_edit_lens_configuration.tsx @@ -117,6 +117,8 @@ export async function getEditLensConfiguration( isNewPanel, deletePanel, hidesSuggestions, + onApplyCb, + onCancelCb, }: EditLensConfigurationProps) => { if (!lensServices || !datasourceMap || !visualizationMap) { return ; @@ -212,6 +214,8 @@ export async function getEditLensConfiguration( setCurrentAttributes, isNewPanel, deletePanel, + onApplyCb, + onCancelCb, }; return getWrapper( diff --git a/x-pack/plugins/lens/public/app_plugin/shared/edit_on_the_fly/lens_configuration_flyout.tsx b/x-pack/plugins/lens/public/app_plugin/shared/edit_on_the_fly/lens_configuration_flyout.tsx index e3df96840c88..1aae97977d71 100644 --- a/x-pack/plugins/lens/public/app_plugin/shared/edit_on_the_fly/lens_configuration_flyout.tsx +++ b/x-pack/plugins/lens/public/app_plugin/shared/edit_on_the_fly/lens_configuration_flyout.tsx @@ -65,6 +65,8 @@ export function LensEditConfigurationFlyout({ isNewPanel, deletePanel, hidesSuggestions, + onApplyCb, + onCancelCb, }: EditConfigPanelProps) { const euiTheme = useEuiTheme(); const previousAttributes = useRef(attributes); @@ -173,6 +175,7 @@ export function LensEditConfigurationFlyout({ if (isNewPanel && deletePanel) { deletePanel(); } + onCancelCb?.(); closeFlyout?.(); }, [ attributesChanged, @@ -186,6 +189,7 @@ export function LensEditConfigurationFlyout({ updatePanelState, updateSuggestion, updateByRefInput, + onCancelCb, ]); const onApply = useCallback(() => { @@ -220,10 +224,12 @@ export function LensEditConfigurationFlyout({ saveByRef?.(attrs); updateByRefInput?.(savedObjectId); } + onApplyCb?.(); closeFlyout?.(); }, [ savedObjectId, closeFlyout, + onApplyCb, datasourceStates, visualization.state, activeVisualization, diff --git a/x-pack/plugins/lens/public/app_plugin/shared/edit_on_the_fly/types.ts b/x-pack/plugins/lens/public/app_plugin/shared/edit_on_the_fly/types.ts index 6b5a2bb50127..bb6b1157f43b 100644 --- a/x-pack/plugins/lens/public/app_plugin/shared/edit_on_the_fly/types.ts +++ b/x-pack/plugins/lens/public/app_plugin/shared/edit_on_the_fly/types.ts @@ -82,6 +82,10 @@ export interface EditConfigPanelProps { deletePanel?: () => void; /** If set to true the layout changes to accordion and the text based query (i.e. ES|QL) can be edited */ hidesSuggestions?: boolean; + /** Optional callback for apply flyout button */ + onApplyCb?: () => void; + /** Optional callback for cancel flyout button */ + onCancelCb?: () => void; } export interface LayerConfigurationProps { diff --git a/x-pack/plugins/lens/public/async_services.ts b/x-pack/plugins/lens/public/async_services.ts index 85724c871cda..28becae5e607 100644 --- a/x-pack/plugins/lens/public/async_services.ts +++ b/x-pack/plugins/lens/public/async_services.ts @@ -52,3 +52,4 @@ export * from './chart_info_api'; export * from './trigger_actions/open_in_discover_helpers'; export * from './trigger_actions/open_lens_config/edit_action_helpers'; export * from './trigger_actions/open_lens_config/create_action_helpers'; +export * from './trigger_actions/open_lens_config/in_app_embeddable_edit/in_app_embeddable_edit_action_helpers'; diff --git a/x-pack/plugins/lens/public/embeddable/embeddable_component.tsx b/x-pack/plugins/lens/public/embeddable/embeddable_component.tsx index 986f2f65c693..bdbcfb49617b 100644 --- a/x-pack/plugins/lens/public/embeddable/embeddable_component.tsx +++ b/x-pack/plugins/lens/public/embeddable/embeddable_component.tsx @@ -46,7 +46,7 @@ type LensAttributes = Omit< visualizationType: TVisType; state: Omit & { datasourceStates: { - formBased: FormBasedPersistedState; + formBased?: FormBasedPersistedState; textBased?: TextBasedPersistedState; }; visualization: TVisState; diff --git a/x-pack/plugins/lens/public/index.ts b/x-pack/plugins/lens/public/index.ts index c611952f44f0..a9f8e0eba3dc 100644 --- a/x-pack/plugins/lens/public/index.ts +++ b/x-pack/plugins/lens/public/index.ts @@ -106,6 +106,8 @@ export type { ReferenceLineLayerConfig, } from '@kbn/expression-xy-plugin/common'; +export type { InlineEditLensEmbeddableContext } from './trigger_actions/open_lens_config/in_app_embeddable_edit/types'; + export type { LensEmbeddableInput, LensSavedObjectAttributes, diff --git a/x-pack/plugins/lens/public/plugin.ts b/x-pack/plugins/lens/public/plugin.ts index 872e1a566ab2..61ffb1d0686d 100644 --- a/x-pack/plugins/lens/public/plugin.ts +++ b/x-pack/plugins/lens/public/plugin.ts @@ -107,6 +107,11 @@ import { getLensAliasConfig } from './vis_type_alias'; import { createOpenInDiscoverAction } from './trigger_actions/open_in_discover_action'; import { ConfigureInLensPanelAction } from './trigger_actions/open_lens_config/edit_action'; import { CreateESQLPanelAction } from './trigger_actions/open_lens_config/create_action'; +import { + inAppEmbeddableEditTrigger, + IN_APP_EMBEDDABLE_EDIT_TRIGGER, +} from './trigger_actions/open_lens_config/in_app_embeddable_edit/in_app_embeddable_edit_trigger'; +import { EditLensEmbeddableAction } from './trigger_actions/open_lens_config/in_app_embeddable_edit/in_app_embeddable_edit_action'; import { visualizeFieldAction } from './trigger_actions/visualize_field_actions'; import { visualizeTSVBAction } from './trigger_actions/visualize_tsvb_actions'; import { visualizeAggBasedVisAction } from './trigger_actions/visualize_agg_based_vis_actions'; @@ -575,6 +580,10 @@ export class LensPlugin { if (startDependencies.uiActions.hasAction(ACTION_VISUALIZE_FIELD)) { startDependencies.uiActions.unregisterAction(ACTION_VISUALIZE_FIELD); } + + // this trigger enables external consumers to use the inline editing flyout + startDependencies.uiActions.registerTrigger(inAppEmbeddableEditTrigger); + startDependencies.uiActions.addTriggerAction( VISUALIZE_FIELD_TRIGGER, visualizeFieldAction(core.application) @@ -600,8 +609,17 @@ export class LensPlugin { core.overlays, core.theme ); + // dashboard edit panel action startDependencies.uiActions.addTriggerAction('CONTEXT_MENU_TRIGGER', editInLensAction); + // Allows the Lens embeddable to easily open the inapp editing flyout + const editLensEmbeddableAction = new EditLensEmbeddableAction(startDependencies, core); + // embeddable edit panel action + startDependencies.uiActions.addTriggerAction( + IN_APP_EMBEDDABLE_EDIT_TRIGGER, + editLensEmbeddableAction + ); + // Displays the add ESQL panel in the dashboard add Panel menu const createESQLPanelAction = new CreateESQLPanelAction(startDependencies, core); startDependencies.uiActions.addTriggerAction('ADD_PANEL_TRIGGER', createESQLPanelAction); diff --git a/x-pack/plugins/lens/public/trigger_actions/open_lens_config/in_app_embeddable_edit/in_app_embeddable_edit_action.test.tsx b/x-pack/plugins/lens/public/trigger_actions/open_lens_config/in_app_embeddable_edit/in_app_embeddable_edit_action.test.tsx new file mode 100644 index 000000000000..a6c7a8bcf6bc --- /dev/null +++ b/x-pack/plugins/lens/public/trigger_actions/open_lens_config/in_app_embeddable_edit/in_app_embeddable_edit_action.test.tsx @@ -0,0 +1,97 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import type { CoreStart } from '@kbn/core/public'; +import { coreMock } from '@kbn/core/public/mocks'; +import type { LensPluginStartDependencies } from '../../../plugin'; +import { createMockStartDependencies } from '../../../editor_frame_service/mocks'; +import type { TypedLensByValueInput } from '../../../embeddable/embeddable_component'; +import { EditLensEmbeddableAction } from './in_app_embeddable_edit_action'; + +describe('inapp editing of Lens embeddable', () => { + const core = coreMock.createStart(); + const mockStartDependencies = + createMockStartDependencies() as unknown as LensPluginStartDependencies; + describe('compatibility check', () => { + const attributes = { + title: 'An extremely cool default document!', + expression: 'definitely a valid expression', + visualizationType: 'testVis', + state: { + query: { esql: 'from test' }, + filters: [{ query: { match_phrase: { src: 'test' } }, meta: { index: 'index-pattern-0' } }], + datasourceStates: { + testDatasource: 'datasource', + }, + visualization: {}, + }, + references: [{ type: 'index-pattern', id: '1', name: 'index-pattern-0' }], + } as unknown as TypedLensByValueInput['attributes']; + it('is incompatible for ESQL charts and if ui setting for ES|QL is off', async () => { + const inAppEditAction = new EditLensEmbeddableAction(mockStartDependencies, core); + const context = { + attributes, + lensEvent: { + adapters: {}, + embeddableOutput$: undefined, + }, + onUpdate: jest.fn(), + }; + const isCompatible = await inAppEditAction.isCompatible(context); + + expect(isCompatible).toBeFalsy(); + }); + + it('is compatible for ESQL charts and if ui setting for ES|QL is on', async () => { + const updatedCore = { + ...core, + uiSettings: { + ...core.uiSettings, + get: (setting: string) => { + return setting === 'discover:enableESQL'; + }, + }, + } as CoreStart; + const inAppEditAction = new EditLensEmbeddableAction(mockStartDependencies, updatedCore); + const context = { + attributes, + lensEvent: { + adapters: {}, + embeddableOutput$: undefined, + }, + onUpdate: jest.fn(), + }; + const isCompatible = await inAppEditAction.isCompatible(context); + + expect(isCompatible).toBeTruthy(); + }); + + it('is compatible for dataview charts', async () => { + const inAppEditAction = new EditLensEmbeddableAction(mockStartDependencies, core); + const newAttributes = { + ...attributes, + state: { + ...attributes.state, + query: { + language: 'kuery', + query: '', + }, + }, + }; + const context = { + attributes: newAttributes, + lensEvent: { + adapters: {}, + embeddableOutput$: undefined, + }, + onUpdate: jest.fn(), + }; + const isCompatible = await inAppEditAction.isCompatible(context); + + expect(isCompatible).toBeTruthy(); + }); + }); +}); diff --git a/x-pack/plugins/lens/public/trigger_actions/open_lens_config/in_app_embeddable_edit/in_app_embeddable_edit_action.tsx b/x-pack/plugins/lens/public/trigger_actions/open_lens_config/in_app_embeddable_edit/in_app_embeddable_edit_action.tsx new file mode 100644 index 000000000000..c132b5e88c6c --- /dev/null +++ b/x-pack/plugins/lens/public/trigger_actions/open_lens_config/in_app_embeddable_edit/in_app_embeddable_edit_action.tsx @@ -0,0 +1,64 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { i18n } from '@kbn/i18n'; +import type { CoreStart } from '@kbn/core/public'; +import { Action } from '@kbn/ui-actions-plugin/public'; +import type { LensPluginStartDependencies } from '../../../plugin'; +import type { InlineEditLensEmbeddableContext } from './types'; + +const ACTION_EDIT_LENS_EMBEDDABLE = 'ACTION_EDIT_LENS_EMBEDDABLE'; + +export const getAsyncHelpers = async () => await import('../../../async_services'); + +export class EditLensEmbeddableAction implements Action { + public type = ACTION_EDIT_LENS_EMBEDDABLE; + public id = ACTION_EDIT_LENS_EMBEDDABLE; + public order = 50; + + constructor( + protected readonly startDependencies: LensPluginStartDependencies, + protected readonly core: CoreStart + ) {} + + public getDisplayName(): string { + return i18n.translate('xpack.lens.app.editLensEmbeddableLabel', { + defaultMessage: 'Edit visualization', + }); + } + + public getIconType() { + return 'pencil'; + } + + public async isCompatible({ attributes }: InlineEditLensEmbeddableContext) { + const { isEmbeddableEditActionCompatible } = await getAsyncHelpers(); + return isEmbeddableEditActionCompatible(this.core, attributes); + } + + public async execute({ + attributes, + lensEvent, + container, + onUpdate, + onApply, + onCancel, + }: InlineEditLensEmbeddableContext) { + const { executeEditEmbeddableAction } = await getAsyncHelpers(); + if (attributes) { + executeEditEmbeddableAction({ + deps: this.startDependencies, + core: this.core, + attributes, + lensEvent, + container, + onUpdate, + onApply, + onCancel, + }); + } + } +} diff --git a/x-pack/plugins/lens/public/trigger_actions/open_lens_config/in_app_embeddable_edit/in_app_embeddable_edit_action_helpers.tsx b/x-pack/plugins/lens/public/trigger_actions/open_lens_config/in_app_embeddable_edit/in_app_embeddable_edit_action_helpers.tsx new file mode 100644 index 000000000000..584aa7aaf132 --- /dev/null +++ b/x-pack/plugins/lens/public/trigger_actions/open_lens_config/in_app_embeddable_edit/in_app_embeddable_edit_action_helpers.tsx @@ -0,0 +1,154 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import React from 'react'; +import ReactDOM from 'react-dom'; +import type { CoreStart } from '@kbn/core/public'; +import { isOfAggregateQueryType } from '@kbn/es-query'; +import { toMountPoint } from '@kbn/kibana-react-plugin/public'; +import { IncompatibleActionError } from '@kbn/ui-actions-plugin/public'; +import type { LensPluginStartDependencies } from '../../../plugin'; +import type { TypedLensByValueInput } from '../../../embeddable/embeddable_component'; +import { extractReferencesFromState } from '../../../utils'; +import type { LensChartLoadEvent } from './types'; + +export function isEmbeddableEditActionCompatible( + core: CoreStart, + attributes: TypedLensByValueInput['attributes'] +) { + // for ES|QL is compatible only when advanced setting is enabled + const query = attributes.state.query; + return isOfAggregateQueryType(query) ? core.uiSettings.get('discover:enableESQL') : true; +} + +export async function executeEditEmbeddableAction({ + deps, + core, + attributes, + lensEvent, + container, + onUpdate, + onApply, + onCancel, +}: { + deps: LensPluginStartDependencies; + core: CoreStart; + attributes: TypedLensByValueInput['attributes']; + lensEvent: LensChartLoadEvent; + container?: HTMLElement | null; + onUpdate: (newAttributes: TypedLensByValueInput['attributes']) => void; + onApply?: () => void; + onCancel?: () => void; +}) { + const isCompatibleAction = isEmbeddableEditActionCompatible(core, attributes); + if (!isCompatibleAction) { + throw new IncompatibleActionError(); + } + + const { getEditLensConfiguration, getVisualizationMap, getDatasourceMap } = await import( + '../../../async_services' + ); + const visualizationMap = getVisualizationMap(); + const datasourceMap = getDatasourceMap(); + const query = attributes.state.query; + const activeDatasourceId = isOfAggregateQueryType(query) ? 'textBased' : 'formBased'; + + const onUpdatePanelState = ( + datasourceState: unknown, + visualizationState: unknown, + visualizationType?: string + ) => { + if (attributes.state) { + const datasourceStates = { + ...attributes.state.datasourceStates, + [activeDatasourceId]: datasourceState, + }; + + const references = extractReferencesFromState({ + activeDatasources: Object.keys(datasourceStates).reduce( + (acc, datasourceId) => ({ + ...acc, + [datasourceId]: datasourceMap[datasourceId], + }), + {} + ), + datasourceStates: Object.fromEntries( + Object.entries(datasourceStates).map(([id, state]) => [id, { isLoading: false, state }]) + ), + visualizationState, + activeVisualization: visualizationType ? visualizationMap[visualizationType] : undefined, + }); + + const attrs = { + ...attributes, + state: { + ...attributes.state, + visualization: visualizationState, + datasourceStates, + }, + references, + visualizationType: visualizationType ?? attributes.visualizationType, + } as TypedLensByValueInput['attributes']; + + onUpdate(attrs); + } + }; + + const onUpdateSuggestion = (attrs: TypedLensByValueInput['attributes']) => { + const newAttributes = { + ...attributes, + ...attrs, + }; + onUpdate(newAttributes); + }; + + const Component = await getEditLensConfiguration(core, deps, visualizationMap, datasourceMap); + const ConfigPanel = ( + + ); + + // in case an element is given render the component in the container, + // otherwise a flyout will open + if (container) { + ReactDOM.render(ConfigPanel, container); + } else { + const handle = core.overlays.openFlyout( + toMountPoint( + React.cloneElement(ConfigPanel, { + closeFlyout: () => { + handle.close(); + }, + }), + { + theme$: core.theme.theme$, + } + ), + { + className: 'lnsConfigPanel__overlay', + size: 's', + 'data-test-subj': 'customizeLens', + type: 'push', + paddingSize: 'm', + hideCloseButton: true, + onClose: (overlayRef) => { + overlayRef.close(); + }, + outsideClickCloses: true, + } + ); + } +} diff --git a/x-pack/plugins/lens/public/trigger_actions/open_lens_config/in_app_embeddable_edit/in_app_embeddable_edit_trigger.ts b/x-pack/plugins/lens/public/trigger_actions/open_lens_config/in_app_embeddable_edit/in_app_embeddable_edit_trigger.ts new file mode 100644 index 000000000000..41bd24e6a62e --- /dev/null +++ b/x-pack/plugins/lens/public/trigger_actions/open_lens_config/in_app_embeddable_edit/in_app_embeddable_edit_trigger.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 { i18n } from '@kbn/i18n'; +import type { Trigger } from '@kbn/ui-actions-plugin/public'; + +export const IN_APP_EMBEDDABLE_EDIT_TRIGGER = 'IN_APP_EMBEDDABLE_EDIT_TRIGGER'; +export const inAppEmbeddableEditTrigger: Trigger = { + id: IN_APP_EMBEDDABLE_EDIT_TRIGGER, + title: i18n.translate('xpack.lens.inAppEditTrigger.title', { + defaultMessage: 'In-app embeddable edit', + }), + description: i18n.translate('xpack.lens.inAppEditTrigger.description', { + defaultMessage: 'Triggers an in app flyout on the current embeddable', + }), +}; diff --git a/x-pack/plugins/lens/public/trigger_actions/open_lens_config/in_app_embeddable_edit/types.ts b/x-pack/plugins/lens/public/trigger_actions/open_lens_config/in_app_embeddable_edit/types.ts new file mode 100644 index 000000000000..e1eadf7a3266 --- /dev/null +++ b/x-pack/plugins/lens/public/trigger_actions/open_lens_config/in_app_embeddable_edit/types.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 type { DefaultInspectorAdapters } from '@kbn/expressions-plugin/common'; +import type { EmbeddableOutput } from '@kbn/embeddable-plugin/public'; +import type { Observable } from 'rxjs'; +import type { TypedLensByValueInput } from '../../../embeddable/embeddable_component'; + +export interface LensChartLoadEvent { + /** + * Inspector adapters for the request + */ + adapters: Partial; + /** + * Observable of the lens embeddable output + */ + embeddableOutput$?: Observable; +} + +export interface InlineEditLensEmbeddableContext { + // attributes of the Lens embeddable + attributes: TypedLensByValueInput['attributes']; + // chart event, can be fetched from the onLoad embeddable callback + lensEvent: LensChartLoadEvent; + // callback which runs every time something changes in the dimension panel + onUpdate: (newAttributes: TypedLensByValueInput['attributes']) => void; + // optional onApply callback + onApply?: () => void; + // optional onCancel callback + onCancel?: () => void; + // custom container element, use in case you need to render outside a flyout + // in that case, the styling is responsibility of the consumer + container?: HTMLElement | null; +} diff --git a/x-pack/plugins/lens/readme.md b/x-pack/plugins/lens/readme.md index 764ff5f2df04..fc2fd5df4c85 100644 --- a/x-pack/plugins/lens/readme.md +++ b/x-pack/plugins/lens/readme.md @@ -271,3 +271,11 @@ Lens has a lot of UI elements – to make it easier to refer to them in issues o * **Suggestion panel** Panel to the bottom showing previews for suggestions on how to change the current chart ![Layout](./layout.png "Layout") + + +# Inline Editing of a Lens Embeddable + +If you have a Lens embeddable in your application and you want to allow inline editing you can do it with 3 ways: +- If you use a portable dashboard, the functionality is built in and you don't need to do anything +- If you don't have a portable dashboard then you can use UI actions to retrieve the inline editing component. For more information check out the example in `x-pack/examples/lens_embeddable_inline_editing_example`. +- The component is also exported from Lens start contract. Check the `EditLensConfigPanelApi`. This is advised to be used only when the 2 above cases can't be used. \ No newline at end of file diff --git a/x-pack/plugins/security_solution/public/entity_analytics/components/risk_summary_flyout/risk_summary.test.tsx b/x-pack/plugins/security_solution/public/entity_analytics/components/risk_summary_flyout/risk_summary.test.tsx index 1946c12aacdc..b0ee36eff074 100644 --- a/x-pack/plugins/security_solution/public/entity_analytics/components/risk_summary_flyout/risk_summary.test.tsx +++ b/x-pack/plugins/security_solution/public/entity_analytics/components/risk_summary_flyout/risk_summary.test.tsx @@ -102,7 +102,9 @@ describe('RiskSummary', () => { const lensAttributes: LensAttributes = mockVisualizationEmbeddable.mock.calls[0][0].lensAttributes; - const datasourceLayers = Object.values(lensAttributes.state.datasourceStates.formBased.layers); + const datasourceLayers = Object.values( + lensAttributes.state.datasourceStates.formBased?.layers ?? {} + ); const firstColumn = Object.values(datasourceLayers[0].columns)[0]; expect(lensAttributes.state.query.query).toEqual('host.name: test'); @@ -126,7 +128,9 @@ describe('RiskSummary', () => { const lensAttributes: LensAttributes = mockVisualizationEmbeddable.mock.calls[0][0].lensAttributes; - const datasourceLayers = Object.values(lensAttributes.state.datasourceStates.formBased.layers); + const datasourceLayers = Object.values( + lensAttributes.state.datasourceStates.formBased?.layers ?? {} + ); const firstColumn = Object.values(datasourceLayers[0].columns)[0]; expect(lensAttributes.state.query.query).toEqual('user.name: test'); diff --git a/yarn.lock b/yarn.lock index 28057e7c10d9..9a5867e2361b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4986,6 +4986,9 @@ version "0.0.0" uid "" +"@kbn/lens-inline-editing-example-plugin@link:x-pack/examples/lens_embeddable_inline_editing_example": + + "@kbn/lens-plugin@link:x-pack/plugins/lens": version "0.0.0" uid "" From 35cccc29631e199979e6887eaf469444b285f637 Mon Sep 17 00:00:00 2001 From: Maxim Palenov Date: Fri, 5 Jan 2024 14:26:30 +0100 Subject: [PATCH 32/57] [Security Solution] OpenAPI linter (#171851) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit **Resolves: https://github.com/elastic/security-team/issues/8099** ## Summary This PR adds an a command to lint OpenAPI specs defined in Security Solution plugin. ## Details We have a number of OpenAPI specs defined in Security Solution plugin. While `@kbn/openapi-generator` package processes the specs and makes sure the specs are parsable and processable we don't have proper specs linter set up. This PR introduces OpenAPI specs linting by leveraging [Redocly CLI](https://github.com/Redocly/redocly-cli)'s `lint` command with a custom configuration placed in `@kbn/openapi-generator` package . Configuration includes reasonable best practices by using [built-in Redocly rules](https://redocly.com/docs/cli/rules/built-in-rules/). The lint utility fulfil the following requirements - Validates yaml files against OpenAPI specification. It supports `3.0` and `3.1`. - Validates `x-modify` property to have only `partial`, `required` or `requiredOptional` values. - Checks for reasonable best practices and displays a warning message when it's not met. Reasonable best practices are based on the [recommended ruleset](https://redocly.com/docs/cli/rules/recommended/#recommended-ruleset). The lint utility has been incorporated into the existing OpenAPI generator, and linting is performed before generation. ### Tool selection [Swagger CLI](https://github.com/APIDevTools/swagger-cli) is a well known tool to validate OpenAPI specs. On November 15th 2023 the repo has been archived with a message in README > ⚠️ Swagger CLI has been deprecated, due to the maintenance burnden of trying to keep up with expectations of a huge userbase with little to no pull requests or support. [Redocly CLI](https://redocly.com/redocly-cli/) covers all of the same functionality, and has more advanced linting with custom rules, and we highly recommend using that instead. They have conveniently provided a [migration guide](https://redocly.com/docs/cli/guides/migrate-from-swagger-cli/) for existing Swagger CLI users. Read the review of [Redocly CLI from APIs You Won't Hate](https://apisyouwonthate.com/blog/redocly-cli/). Taking it into account choice falls on **Redocly CLI**. ## How to test? Change directory to Security Solution plugin's root and run linting by using the following commands from Kibana root ```sh cd x-pack/plugins/security_solution yarn openapi:generate ``` --------- Co-authored-by: Georgii Gorbachev --- package.json | 1 + packages/kbn-openapi-generator/index.ts | 1 + .../redocly_linter/config.yaml | 27 + .../extra_linter_rules_plugin.js | 49 ++ packages/kbn-openapi-generator/src/cli.ts | 5 + .../src/openapi_generator.ts | 11 +- .../src/openapi_linter.ts | 47 ++ src/dev/license_checker/config.ts | 2 +- src/dev/yarn_deduplicate/index.ts | 2 +- .../osquery/scripts/openapi/generate.js | 2 + .../create_asset_criticality.schema.yaml | 3 +- .../delete_asset_criticality.schema.yaml | 3 +- .../get_asset_criticality.schema.yaml | 3 +- ...t_asset_criticality_privileges.schema.yaml | 3 +- .../get_asset_criticality_status.schema.yaml | 1 + x-pack/plugins/security_solution/package.json | 2 +- yarn.lock | 515 ++++++++++++++++-- 17 files changed, 620 insertions(+), 57 deletions(-) create mode 100644 packages/kbn-openapi-generator/redocly_linter/config.yaml create mode 100644 packages/kbn-openapi-generator/redocly_linter/extra_linter_rules_plugin.js create mode 100644 packages/kbn-openapi-generator/src/openapi_linter.ts diff --git a/package.json b/package.json index 0a4d9ebfcebd..23e49b0d4cb3 100644 --- a/package.json +++ b/package.json @@ -1307,6 +1307,7 @@ "@octokit/rest": "^16.35.0", "@openpgp/web-stream-tools": "^0.0.10", "@parcel/watcher": "^2.1.0", + "@redocly/cli": "^1.6.0", "@storybook/addon-a11y": "^6.5.16", "@storybook/addon-actions": "^6.5.16", "@storybook/addon-controls": "^6.5.16", diff --git a/packages/kbn-openapi-generator/index.ts b/packages/kbn-openapi-generator/index.ts index eeaad5343dc9..711ee4b6269d 100644 --- a/packages/kbn-openapi-generator/index.ts +++ b/packages/kbn-openapi-generator/index.ts @@ -6,5 +6,6 @@ * Side Public License, v 1. */ +export * from './src/openapi_linter'; export * from './src/openapi_generator'; export * from './src/cli'; diff --git a/packages/kbn-openapi-generator/redocly_linter/config.yaml b/packages/kbn-openapi-generator/redocly_linter/config.yaml new file mode 100644 index 000000000000..b423d9172b1c --- /dev/null +++ b/packages/kbn-openapi-generator/redocly_linter/config.yaml @@ -0,0 +1,27 @@ +# Recommended Redocly CLI ruleset https://redocly.com/docs/cli/rules/recommended/#recommended-ruleset +# Redocly CLI custom plugins https://redocly.com/docs/cli/custom-plugins/ +plugins: + - extra_linter_rules_plugin.js + +rules: + spec: error + spec-strict-refs: warn + no-path-trailing-slash: error + no-identical-paths: error + no-ambiguous-paths: warn + no-unresolved-refs: error + no-enum-type-mismatch: error + component-name-unique: error + path-declaration-must-exist: error + path-not-include-query: error + path-parameters-defined: warn + operation-description: warn + operation-2xx-response: error + operation-4xx-response: warn + operation-operationId: error + operation-operationId-unique: error + operation-summary: warn + operation-operationId-url-safe: error + operation-parameters-unique: error + boolean-parameter-prefixes: warn + extra-linter-rules-plugin/valid-x-modify: error diff --git a/packages/kbn-openapi-generator/redocly_linter/extra_linter_rules_plugin.js b/packages/kbn-openapi-generator/redocly_linter/extra_linter_rules_plugin.js new file mode 100644 index 000000000000..caef408c366b --- /dev/null +++ b/packages/kbn-openapi-generator/redocly_linter/extra_linter_rules_plugin.js @@ -0,0 +1,49 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 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 KNOWN_X_MODIFY_VALUES = ['partial', 'required', 'requiredOptional']; + +function ValidXModify() { + return { + any: { + leave(node, ctx) { + if (typeof node !== 'object' || !('x-modify' in node)) { + return; + } + + if (!KNOWN_X_MODIFY_VALUES.includes(node['x-modify'])) + ctx.report({ + message: `Only ${KNOWN_X_MODIFY_VALUES.join(', ')} can be used for x-modify`, + location: ctx.location.child('x-modify'), + }); + }, + }, + ref: { + leave(node, ctx) { + if (typeof node !== 'object' || !('x-modify' in node)) { + return; + } + + if (!KNOWN_X_MODIFY_VALUES.includes(node['x-modify'])) + ctx.report({ + message: `Only ${KNOWN_X_MODIFY_VALUES.join(', ')} can be used for x-modify`, + location: ctx.location.child('x-modify'), + }); + }, + }, + }; +} + +module.exports = { + id: 'extra-linter-rules-plugin', + rules: { + oas3: { + 'valid-x-modify': ValidXModify, + }, + }, +}; diff --git a/packages/kbn-openapi-generator/src/cli.ts b/packages/kbn-openapi-generator/src/cli.ts index 9eb91dd9bba9..6361c0a20de3 100644 --- a/packages/kbn-openapi-generator/src/cli.ts +++ b/packages/kbn-openapi-generator/src/cli.ts @@ -31,6 +31,11 @@ export function runCli() { default: 'zod_operation_schema' as const, choices: AVAILABLE_TEMPLATES, }) + .option('skipLinting', { + describe: 'Whether linting should be skipped', + type: 'boolean', + default: false, + }) .showHelpOnFail(false), (argv) => { generate(argv).catch((err) => { diff --git a/packages/kbn-openapi-generator/src/openapi_generator.ts b/packages/kbn-openapi-generator/src/openapi_generator.ts index 539994a25812..60efd762dade 100644 --- a/packages/kbn-openapi-generator/src/openapi_generator.ts +++ b/packages/kbn-openapi-generator/src/openapi_generator.ts @@ -17,6 +17,7 @@ import { fixEslint } from './lib/fix_eslint'; import { formatOutput } from './lib/format_output'; import { getGeneratedFilePath } from './lib/get_generated_file_path'; import { removeGenArtifacts } from './lib/remove_gen_artifacts'; +import { lint } from './openapi_linter'; import { getGenerationContext } from './parser/get_generation_context'; import type { OpenApiDocument } from './parser/openapi_types'; import { initTemplateService, TemplateName } from './template_service/template_service'; @@ -25,10 +26,18 @@ export interface GeneratorConfig { rootDir: string; sourceGlob: string; templateName: TemplateName; + skipLinting?: boolean; } export const generate = async (config: GeneratorConfig) => { - const { rootDir, sourceGlob, templateName } = config; + const { rootDir, sourceGlob, templateName, skipLinting } = config; + + if (!skipLinting) { + await lint({ + rootDir, + sourceGlob, + }); + } console.log(chalk.bold(`Generating API route schemas`)); console.log(chalk.bold(`Working directory: ${chalk.underline(rootDir)}`)); diff --git a/packages/kbn-openapi-generator/src/openapi_linter.ts b/packages/kbn-openapi-generator/src/openapi_linter.ts new file mode 100644 index 000000000000..afd31a77bdee --- /dev/null +++ b/packages/kbn-openapi-generator/src/openapi_linter.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. + */ + +/* eslint-disable no-console */ + +import { resolve } from 'path'; +import globby from 'globby'; +import execa from 'execa'; +import chalk from 'chalk'; +import { REPO_ROOT } from '@kbn/repo-info'; + +export interface LinterConfig { + rootDir: string; + sourceGlob: string; +} + +export const lint = async (config: LinterConfig) => { + const { rootDir, sourceGlob } = config; + + const sourceFilesGlob = resolve(rootDir, sourceGlob); + const schemaPaths = await globby([sourceFilesGlob]); + + console.log(chalk.bold(`Linting API route schemas`)); + + try { + await execa( + './node_modules/.bin/redocly', + [ + 'lint', + '--config=packages/kbn-openapi-generator/redocly_linter/config.yaml', + ...schemaPaths, + ], + { + cwd: REPO_ROOT, + stderr: process.stderr, + stdout: process.stdout, + } + ); + } catch { + throw new Error('Linter failed'); + } +}; diff --git a/src/dev/license_checker/config.ts b/src/dev/license_checker/config.ts index 6ba5deb6408a..db69bab07e1e 100644 --- a/src/dev/license_checker/config.ts +++ b/src/dev/license_checker/config.ts @@ -73,7 +73,7 @@ export const LICENSE_ALLOWED = [ // The following list only applies to licenses that // we wanna allow in packages only used as dev dependencies -export const DEV_ONLY_LICENSE_ALLOWED = ['MPL-2.0']; +export const DEV_ONLY_LICENSE_ALLOWED = ['MPL-2.0', '(MPL-2.0 OR Apache-2.0)']; // there are some licenses which should not be globally allowed // but can be brought in on a per-package basis diff --git a/src/dev/yarn_deduplicate/index.ts b/src/dev/yarn_deduplicate/index.ts index 13c12ac5e91b..1b1bade3b8b2 100644 --- a/src/dev/yarn_deduplicate/index.ts +++ b/src/dev/yarn_deduplicate/index.ts @@ -16,7 +16,7 @@ const yarnLock = readFileSync(yarnLockFile, 'utf-8'); const output = fixDuplicates(yarnLock, { useMostCommon: false, excludeScopes: ['@types'], - excludePackages: ['axe-core', '@babel/types'], + excludePackages: ['axe-core', '@babel/types', 'csstype'], }); writeFileSync(yarnLockFile, output); diff --git a/x-pack/plugins/osquery/scripts/openapi/generate.js b/x-pack/plugins/osquery/scripts/openapi/generate.js index 018a965702c3..35c099301e81 100644 --- a/x-pack/plugins/osquery/scripts/openapi/generate.js +++ b/x-pack/plugins/osquery/scripts/openapi/generate.js @@ -17,4 +17,6 @@ generate({ rootDir: OSQUERY_ROOT, sourceGlob: './**/*.schema.yaml', templateName: 'zod_operation_schema', + // TODO: Fix lint errors + skipLinting: true, }); diff --git a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/create_asset_criticality.schema.yaml b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/create_asset_criticality.schema.yaml index bb5e68215506..cc8c980809f9 100644 --- a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/create_asset_criticality.schema.yaml +++ b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/create_asset_criticality.schema.yaml @@ -12,6 +12,7 @@ servers: paths: /internal/asset_criticality: post: + operationId: AssetCriticalityCreateRecord summary: Create Criticality Record requestBody: required: true @@ -27,4 +28,4 @@ paths: schema: $ref: './common.schema.yaml#/components/schemas/AssetCriticalityRecord' '400': - description: Invalid request \ No newline at end of file + description: Invalid request diff --git a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/delete_asset_criticality.schema.yaml b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/delete_asset_criticality.schema.yaml index fbdb4feb19e5..cada6a62fcaa 100644 --- a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/delete_asset_criticality.schema.yaml +++ b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/delete_asset_criticality.schema.yaml @@ -12,6 +12,7 @@ servers: paths: /internal/asset_criticality: delete: + operationId: AssetCriticalityDeleteRecord summary: Delete Criticality Record parameters: - $ref: './common.schema.yaml#/components/parameters/id_value' @@ -20,4 +21,4 @@ paths: '200': description: Successful response '400': - description: Invalid request \ No newline at end of file + description: Invalid request diff --git a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/get_asset_criticality.schema.yaml b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/get_asset_criticality.schema.yaml index 1411f2a08734..777666daccb2 100644 --- a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/get_asset_criticality.schema.yaml +++ b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/get_asset_criticality.schema.yaml @@ -12,6 +12,7 @@ servers: paths: /internal/asset_criticality: get: + operationId: AssetCriticalityGetRecord summary: Get Criticality Record parameters: - $ref: './common.schema.yaml#/components/parameters/id_value' @@ -26,4 +27,4 @@ paths: '400': description: Invalid request '404': - description: Criticality record not found \ No newline at end of file + description: Criticality record not found diff --git a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/get_asset_criticality_privileges.schema.yaml b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/get_asset_criticality_privileges.schema.yaml index b877b90efca9..6f1734262c66 100644 --- a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/get_asset_criticality_privileges.schema.yaml +++ b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/get_asset_criticality_privileges.schema.yaml @@ -12,6 +12,7 @@ servers: paths: /internal/asset_criticality/privileges: get: + operationId: AssetCriticalityGetPrivileges summary: Get Asset Criticality Privileges responses: '200': @@ -26,4 +27,4 @@ paths: ".asset-criticality.asset-criticality-*": read: true write: false - has_all_required: false \ No newline at end of file + has_all_required: false diff --git a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/get_asset_criticality_status.schema.yaml b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/get_asset_criticality_status.schema.yaml index a5a6b5035468..a62450cbcff4 100644 --- a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/get_asset_criticality_status.schema.yaml +++ b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/get_asset_criticality_status.schema.yaml @@ -12,6 +12,7 @@ servers: paths: /internal/asset_criticality/status: get: + operationId: AssetCriticalityGetStatus summary: Get Asset Criticality Status responses: '200': diff --git a/x-pack/plugins/security_solution/package.json b/x-pack/plugins/security_solution/package.json index 5f0613c3e89b..3d9effa5983b 100644 --- a/x-pack/plugins/security_solution/package.json +++ b/x-pack/plugins/security_solution/package.json @@ -29,4 +29,4 @@ "openapi:generate:debug": "node --inspect-brk scripts/openapi/generate", "openapi:bundle": "node scripts/openapi/bundle" } -} \ No newline at end of file +} diff --git a/yarn.lock b/yarn.lock index 9a5867e2361b..21b560fc24e8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2010,6 +2010,13 @@ resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.9.1.tgz#4ffb0055f7ef676ebc3a5a91fb621393294e2f43" integrity sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ== +"@emotion/is-prop-valid@1.2.1", "@emotion/is-prop-valid@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-1.2.1.tgz#23116cf1ed18bfeac910ec6436561ecb1a3885cc" + integrity sha512-61Mf7Ufx4aDxx1xlDeOm8aFFigGHE4z+0sKCa+IHCeZKiyP9RLD0Mmx7m8b9/Cf37f7NAvQOOJAbQQGVr5uERw== + dependencies: + "@emotion/memoize" "^0.8.1" + "@emotion/is-prop-valid@^0.8.8": version "0.8.8" resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz#db28b1c4368a259b60a97311d6a952d4fd01ac1a" @@ -2017,13 +2024,6 @@ dependencies: "@emotion/memoize" "0.7.4" -"@emotion/is-prop-valid@^1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-1.2.1.tgz#23116cf1ed18bfeac910ec6436561ecb1a3885cc" - integrity sha512-61Mf7Ufx4aDxx1xlDeOm8aFFigGHE4z+0sKCa+IHCeZKiyP9RLD0Mmx7m8b9/Cf37f7NAvQOOJAbQQGVr5uERw== - dependencies: - "@emotion/memoize" "^0.8.1" - "@emotion/jest@^11.11.0": version "11.11.0" resolved "https://registry.yarnpkg.com/@emotion/jest/-/jest-11.11.0.tgz#4d64b33052308739dcdd7396fd2bc902f7244f82" @@ -2123,6 +2123,11 @@ resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.7.5.tgz#77211291c1900a700b8a78cfafda3160d76949ed" integrity sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg== +"@emotion/unitless@0.8.0": + version "0.8.0" + resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.8.0.tgz#a4a36e9cbdc6903737cd20d38033241e1b8833db" + integrity sha512-VINS5vEYAscRl2ZUDiT3uMPlrFQupiKgHz5AA4bCH1miKBg4qtwkim1qPmJj/4WG6TreYMY111rEFsjupcOKHw== + "@emotion/unitless@^0.8.1": version "0.8.1" resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.8.1.tgz#182b5a4704ef8ad91bde93f7a860a88fd92c79a3" @@ -2295,6 +2300,11 @@ resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.46.0.tgz#3f7802972e8b6fe3f88ed1aabc74ec596c456db6" integrity sha512-a8TLtmPi8xzPkCbp/OGFUo5yhRkHM2Ko9kOWP4znJr0WAhWyThaw3PnwX4vOTWOAMsV2uRt32PPDcEz63esSaA== +"@exodus/schemasafe@^1.0.0-rc.2": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@exodus/schemasafe/-/schemasafe-1.3.0.tgz#731656abe21e8e769a7f70a4d833e6312fe59b7f" + integrity sha512-5Aap/GaRupgNx/feGBwLLTVv8OQFfv3pq2lPRzPg9R+IOBnDgghTGW7l7EuVXOvg5cc/xSAlRW8rBrjIC3Nvqw== + "@fastify/busboy@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@fastify/busboy/-/busboy-2.0.0.tgz#f22824caff3ae506b18207bad4126dbc6ccdb6b8" @@ -7475,6 +7485,54 @@ unbzip2-stream "1.4.3" yargs "17.7.2" +"@redocly/ajv@^8.11.0": + version "8.11.0" + resolved "https://registry.yarnpkg.com/@redocly/ajv/-/ajv-8.11.0.tgz#2fad322888dc0113af026e08fceb3e71aae495ae" + integrity sha512-9GWx27t7xWhDIR02PA18nzBdLcKQRgc46xNQvjFkrYk4UOmvKhJ/dawwiX0cCOeetN5LcaaiqQbVOWYK62SGHw== + dependencies: + fast-deep-equal "^3.1.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.2.2" + +"@redocly/cli@^1.6.0": + version "1.6.0" + resolved "https://registry.yarnpkg.com/@redocly/cli/-/cli-1.6.0.tgz#d3f6c8d6822eead487c2cb814d131e17d05c961f" + integrity sha512-0naVFJGR2tVcpMIHSFRr2HAoyy70qMqDAP6kXcnOdkGkwLRJ8s/5n1STwsym/yZwNkhrt2M0cKT6KAMlTUeCeg== + dependencies: + "@redocly/openapi-core" "1.6.0" + chokidar "^3.5.1" + colorette "^1.2.0" + core-js "^3.32.1" + get-port-please "^3.0.1" + glob "^7.1.6" + handlebars "^4.7.6" + mobx "^6.0.4" + node-fetch "^2.6.1" + react "^17.0.0 || ^18.2.0" + react-dom "^17.0.0 || ^18.2.0" + redoc "~2.1.3" + semver "^7.5.2" + simple-websocket "^9.0.0" + styled-components "^6.0.7" + yargs "17.0.1" + +"@redocly/openapi-core@1.6.0", "@redocly/openapi-core@^1.0.0-rc.2": + version "1.6.0" + resolved "https://registry.yarnpkg.com/@redocly/openapi-core/-/openapi-core-1.6.0.tgz#09aee5e21a9cbad08f3230ced16685d043a9b197" + integrity sha512-oao6Aey4peLKfagzWGb6N7OBI6CoDWEP4ka/XjrUNZw+UoKVVg3hVBXW4Vr3CJ2O8j6wEa2i+Lbb92VQQsoxwg== + dependencies: + "@redocly/ajv" "^8.11.0" + "@types/node" "^14.11.8" + colorette "^1.2.0" + js-levenshtein "^1.1.6" + js-yaml "^4.1.0" + lodash.isequal "^4.5.0" + minimatch "^5.0.1" + node-fetch "^2.6.1" + pluralize "^8.0.0" + yaml-ast-parser "0.0.43" + "@redux-saga/core@^1.1.3": version "1.1.3" resolved "https://registry.yarnpkg.com/@redux-saga/core/-/core-1.1.3.tgz#3085097b57a4ea8db5528d58673f20ce0950f6a4" @@ -9564,6 +9622,11 @@ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== +"@types/json-schema@^7.0.7": + version "7.0.15" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" + integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== + "@types/json-stable-stringify@^1.0.32": version "1.0.32" resolved "https://registry.yarnpkg.com/@types/json-stable-stringify/-/json-stable-stringify-1.0.32.tgz#121f6917c4389db3923640b2e68de5fa64dda88e" @@ -9797,7 +9860,7 @@ dependencies: "@types/node" "*" -"@types/node@*", "@types/node@20.10.5", "@types/node@>= 8", "@types/node@>=12.12.47", "@types/node@>=13.7.0", "@types/node@>=18.0.0", "@types/node@^10.1.0", "@types/node@^14.0.10 || ^16.0.0", "@types/node@^14.14.20 || ^16.0.0", "@types/node@^18.11.18", "@types/node@^18.17.5": +"@types/node@*", "@types/node@20.10.5", "@types/node@>= 8", "@types/node@>=12.12.47", "@types/node@>=13.7.0", "@types/node@>=18.0.0", "@types/node@^10.1.0", "@types/node@^14.0.10 || ^16.0.0", "@types/node@^14.11.8", "@types/node@^14.14.20 || ^16.0.0", "@types/node@^18.11.18", "@types/node@^18.17.5": version "20.10.5" resolved "https://registry.yarnpkg.com/@types/node/-/node-20.10.5.tgz#47ad460b514096b7ed63a1dae26fad0914ed3ab2" integrity sha512-nNPsNE65wjMxEKI93yOP+NPGGBJz/PoN3kZsVLee0XMiJolxSekEVD8wRwBUBqkwc7UWop0edW50yrCQW4CyRw== @@ -10234,6 +10297,11 @@ "@types/react-native" "*" csstype "^2.2.0" +"@types/stylis@4.2.0": + version "4.2.0" + resolved "https://registry.yarnpkg.com/@types/stylis/-/stylis-4.2.0.tgz#199a3f473f0c3a6f6e4e1b17cdbc967f274bdc6b" + integrity sha512-n4sx2bqL0mW1tvDf/loQ+aMX7GQD3lc3fkCMC55VFNDu/vBOabO+LTIeXKM14xK0ppk5TUGcWRjiSpIlUpghKw== + "@types/superagent@*": version "3.8.4" resolved "https://registry.yarnpkg.com/@types/superagent/-/superagent-3.8.4.tgz#24a5973c7d1a9c024b4bbda742a79267c33fb86a" @@ -13039,7 +13107,7 @@ cheerio@^1.0.0-rc.12, cheerio@^1.0.0-rc.3: parse5 "^7.0.0" parse5-htmlparser2-tree-adapter "^7.0.0" -chokidar@3.5.3, chokidar@^2.1.2, chokidar@^2.1.8, chokidar@^3.4.0, chokidar@^3.4.1, chokidar@^3.4.2, chokidar@^3.5.3: +chokidar@3.5.3, chokidar@^2.1.2, chokidar@^2.1.8, chokidar@^3.4.0, chokidar@^3.4.1, chokidar@^3.4.2, chokidar@^3.5.1, chokidar@^3.5.3: version "3.5.3" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== @@ -13141,10 +13209,10 @@ classnames@2.2.6: resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce" integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q== -classnames@^2.2.6, classnames@^2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.2.tgz#351d813bf0137fcc6a76a16b88208d2560a0d924" - integrity sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw== +classnames@^2.2.6, classnames@^2.3.1, classnames@^2.3.2: + version "2.5.1" + resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.5.1.tgz#ba774c614be0f016da105c858e7159eae8e7687b" + integrity sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow== clean-css@^4.2.3: version "4.2.3" @@ -13320,10 +13388,10 @@ cloneable-readable@^1.0.0: process-nextick-args "^2.0.0" readable-stream "^2.3.5" -clsx@^1.0.4, clsx@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.1.1.tgz#98b3134f9abbdf23b2663491ace13c5c03a73188" - integrity sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA== +clsx@^1.0.4, clsx@^1.1.0, clsx@^1.1.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.2.1.tgz#0ddc4a20a549b59c93a4116bb26f5294ca17dc12" + integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg== co@^4.6.0: version "4.6.0" @@ -13418,10 +13486,10 @@ colord@^2.9.1, colord@^2.9.2: resolved "https://registry.yarnpkg.com/colord/-/colord-2.9.2.tgz#25e2bacbbaa65991422c07ea209e2089428effb1" integrity sha512-Uqbg+J445nc1TKn4FoDPS6ZZqAvEDnwrH42yo8B40JSOgSLxMZ/gt3h4nmCtPLQeXhjJJkqBx7SCY35WnIixaQ== -colorette@^1.2.1, colorette@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.2.tgz#cbcc79d5e99caea2dbf10eb3a26fd8b3e6acfa94" - integrity sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w== +colorette@^1.2.0, colorette@^1.2.1, colorette@^1.2.2: + version "1.4.0" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.4.0.tgz#5190fbb87276259a86ad700bff2c6d6faa3fca40" + integrity sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g== colorette@^2.0.10, colorette@^2.0.14: version "2.0.19" @@ -13764,10 +13832,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.34.0, core-js@^3.6.5, core-js@^3.8.2, core-js@^3.8.3: - version "3.34.0" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.34.0.tgz#5705e6ad5982678612e96987d05b27c6c7c274a5" - integrity sha512-aDdvlDder8QmY91H88GzNi9EtQi2TjvQhpCX6B1v/dAZHU1AuLgHvRh54RiOerpEhEW46Tkf+vgAViB/CWC0ag== +core-js@^3.0.4, core-js@^3.32.1, core-js@^3.34.0, core-js@^3.6.5, core-js@^3.8.2, core-js@^3.8.3: + version "3.35.0" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.35.0.tgz#58e651688484f83c34196ca13f099574ee53d6b4" + integrity sha512-ntakECeqg81KqMueeGJ79Q5ZgQNR+6eaE8sxGCx62zMbAIj65q+uYvatToew3m6eAGdU4gNZwpZ34NMe4GYswg== core-util-is@1.0.2, core-util-is@^1.0.2, core-util-is@~1.0.0: version "1.0.2" @@ -14025,10 +14093,10 @@ css-select@^5.1.0: domutils "^3.0.1" nth-check "^2.0.1" -css-to-react-native@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/css-to-react-native/-/css-to-react-native-3.0.0.tgz#62dbe678072a824a689bcfee011fc96e02a7d756" - integrity sha512-Ro1yETZA813eoyUp2GDBhG2j+YggidUmzO1/v9eYBKR2EHVEniE2MI/NqpTQ954BMpTPZFsGNPm46qFB9dpaPQ== +css-to-react-native@3.2.0, css-to-react-native@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/css-to-react-native/-/css-to-react-native-3.2.0.tgz#cdd8099f71024e149e4f6fe17a7d46ecd55f1e32" + integrity sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ== dependencies: camelize "^1.0.0" css-color-keywords "^1.0.0" @@ -14145,6 +14213,11 @@ cssstyle@^2.3.0: dependencies: cssom "~0.3.6" +csstype@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.2.tgz#1d4bf9d572f11c14031f0436e1c10bc1f571f50b" + integrity sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ== + csstype@^2.2.0, csstype@^2.5.5, csstype@^2.5.7, csstype@^2.6.7: version "2.6.7" resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.7.tgz#20b0024c20b6718f4eda3853a1f5a1cce7f5e4a5" @@ -14685,6 +14758,11 @@ decimal.js@^10.4.1: resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.4.1.tgz#be75eeac4a2281aace80c1a8753587c27ef053e7" integrity sha512-F29o+vci4DodHYT9UrR5IEbfBw9pE5eSapIJdTqXK5+6hq+t8VRxwQyKlW2i+KDKFkkJQRvFyI/QXD83h8LyQw== +decko@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decko/-/decko-1.2.0.tgz#fd43c735e967b8013306884a56fbe665996b6817" + integrity sha512-m8FnyHXV1QX+S1cl+KPFDIl6NMkxtKsy6+U/aYyjrOqWMuwAwYWu7ePqrsUHtDR5Y8Yk2pi/KIDSgF+vT4cPOQ== + decode-uri-component@^0.2.0: version "0.2.2" resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz#e69dbe25d37941171dd540e024c444cd5188e1e9" @@ -15299,6 +15377,11 @@ domhandler@^5.0.1, domhandler@^5.0.2, domhandler@^5.0.3: dependencies: domelementtype "^2.3.0" +dompurify@^2.2.8: + version "2.4.7" + resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.4.7.tgz#277adeb40a2c84be2d42a8bcd45f582bfa4d0cfc" + integrity sha512-kxxKlPEDa6Nc5WJi+qRgPbOAbgTpSULL+vI3NUXsZMlkJxTqYI9wg5ZTay2sFrdZRWHPWNi+EdAhcJf81WtoMQ== + domutils@^2.0.0, domutils@^2.5.2, domutils@^2.8.0: version "2.8.0" resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135" @@ -15931,6 +16014,11 @@ es6-map@^0.1.5: es6-symbol "~3.1.1" event-emitter "~0.3.5" +es6-promise@^3.2.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-3.3.1.tgz#a08cdde84ccdbf34d027a1451bc91d4bcd28a613" + integrity sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg== + es6-promise@^4.2.8: version "4.2.8" resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a" @@ -16445,7 +16533,7 @@ eventemitter2@6.4.7: resolved "https://registry.yarnpkg.com/eventemitter2/-/eventemitter2-6.4.7.tgz#a7f6c4d7abf28a14c1ef3442f21cb306a054271d" integrity sha512-tYUSVOGeQPKt/eC1ABfhHy5Xd96N3oIijJvN3O9+TsC28T5V9yX9oEfEK5faP0EFSNVOG97qtAS68GBrQB2hDg== -eventemitter3@^4.0.0, eventemitter3@^4.0.4: +eventemitter3@^4.0.0, eventemitter3@^4.0.4, eventemitter3@^4.0.7: version "4.0.7" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== @@ -17184,6 +17272,11 @@ for-in@^1.0.2: resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= +foreach@^2.0.4: + version "2.0.6" + resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.6.tgz#87bcc8a1a0e74000ff2bf9802110708cfb02eb6e" + integrity sha512-k6GAGDyqLe9JaebCsFCoudPPWfihKu8pylYXRlqP1J7ms39iPoTtk2fviNglIeQEwdh0bQeKJ01ZPyuyQvKzwg== + foreground-child@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-2.0.0.tgz#71b32800c9f15aa8f2f83f4a6bd9bff35d861a53" @@ -17602,6 +17695,11 @@ get-package-type@^0.1.0: resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== +get-port-please@^3.0.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/get-port-please/-/get-port-please-3.1.1.tgz#2556623cddb4801d823c0a6a15eec038abb483be" + integrity sha512-3UBAyM3u4ZBVYDsxOQfJDxEa6XTbpBDrOjp4mf7ExFRt5BKs/QywQQiJsh2B+hxcZLSapWqCRvElUe8DnKcFHA== + get-port@^5.0.0: version "5.1.1" resolved "https://registry.yarnpkg.com/get-port/-/get-port-5.1.1.tgz#0469ed07563479de6efb986baf053dcd7d4e3193" @@ -18097,7 +18195,7 @@ handle-thing@^2.0.0: resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.0.tgz#0e039695ff50c93fc288557d696f3c1dc6776754" integrity sha512-d4sze1JNC454Wdo2fkuyzCr6aHcbL6PGGuFAz0Li/NcOm1tCHGnWDRmJP85dh9IhQErTc2svWFEX5xHIOo//kQ== -handlebars@4.7.8, handlebars@^4.7.7: +handlebars@4.7.8, handlebars@^4.7.6, handlebars@^4.7.7: version "4.7.8" resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.8.tgz#41c42c18b1be2365439188c77c6afae71c0cd9e9" integrity sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ== @@ -18697,6 +18795,11 @@ http-signature@~1.3.6: jsprim "^2.0.2" sshpk "^1.14.1" +http2-client@^1.2.5: + version "1.3.5" + resolved "https://registry.yarnpkg.com/http2-client/-/http2-client-1.3.5.tgz#20c9dc909e3cc98284dd20af2432c524086df181" + integrity sha512-EC2utToWl4RKfs5zd36Mxq7nzHHBuomZboI0yYL6Y0RmBgT7Sgkq4rQ0ezFTYoIsSs7Tm9SJe+o2FcAg6GBhGA== + http2-wrapper@^1.0.0-beta.5.2: version "1.0.0-beta.5.2" resolved "https://registry.yarnpkg.com/http2-wrapper/-/http2-wrapper-1.0.0-beta.5.2.tgz#8b923deb90144aea65cf834b016a340fc98556f3" @@ -20616,6 +20719,13 @@ json-parse-even-better-errors@^2.3.0, json-parse-even-better-errors@^2.3.1: resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== +json-pointer@0.6.2, json-pointer@^0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/json-pointer/-/json-pointer-0.6.2.tgz#f97bd7550be5e9ea901f8c9264c9d436a22a93cd" + integrity sha512-vLWcKbOaXlO+jvRy4qNd+TI1QUPZzfJj1tpJ3vAXDych5XJf93ftpUKe5pKCrzyIIwgBJcOcCVRUfqQP25afBw== + dependencies: + foreach "^2.0.4" + json-schema-to-ts@^2.9.1: version "2.9.1" resolved "https://registry.yarnpkg.com/json-schema-to-ts/-/json-schema-to-ts-2.9.1.tgz#0e055b787587477abdb7e880c874efad3dba7779" @@ -21587,6 +21697,11 @@ lru-queue@0.1: dependencies: es5-ext "~0.10.2" +lunr@^2.3.9: + version "2.3.9" + resolved "https://registry.yarnpkg.com/lunr/-/lunr-2.3.9.tgz#18b123142832337dd6e964df1a5a7707b25d35e1" + integrity sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow== + luxon@^1.25.0: version "1.28.1" resolved "https://registry.yarnpkg.com/luxon/-/luxon-1.28.1.tgz#528cdf3624a54506d710290a2341aa8e6e6c61b0" @@ -21732,6 +21847,11 @@ marge@^1.0.1: dependencies: yargs "^3.15.0" +mark.js@^8.11.1: + version "8.11.1" + resolved "https://registry.yarnpkg.com/mark.js/-/mark.js-8.11.1.tgz#180f1f9ebef8b0e638e4166ad52db879beb2ffc5" + integrity sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ== + markdown-escapes@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/markdown-escapes/-/markdown-escapes-1.0.1.tgz#1994df2d3af4811de59a6714934c2b2292734518" @@ -21767,6 +21887,11 @@ markdown-table@^2.0.0: dependencies: repeat-string "^1.0.0" +marked@^4.0.15: + version "4.3.0" + resolved "https://registry.yarnpkg.com/marked/-/marked-4.3.0.tgz#796362821b019f734054582038b116481b456cf3" + integrity sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A== + material-colors@^1.2.1: version "1.2.5" resolved "https://registry.yarnpkg.com/material-colors/-/material-colors-1.2.5.tgz#5292593e6754cb1bcc2b98030e4e0d6a3afc9ea1" @@ -22456,6 +22581,23 @@ ml-tree-similarity@^1.0.0: binary-search "^1.3.5" num-sort "^2.0.0" +mobx-react-lite@^3.4.0: + version "3.4.3" + resolved "https://registry.yarnpkg.com/mobx-react-lite/-/mobx-react-lite-3.4.3.tgz#3a4c22c30bfaa8b1b2aa48d12b2ba811c0947ab7" + integrity sha512-NkJREyFTSUXR772Qaai51BnE1voWx56LOL80xG7qkZr6vo8vEaLF3sz1JNUVh+rxmUzxYaqOhfuxTfqUh0FXUg== + +mobx-react@^7.2.0: + version "7.6.0" + resolved "https://registry.yarnpkg.com/mobx-react/-/mobx-react-7.6.0.tgz#ebf0456728a9bd2e5c24fdcf9b36e285a222a7d6" + integrity sha512-+HQUNuh7AoQ9ZnU6c4rvbiVVl+wEkb9WqYsVDzGLng+Dqj1XntHu79PvEWKtSMoMj67vFp/ZPXcElosuJO8ckA== + dependencies: + mobx-react-lite "^3.4.0" + +mobx@^6.0.4: + version "6.12.0" + resolved "https://registry.yarnpkg.com/mobx/-/mobx-6.12.0.tgz#72b2685ca5af031aaa49e77a4d76ed67fcbf9135" + integrity sha512-Mn6CN6meXEnMa0a5u6a5+RKrqRedHBhZGd15AWLk9O6uFY4KYHzImdt8JI8WODo1bjTSRnwXhJox+FCUZhCKCQ== + mocha-junit-reporter@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/mocha-junit-reporter/-/mocha-junit-reporter-2.0.2.tgz#d521689b651dc52f52044739f8ffb368be415731" @@ -22937,6 +23079,13 @@ node-emoji@^1.10.0: dependencies: lodash.toarray "^4.4.0" +node-fetch-h2@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/node-fetch-h2/-/node-fetch-h2-2.3.0.tgz#c6188325f9bd3d834020bf0f2d6dc17ced2241ac" + integrity sha512-ofRW94Ab0T4AOh5Fk8t0h8OBWrmjb0SSB20xh1H8YnPV9EJ+f5AMoYSUQ2zgJ4Iq2HAK0I2l5/Nequ8YzFS3Hg== + dependencies: + http2-client "^1.2.5" + node-fetch@^1.0.1, node-fetch@^2.6.1, node-fetch@^2.6.12, node-fetch@^2.6.7: version "2.7.0" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" @@ -23052,6 +23201,13 @@ node-preload@^0.2.1: dependencies: process-on-spawn "^1.0.0" +node-readfiles@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/node-readfiles/-/node-readfiles-0.2.0.tgz#dbbd4af12134e2e635c245ef93ffcf6f60673a5d" + integrity sha512-SU00ZarexNlE4Rjdm83vglt5Y9yiQ+XI1XpflWlb7q7UTN1JUItm69xMeiQCTxtTfnzt+83T8Cx+vI2ED++VDA== + dependencies: + es6-promise "^3.2.1" + node-releases@^2.0.14: version "2.0.14" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b" @@ -23240,6 +23396,52 @@ nyc@15.1.0, nyc@^15.1.0: test-exclude "^6.0.0" yargs "^15.0.2" +oas-kit-common@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/oas-kit-common/-/oas-kit-common-1.0.8.tgz#6d8cacf6e9097967a4c7ea8bcbcbd77018e1f535" + integrity sha512-pJTS2+T0oGIwgjGpw7sIRU8RQMcUoKCDWFLdBqKB2BNmGpbBMH2sdqAaOXUg8OzonZHU0L7vfJu1mJFEiYDWOQ== + dependencies: + fast-safe-stringify "^2.0.7" + +oas-linter@^3.2.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/oas-linter/-/oas-linter-3.2.2.tgz#ab6a33736313490659035ca6802dc4b35d48aa1e" + integrity sha512-KEGjPDVoU5K6swgo9hJVA/qYGlwfbFx+Kg2QB/kd7rzV5N8N5Mg6PlsoCMohVnQmo+pzJap/F610qTodKzecGQ== + dependencies: + "@exodus/schemasafe" "^1.0.0-rc.2" + should "^13.2.1" + yaml "^1.10.0" + +oas-resolver@^2.5.6: + version "2.5.6" + resolved "https://registry.yarnpkg.com/oas-resolver/-/oas-resolver-2.5.6.tgz#10430569cb7daca56115c915e611ebc5515c561b" + integrity sha512-Yx5PWQNZomfEhPPOphFbZKi9W93CocQj18NlD2Pa4GWZzdZpSJvYwoiuurRI7m3SpcChrnO08hkuQDL3FGsVFQ== + dependencies: + node-fetch-h2 "^2.3.0" + oas-kit-common "^1.0.8" + reftools "^1.1.9" + yaml "^1.10.0" + yargs "^17.0.1" + +oas-schema-walker@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/oas-schema-walker/-/oas-schema-walker-1.1.5.tgz#74c3cd47b70ff8e0b19adada14455b5d3ac38a22" + integrity sha512-2yucenq1a9YPmeNExoUa9Qwrt9RFkjqaMAA1X+U7sbb0AqBeTIdMHky9SQQ6iN94bO5NW0W4TRYXerG+BdAvAQ== + +oas-validator@^5.0.8: + version "5.0.8" + resolved "https://registry.yarnpkg.com/oas-validator/-/oas-validator-5.0.8.tgz#387e90df7cafa2d3ffc83b5fb976052b87e73c28" + integrity sha512-cu20/HE5N5HKqVygs3dt94eYJfBi0TsZvPVXDhbXQHiEityDN+RROTleefoKRKKJ9dFAF2JBkDHgvWj0sjKGmw== + dependencies: + call-me-maybe "^1.0.1" + oas-kit-common "^1.0.8" + oas-linter "^3.2.2" + oas-resolver "^2.5.6" + oas-schema-walker "^1.1.5" + reftools "^1.1.9" + should "^13.2.1" + yaml "^1.10.0" + object-assign@4.X, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" @@ -23477,6 +23679,14 @@ openai@^4.17.0, openai@^4.24.1: node-fetch "^2.6.7" web-streams-polyfill "^3.2.1" +openapi-sampler@^1.3.1: + version "1.4.0" + resolved "https://registry.yarnpkg.com/openapi-sampler/-/openapi-sampler-1.4.0.tgz#c133cad6250481f2ec7e48b16eb70062adb514c0" + integrity sha512-3FKJQCHAMG9T7RsRy9u5Ft4ERPq1QQmn77C8T3OSofYL9uur59AqychvQ0YQKijrqRwIkAbzkh+nQnAE3gjMVA== + dependencies: + "@types/json-schema" "^7.0.7" + json-pointer "0.6.2" + openapi-types@^10.0.0: version "10.0.0" resolved "https://registry.yarnpkg.com/openapi-types/-/openapi-types-10.0.0.tgz#0debbf663b2feed0322030b5b7c9080804076934" @@ -24086,6 +24296,11 @@ pend@~1.2.0: resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA= +perfect-scrollbar@^1.5.5: + version "1.5.5" + resolved "https://registry.yarnpkg.com/perfect-scrollbar/-/perfect-scrollbar-1.5.5.tgz#41a211a2fb52a7191eff301432134ea47052b27f" + integrity sha512-dzalfutyP3e/FOpdlhVryN4AJ5XDVauVWxybSkLZmakFE2sS3y3pc4JnSprw8tGmHvkaG5Edr5T7LBTZ+WWU2g== + performance-now@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" @@ -24335,7 +24550,7 @@ polished@^3.7.2: dependencies: "@babel/runtime" "^7.12.5" -polished@^4.2.2: +polished@^4.1.3, polished@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/polished/-/polished-4.2.2.tgz#2529bb7c3198945373c52e34618c8fe7b1aa84d1" integrity sha512-Sz2Lkdxz6F2Pgnpi9U5Ng/WdWAUZxmHrNPoVlm3aAemxoy2Qy7LGjQg4uf8qKelDAUW94F4np3iH2YPf2qefcQ== @@ -24650,15 +24865,7 @@ postcss-values-parser@^6.0.2: is-url-superb "^4.0.0" quote-unquote "^1.0.0" -postcss@^7.0.14, postcss@^7.0.16, postcss@^7.0.26, postcss@^7.0.32, postcss@^7.0.36, postcss@^7.0.5, postcss@^7.0.6: - version "7.0.39" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.39.tgz#9624375d965630e2e1f2c02a935c82a59cb48309" - integrity sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA== - dependencies: - picocolors "^0.2.1" - source-map "^0.6.1" - -postcss@^8.4.14, postcss@^8.4.23, postcss@^8.4.31: +postcss@8.4.31, postcss@^8.4.14, postcss@^8.4.23, postcss@^8.4.31: version "8.4.31" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.31.tgz#92b451050a9f914da6755af352bdc0192508656d" integrity sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ== @@ -24667,6 +24874,14 @@ postcss@^8.4.14, postcss@^8.4.23, postcss@^8.4.31: picocolors "^1.0.0" source-map-js "^1.0.2" +postcss@^7.0.14, postcss@^7.0.16, postcss@^7.0.26, postcss@^7.0.32, postcss@^7.0.36, postcss@^7.0.5, postcss@^7.0.6: + version "7.0.39" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.39.tgz#9624375d965630e2e1f2c02a935c82a59cb48309" + integrity sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA== + dependencies: + picocolors "^0.2.1" + source-map "^0.6.1" + potpack@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/potpack/-/potpack-2.0.0.tgz#61f4dd2dc4b3d5e996e3698c0ec9426d0e169104" @@ -24810,7 +25025,12 @@ printj@~1.1.0: resolved "https://registry.yarnpkg.com/printj/-/printj-1.1.2.tgz#d90deb2975a8b9f600fb3a1c94e3f4c53c78a222" integrity sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ== -prismjs@^1.22.0, prismjs@~1.27.0: +prismjs@^1.22.0, prismjs@^1.27.0: + version "1.29.0" + resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.29.0.tgz#f113555a8fa9b57c35e637bba27509dcf802dd12" + integrity sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q== + +prismjs@~1.27.0: version "1.27.0" resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.27.0.tgz#bb6ee3138a0b438a3653dd4d6ce0cc6510a45057" integrity sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA== @@ -24918,7 +25138,7 @@ prompts@^2.0.1, prompts@^2.4.0, prompts@~2.4.2: kleur "^3.0.3" sisteransi "^1.0.5" -prop-types@15.x, prop-types@^15.0.0, prop-types@^15.5.10, prop-types@^15.5.7, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.2, prop-types@^15.7.0, prop-types@^15.7.2, prop-types@^15.8.1: +prop-types@15.x, prop-types@^15.0.0, prop-types@^15.5.0, prop-types@^15.5.10, prop-types@^15.5.7, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.2, prop-types@^15.7.0, prop-types@^15.7.2, prop-types@^15.8.1: version "15.8.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== @@ -25184,6 +25404,11 @@ querystringify@^2.1.1: resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.1.1.tgz#60e5a5fd64a7f8bfa4d2ab2ed6fdf4c85bad154e" integrity sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA== +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + queue-tick@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/queue-tick/-/queue-tick-1.0.1.tgz#f6f07ac82c1fd60f82e098b417a80e52f1f4c142" @@ -25421,6 +25646,14 @@ react-docgen@^5.0.0: node-dir "^0.1.10" strip-indent "^3.0.0" +"react-dom@^17.0.0 || ^18.2.0": + version "18.2.0" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d" + integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g== + dependencies: + loose-envify "^1.1.0" + scheduler "^0.23.0" + react-dom@^17.0.2: version "17.0.2" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.2.tgz#ecffb6845e3ad8dbfcdc498f0d0a939736502c23" @@ -25824,6 +26057,14 @@ react-syntax-highlighter@^15.3.1: prismjs "^1.22.0" refractor "^3.2.0" +react-tabs@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/react-tabs/-/react-tabs-4.3.0.tgz#9f4db0fd209ba4ab2c1e78993ff964435f84af62" + integrity sha512-2GfoG+f41kiBIIyd3gF+/GRCCYtamC8/2zlAcD8cqQmqI9Q+YVz7fJLHMmU9pXDVYYHpJeCgUSBJju85vu5q8Q== + dependencies: + clsx "^1.1.0" + prop-types "^15.5.0" + "react-test-renderer@^16.8.0 || ^17.0.0", react-test-renderer@^17.0.0, react-test-renderer@^17.0.2: version "17.0.2" resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-17.0.2.tgz#4cd4ae5ef1ad5670fc0ef776e8cc7e1231d9866c" @@ -25903,6 +26144,13 @@ react-window@^1.8.9: "@babel/runtime" "^7.0.0" memoize-one ">=3.1.1 <6" +"react@^17.0.0 || ^18.2.0": + version "18.2.0" + resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5" + integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ== + dependencies: + loose-envify "^1.1.0" + react@^17.0.2: version "17.0.2" resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037" @@ -26105,6 +26353,33 @@ redent@^3.0.0: indent-string "^4.0.0" strip-indent "^3.0.0" +redoc@~2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/redoc/-/redoc-2.1.3.tgz#612c9fed744993d5fc99cbf39fe9056bd1034fa5" + integrity sha512-d7F9qLLxaiFW4GC03VkwlX9wuRIpx9aiIIf3o6mzMnqPfhxrn2IRKGndrkJeVdItgCfmg9jXZiFEowm60f1meQ== + dependencies: + "@redocly/openapi-core" "^1.0.0-rc.2" + classnames "^2.3.1" + decko "^1.2.0" + dompurify "^2.2.8" + eventemitter3 "^4.0.7" + json-pointer "^0.6.2" + lunr "^2.3.9" + mark.js "^8.11.1" + marked "^4.0.15" + mobx-react "^7.2.0" + openapi-sampler "^1.3.1" + path-browserify "^1.0.1" + perfect-scrollbar "^1.5.5" + polished "^4.1.3" + prismjs "^1.27.0" + prop-types "^15.7.2" + react-tabs "^4.3.0" + slugify "~1.4.7" + stickyfill "^1.1.1" + swagger2openapi "^7.0.6" + url-template "^2.0.8" + reduce-reducers@^0.4.3: version "0.4.3" resolved "https://registry.yarnpkg.com/reduce-reducers/-/reduce-reducers-0.4.3.tgz#8e052618801cd8fc2714b4915adaa8937eb6d66c" @@ -26179,6 +26454,11 @@ refractor@^3.2.0, refractor@^3.6.0: parse-entities "^2.0.0" prismjs "~1.27.0" +reftools@^1.1.9: + version "1.1.9" + resolved "https://registry.yarnpkg.com/reftools/-/reftools-1.1.9.tgz#e16e19f662ccd4648605312c06d34e5da3a2b77e" + integrity sha512-OVede/NQE13xBQ+ob5CKd5KyeJYU2YInb1bmV4nRoOfquZPkAkxuOXicSe1PvqIuZZ4kD13sPKBbR7UFDmli6w== + regedit@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/regedit/-/regedit-5.0.0.tgz#7ec444ef027cc704e104fae00586f84752291116" @@ -27039,6 +27319,13 @@ scheduler@^0.20.2: loose-envify "^1.1.0" object-assign "^4.1.1" +scheduler@^0.23.0: + version "0.23.0" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe" + integrity sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw== + dependencies: + loose-envify "^1.1.0" + schema-utils@2.7.0, schema-utils@^2.0.0, schema-utils@^2.0.1, schema-utils@^2.5.0, schema-utils@^2.6.5, schema-utils@^2.7.0: version "2.7.0" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.0.tgz#17151f76d8eae67fbbf77960c33c676ad9f4efc7" @@ -27323,7 +27610,7 @@ shallow-equal@^3.1.0: resolved "https://registry.yarnpkg.com/shallow-equal/-/shallow-equal-3.1.0.tgz#e7a54bac629c7f248eff6c2f5b63122ba4320bec" integrity sha512-pfVOw8QZIXpMbhBWvzBISicvToTiM5WBF1EeAUZDDSb5Dt29yl4AYbyywbJFSEsRUMr7gJaxqCdr4L3tQf9wVg== -shallowequal@^1.1.0: +shallowequal@1.1.0, shallowequal@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-1.1.0.tgz#188d521de95b9087404fd4dcb68b13df0ae4e7f8" integrity sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ== @@ -27389,6 +27676,50 @@ shelljs@^0.8.5: interpret "^1.0.0" rechoir "^0.6.2" +should-equal@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/should-equal/-/should-equal-2.0.0.tgz#6072cf83047360867e68e98b09d71143d04ee0c3" + integrity sha512-ZP36TMrK9euEuWQYBig9W55WPC7uo37qzAEmbjHz4gfyuXrEUgF8cUvQVO+w+d3OMfPvSRQJ22lSm8MQJ43LTA== + dependencies: + should-type "^1.4.0" + +should-format@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/should-format/-/should-format-3.0.3.tgz#9bfc8f74fa39205c53d38c34d717303e277124f1" + integrity sha512-hZ58adtulAk0gKtua7QxevgUaXTTXxIi8t41L3zo9AHvjXO1/7sdLECuHeIN2SRtYXpNkmhoUP2pdeWgricQ+Q== + dependencies: + should-type "^1.3.0" + should-type-adaptors "^1.0.1" + +should-type-adaptors@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/should-type-adaptors/-/should-type-adaptors-1.1.0.tgz#401e7f33b5533033944d5cd8bf2b65027792e27a" + integrity sha512-JA4hdoLnN+kebEp2Vs8eBe9g7uy0zbRo+RMcU0EsNy+R+k049Ki+N5tT5Jagst2g7EAja+euFuoXFCa8vIklfA== + dependencies: + should-type "^1.3.0" + should-util "^1.0.0" + +should-type@^1.3.0, should-type@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/should-type/-/should-type-1.4.0.tgz#0756d8ce846dfd09843a6947719dfa0d4cff5cf3" + integrity sha512-MdAsTu3n25yDbIe1NeN69G4n6mUnJGtSJHygX3+oN0ZbO3DTiATnf7XnYJdGT42JCXurTb1JI0qOBR65shvhPQ== + +should-util@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/should-util/-/should-util-1.0.1.tgz#fb0d71338f532a3a149213639e2d32cbea8bcb28" + integrity sha512-oXF8tfxx5cDk8r2kYqlkUJzZpDBqVY/II2WhvU0n9Y3XYvAYRmeaf1PvvIvTgPnv4KJ+ES5M0PyDq5Jp+Ygy2g== + +should@^13.2.1: + version "13.2.3" + resolved "https://registry.yarnpkg.com/should/-/should-13.2.3.tgz#96d8e5acf3e97b49d89b51feaa5ae8d07ef58f10" + integrity sha512-ggLesLtu2xp+ZxI+ysJTmNjh2U0TsC+rQ/pfED9bUZZ4DKefP27D+7YJVVTvKsmjLpIi9jAa7itwDGkDDmt1GQ== + dependencies: + should-equal "^2.0.0" + should-format "^3.0.3" + should-type "^1.4.0" + should-type-adaptors "^1.0.1" + should-util "^1.0.0" + side-channel@^1.0.2, side-channel@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" @@ -27453,6 +27784,17 @@ simple-swizzle@^0.2.2: dependencies: is-arrayish "^0.3.1" +simple-websocket@^9.0.0: + version "9.1.0" + resolved "https://registry.yarnpkg.com/simple-websocket/-/simple-websocket-9.1.0.tgz#91cbb39eafefbe7e66979da6c639109352786a7f" + integrity sha512-8MJPnjRN6A8UCp1I+H/dSFyjwJhp6wta4hsVRhjf8w9qBHRzxYt14RaOcjvQnhD1N4yKOddEjflwMnQM4VtXjQ== + dependencies: + debug "^4.3.1" + queue-microtask "^1.2.2" + randombytes "^2.1.0" + readable-stream "^3.6.0" + ws "^7.4.2" + sinon@^7.4.2: version "7.5.0" resolved "https://registry.yarnpkg.com/sinon/-/sinon-7.5.0.tgz#e9488ea466070ea908fd44a3d6478fd4923c67ec" @@ -27518,6 +27860,11 @@ slide@~1.1.3: resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707" integrity sha1-VusCfWW00tzmyy4tMsTUr8nh1wc= +slugify@~1.4.7: + version "1.4.7" + resolved "https://registry.yarnpkg.com/slugify/-/slugify-1.4.7.tgz#e42359d505afd84a44513280868e31202a79a628" + integrity sha512-tf+h5W1IrjNm/9rKKj0JU2MDMruiopx0jjVA5zCdBtcGjfp0+c5rHw/zADLC3IeKlGHtVbHtpfzvYA0OYT+HKg== + smart-buffer@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae" @@ -28060,6 +28407,11 @@ stats-lite@^2.2.0: resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= +stickyfill@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/stickyfill/-/stickyfill-1.1.1.tgz#39413fee9d025c74a7e59ceecb23784cc0f17f02" + integrity sha512-GCp7vHAfpao+Qh/3Flh9DXEJ/qSi0KJwJw6zYlZOtRYXWUIpMM6mC2rIep/dK8RQqwW0KxGJIllmjPIBOGN8AA== + store2@^2.12.0: version "2.12.0" resolved "https://registry.yarnpkg.com/store2/-/store2-2.12.0.tgz#e1f1b7e1a59b6083b2596a8d067f6ee88fd4d3cf" @@ -28398,6 +28750,21 @@ styled-components@^5.1.0: shallowequal "^1.1.0" supports-color "^5.5.0" +styled-components@^6.0.7: + version "6.1.6" + resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-6.1.6.tgz#c75c4f994136545b3bcc11608db5363710b78c0e" + integrity sha512-DgTLULSC29xpabJ24bbn1+hulU6vvGFQf4RPwBOJrm8WJFnN42yXpo5voBt3jDSJBa5tBd1L6PqswJjQ0wRKdg== + dependencies: + "@emotion/is-prop-valid" "1.2.1" + "@emotion/unitless" "0.8.0" + "@types/stylis" "4.2.0" + css-to-react-native "3.2.0" + csstype "3.1.2" + postcss "8.4.31" + shallowequal "1.1.0" + stylis "4.3.1" + tslib "2.5.0" + stylehacks@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-5.1.0.tgz#a40066490ca0caca04e96c6b02153ddc39913520" @@ -28473,6 +28840,11 @@ stylis@4.2.0: resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.2.0.tgz#79daee0208964c8fe695a42fcffcac633a211a51" integrity sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw== +stylis@4.3.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.3.1.tgz#ed8a9ebf9f76fe1e12d462f5cc3c4c980b23a7eb" + integrity sha512-EQepAV+wMsIaGVGX1RECzgrcqRRU/0sYOHkeLsZ3fzHaHXZy4DaOOX0vOlGQdlsjkh3mFHAIlVimpwAs4dslyQ== + stylus-lookup@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/stylus-lookup/-/stylus-lookup-5.0.1.tgz#3c4d116c3b1e8e1a8169c0d9cd20e608595560f4" @@ -28592,6 +28964,23 @@ svgo@^2.7.0, svgo@^2.8.0: picocolors "^1.0.0" stable "^0.1.8" +swagger2openapi@^7.0.6: + version "7.0.8" + resolved "https://registry.yarnpkg.com/swagger2openapi/-/swagger2openapi-7.0.8.tgz#12c88d5de776cb1cbba758994930f40ad0afac59" + integrity sha512-upi/0ZGkYgEcLeGieoz8gT74oWHA0E7JivX7aN9mAf+Tc7BQoRBvnIGHoPDw+f9TXTW4s6kGYCZJtauP6OYp7g== + dependencies: + call-me-maybe "^1.0.1" + node-fetch "^2.6.1" + node-fetch-h2 "^2.3.0" + node-readfiles "^0.2.0" + oas-kit-common "^1.0.8" + oas-resolver "^2.5.6" + oas-schema-walker "^1.1.5" + oas-validator "^5.0.8" + reftools "^1.1.9" + yaml "^1.10.0" + yargs "^17.0.1" + symbol-observable@^1.0.4, symbol-observable@^1.1.0, symbol-observable@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804" @@ -29272,6 +29661,11 @@ tslib@2.3.1: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== +tslib@2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.0.tgz#42bfed86f5787aeb41d031866c8f402429e0fddf" + integrity sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg== + tslib@^1.10.0, tslib@^1.11.1, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" @@ -29892,6 +30286,11 @@ url-parse@^1.5.10, url-parse@^1.5.3: querystringify "^2.1.1" requires-port "^1.0.0" +url-template@^2.0.8: + version "2.0.8" + resolved "https://registry.yarnpkg.com/url-template/-/url-template-2.0.8.tgz#fc565a3cccbff7730c775f5641f9555791439f21" + integrity sha512-XdVKMF4SJ0nP/O7XIPB0JwAEuT9lDIYnNsK8yGVe43y0AWoKeJNdv3ZNWh7ksJ6KqQFjOO6ox/VEitLnaVNufw== + url@^0.11.0: version "0.11.0" resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" @@ -31197,10 +31596,10 @@ ws@8.14.2, ws@>=8.14.2, ws@^8.2.3, ws@^8.4.2, ws@^8.9.0: resolved "https://registry.yarnpkg.com/ws/-/ws-8.14.2.tgz#6c249a806eb2db7a20d26d51e7709eab7b2e6c7f" integrity sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g== -ws@^7.3.1: - version "7.5.6" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.6.tgz#e59fc509fb15ddfb65487ee9765c5a51dec5fe7b" - integrity sha512-6GLgCqo2cy2A2rjCNFlxQS6ZljG/coZfZXclldI8FB/1G3CCI36Zd8xy2HrFVACi8tfk5XrgLQEk+P0Tnz9UcA== +ws@^7.3.1, ws@^7.4.2: + version "7.5.9" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" + integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== x-default-browser@^0.4.0: version "0.4.0" @@ -31320,6 +31719,11 @@ yallist@^4.0.0: resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== +yaml-ast-parser@0.0.43: + version "0.0.43" + resolved "https://registry.yarnpkg.com/yaml-ast-parser/-/yaml-ast-parser-0.0.43.tgz#e8a23e6fb4c38076ab92995c5dca33f3d3d7c9bb" + integrity sha512-2PTINUwsRqSd+s8XxKaJWQlUuEMHJQyEuh2edBbW8KNJz0SJPwUSD2zRWqezFEdN7IzAgeuYHFUCF7o8zRdZ0A== + yaml-language-server-parser@^0.1.0: version "0.1.3" resolved "https://registry.yarnpkg.com/yaml-language-server-parser/-/yaml-language-server-parser-0.1.3.tgz#f0e9082068291c7c330eefa1f3c9f1b4c3c54183" @@ -31376,7 +31780,20 @@ yargs@16.2.0: y18n "^5.0.5" yargs-parser "^20.2.2" -yargs@17.7.2, yargs@^17.2.1, yargs@^17.3.1, yargs@^17.4.0, yargs@^17.7.1, yargs@^17.7.2: +yargs@17.0.1: + version "17.0.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.0.1.tgz#6a1ced4ed5ee0b388010ba9fd67af83b9362e0bb" + integrity sha512-xBBulfCc8Y6gLFcrPvtqKz9hz8SO0l1Ni8GgDekvBX2ro0HRQImDGnikfc33cgzcYUSncapnNcZDjVFIH3f6KQ== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2" + +yargs@17.7.2, yargs@^17.0.1, yargs@^17.2.1, yargs@^17.3.1, yargs@^17.4.0, yargs@^17.7.1, yargs@^17.7.2: version "17.7.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== From d458b5382fdbf29e7f35a35fe2792aa86f4d6c4c Mon Sep 17 00:00:00 2001 From: "Eyo O. Eyo" <7893459+eokoneyo@users.noreply.github.com> Date: Fri, 5 Jan 2024 14:35:09 +0100 Subject: [PATCH 33/57] Remove legacy kibana react code editor (#171047) ## Summary This PR removes the legacy kibana react code-editor, alongside replacing all import declarations of this legacy component to the one offered by shared-ux, i.e import declaration source of `'@kbn/kibana-react/public'` is switched to `@kbn/code-editor`. Also in this PR an helper for writing jest tests has been included through the package `@kbn/code-editor-mock`, this would facilitate mocking the editor, especially given that the code editor leverages couple of APIs that are aren't included by default in jsdom, among them, `matchMedia`, `ResizeObserver`. The provided mock is sufficient for most use cases and can be setup in any package within kibana as a [`node_module` mock](https://jestjs.io/docs/manual-mocks#mocking-node-modules) without having to repeatedly manually mock the editor within individual test files. An example for how this might be done can be found here https://github.com/elastic/kibana/pull/171047/commits/ec5ba253688e952c6e601fb6e07de860e2a25c3a ### Checklist - [x] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .github/CODEOWNERS | 3 +- .../public/editor/expression_editor.tsx | 2 +- examples/expressions_explorer/tsconfig.json | 1 + package.json | 3 +- .../components/field_input/code_editor.tsx | 5 +- .../components/field_input/tsconfig.json | 2 +- packages/kbn-monaco/index.ts | 10 +- packages/kbn-monaco/src/monaco_imports.ts | 14 +++ packages/kbn-monaco/src/typings.d.ts | 12 +++ .../src/text_based_languages_editor.tsx | 3 +- packages/kbn-text-based-editor/tsconfig.json | 3 +- packages/kbn-ui-shared-deps-src/BUILD.bazel | 1 + .../kbn-ui-shared-deps-src/src/definitions.js | 1 + packages/kbn-ui-shared-deps-src/src/entry.js | 1 + .../src/utils/get_render_cell_value.test.tsx | 3 +- .../shared-ux/code_editor/impl/BUILD.bazel | 37 +++++++ .../code_editor/{ => impl}/README.mdx | 0 .../__snapshots__/code_editor.test.tsx.snap | 34 ++++++- .../{ => impl}/code_editor.stories.tsx | 0 .../{ => impl}/code_editor.test.tsx | 20 +++- .../code_editor/{ => impl}/code_editor.tsx | 0 .../code_editor/{ => impl}/editor.styles.ts | 0 packages/shared-ux/code_editor/impl/index.tsx | 83 ++++++++++++++++ .../code_editor/{ => impl}/jest.config.js | 2 +- .../code_editor/{ => impl}/kibana.jsonc | 0 .../{ => impl}/languages/constants.ts | 0 .../{ => impl}/languages/css/constants.ts | 0 .../{ => impl}/languages/css/index.ts | 0 .../{ => impl}/languages/css/language.ts | 5 +- .../{ => impl}/languages/grok/constants.ts | 0 .../{ => impl}/languages/grok/index.ts | 0 .../languages/grok/language.test.ts | 0 .../{ => impl}/languages/grok/language.ts | 0 .../languages/handlebars/constants.ts | 0 .../{ => impl}/languages/handlebars/index.ts | 0 .../languages/handlebars/language.ts | 0 .../{ => impl}/languages/hjson/constants.ts | 0 .../{ => impl}/languages/hjson/index.ts | 0 .../{ => impl}/languages/hjson/language.ts | 0 .../code_editor/{ => impl}/languages/index.ts | 0 .../languages/markdown/constants.ts | 0 .../{ => impl}/languages/markdown/index.ts | 0 .../languages/markdown}/language.ts | 5 +- .../{ => impl}/languages/yaml/constants.ts | 0 .../{ => impl}/languages/yaml/index.ts | 0 .../languages/yaml}/language.ts | 5 +- .../code_editor/{ => impl}/mocks/storybook.ts | 0 .../code_editor/{ => impl}/package.json | 0 .../{ => impl}/placeholder_widget.ts | 0 .../{ => impl}/register_languages.ts | 0 .../code_editor/{ => impl}/remeasure_fonts.ts | 0 .../code_editor/{ => impl}/tsconfig.json | 5 +- .../shared-ux/code_editor/mocks/README.md | 23 +++++ .../code_editor/mocks/code_editor_mock.tsx | 28 ++++++ .../code_editor/{ => mocks}/index.ts | 2 +- .../code_editor/mocks/jest_helper.ts | 15 +-- .../shared-ux/code_editor/mocks/kibana.jsonc | 5 + .../monaco_mock/index.tsx} | 96 +++++++++++-------- .../shared-ux/code_editor/mocks/package.json | 6 ++ .../shared-ux/code_editor/mocks/tsconfig.json | 24 +++++ .../components/field/field.test.tsx | 1 + .../components/field/field_code_editor.tsx | 3 +- src/plugins/advanced_settings/tsconfig.json | 2 + .../components/actions/inspect_button.tsx | 7 +- src/plugins/data/tsconfig.json | 3 +- .../data_view_editor/public/shared_imports.ts | 9 +- src/plugins/data_view_editor/tsconfig.json | 1 + .../client_integration/helpers/jest.mocks.tsx | 4 +- .../public/shared_imports.ts | 8 +- .../data_view_field_editor/tsconfig.json | 1 + .../field_editor/field_editor.test.tsx | 4 +- .../components/field_editor/field_editor.tsx | 3 +- .../data_view_management/tsconfig.json | 1 + src/plugins/es_ui_shared/kibana.jsonc | 3 +- .../components/json_editor/json_editor.tsx | 2 +- src/plugins/es_ui_shared/tsconfig.json | 2 +- .../components/details/req_code_viewer.tsx | 3 +- src/plugins/inspector/tsconfig.json | 3 +- .../kibana_react/public/code_editor/README.md | 12 --- .../public/code_editor/code_editor_field.tsx | 38 -------- .../kibana_react/public/code_editor/index.tsx | 66 ------------- src/plugins/kibana_react/public/index.ts | 12 --- .../url_template_editor.stories.tsx | 2 +- .../url_template_editor.tsx | 3 +- src/plugins/kibana_react/tsconfig.json | 1 - .../components/expression_input/constants.ts | 2 +- .../expression_input/expression_input.tsx | 2 +- src/plugins/presentation_util/tsconfig.json | 3 +- .../object_view/components/inspect.tsx | 2 +- .../saved_objects_management/tsconfig.json | 1 + src/plugins/unified_doc_viewer/kibana.jsonc | 2 +- .../doc_viewer_source/source.test.tsx | 1 + .../json_code_editor_common.tsx | 2 +- src/plugins/unified_doc_viewer/tsconfig.json | 4 +- .../filter_editor/filter_editor.test.tsx | 4 +- .../filter_editor/filter_editor.tsx | 2 +- src/plugins/unified_search/tsconfig.json | 3 +- .../public/components/controls/raw_json.tsx | 2 +- src/plugins/vis_default_editor/tsconfig.json | 1 + .../components/timelion_expression_input.tsx | 3 +- src/plugins/vis_types/timelion/tsconfig.json | 1 + .../application/components/markdown_editor.js | 3 +- .../components/panel_config/markdown.tsx | 2 +- .../vis_types/timeseries/tsconfig.json | 1 + .../public/components/vega_vis_editor.tsx | 2 +- .../vega_inspector/components/spec_viewer.tsx | 2 +- src/plugins/vis_types/vega/tsconfig.json | 1 + tsconfig.base.json | 6 +- typings/index.d.ts | 5 - .../testing_embedded_lens/public/app.tsx | 3 +- .../testing_embedded_lens/tsconfig.json | 1 + .../cytoscape_example_data.stories.tsx | 2 +- .../settings_form/form_row_setting.tsx | 2 +- .../shared/monaco_code_editor/index.tsx | 2 +- x-pack/plugins/apm/tsconfig.json | 5 +- .../uis/arguments/editor.tsx | 2 +- .../uis/datasources/essql.js | 2 +- .../canvas_plugin_src/uis/views/markdown.js | 2 +- x-pack/plugins/canvas/tsconfig.json | 1 + .../control_settings/index.test.tsx | 3 +- .../control_yaml_view/index.test.tsx | 2 +- .../components/control_yaml_view/index.tsx | 2 +- .../components/policy_settings/index.test.tsx | 1 + .../public/test/test_provider.tsx | 2 +- x-pack/plugins/cloud_defend/tsconfig.json | 3 +- .../findings_flyout/json_tab.tsx | 2 +- .../vulnerability_finding_flyout.test.tsx | 1 + .../vulnerability_json_tab.tsx | 2 +- .../cloud_security_posture/tsconfig.json | 4 +- .../components/json_editor/json_editor.tsx | 2 +- x-pack/plugins/data_visualizer/tsconfig.json | 1 + .../sync_rules/advanced_sync_rules.tsx | 2 +- .../pipelines/ml_inference/test_pipeline.tsx | 2 +- .../shared/api_key/metadata_form.tsx | 2 +- .../api_key/security_privileges_form.tsx | 2 +- .../plugins/enterprise_search/tsconfig.json | 1 + .../components/import_complete_view.tsx | 3 +- x-pack/plugins/file_upload/tsconfig.json | 1 + .../package_policy_input_var_field.tsx | 2 +- .../sections/debug/components/code_block.tsx | 2 +- .../edit_output_flyout/index.test.tsx | 2 +- .../yaml_code_editor_with_placeholder.tsx | 3 +- x-pack/plugins/fleet/tsconfig.json | 1 + .../custom_patterns_input.js | 2 +- .../components/event_input/event_input.js | 2 +- .../components/pattern_input/pattern_input.js | 3 +- x-pack/plugins/grokdebugger/tsconfig.json | 1 + .../create_enrich_policy.test.tsx | 4 +- .../home/enrich_policies.test.tsx | 4 +- .../index_details_page.test.tsx | 4 +- .../template_create.test.tsx | 4 +- .../template_edit.test.tsx | 4 +- .../component_template_create.test.tsx | 4 +- .../component_template_edit.test.tsx | 8 +- .../helpers/mappings_editor.helpers.tsx | 4 +- .../helpers/setup_environment.tsx | 4 +- .../load_mappings_provider.test.tsx | 4 +- .../components/wizard_steps/step_aliases.tsx | 2 +- .../components/wizard_steps/step_settings.tsx | 2 +- .../details_flyout/policy_details_flyout.tsx | 2 +- .../details_page_settings_content.tsx | 2 +- x-pack/plugins/index_management/tsconfig.json | 1 + .../ingest_pipelines_create.test.tsx | 4 +- .../ingest_pipelines_create_from_csv.test.tsx | 4 +- .../pipeline_processors_editor.helpers.tsx | 4 +- .../__jest__/processors/processor.helpers.tsx | 4 +- .../__jest__/test_pipeline.helpers.tsx | 4 +- .../load_from_json/modal_provider.test.tsx | 4 +- .../pipelines_preview.tsx | 2 +- .../ingest_pipelines/public/shared_imports.ts | 3 +- x-pack/plugins/ingest_pipelines/tsconfig.json | 1 + .../formula/editor/formula_editor.tsx | 3 +- x-pack/plugins/lens/tsconfig.json | 2 + .../pipeline_editor/pipeline_editor.js | 2 +- x-pack/plugins/logstash/tsconfig.json | 1 + .../components/tile_request_tab.tsx | 2 +- .../components/vector_tile_inspector.tsx | 2 +- x-pack/plugins/maps/tsconfig.json | 1 + .../components/processor_configuration.tsx | 2 +- .../ml_inference/components/test_pipeline.tsx | 2 +- .../shared/on_failure_configuration.tsx | 2 +- .../create_analytics_advanced_editor.tsx | 2 +- .../runtime_mappings_editor.tsx | 2 +- .../ml_job_editor/ml_job_editor.tsx | 2 +- .../pipeline_details.tsx | 2 +- x-pack/plugins/ml/tsconfig.json | 1 + .../chat/chat_prompt_editor_function.tsx | 2 +- .../observability_ai_assistant/tsconfig.json | 3 +- .../plugins/osquery/public/editor/index.tsx | 2 +- x-pack/plugins/osquery/tsconfig.json | 3 +- .../public/application/components/editor.tsx | 2 +- .../components/output_pane/context_tab.tsx | 2 +- .../components/output_pane/parameters_tab.tsx | 2 +- x-pack/plugins/painless_lab/tsconfig.json | 1 + .../public/__jest__/setup_environment.tsx | 21 +--- .../runtime_fields/public/shared_imports.ts | 8 +- x-pack/plugins/runtime_fields/tsconfig.json | 2 + .../api_keys/api_keys_grid/api_key_flyout.tsx | 3 +- .../edit_role_mapping_page.test.tsx | 1 + .../json_rule_editor.test.tsx | 3 +- .../rule_editor_panel/json_rule_editor.tsx | 3 +- .../rule_editor_panel.test.tsx | 1 + .../es/index_privilege_form.test.tsx | 4 +- .../privileges/es/index_privilege_form.tsx | 2 +- .../privileges/es/index_privileges.test.tsx | 1 + x-pack/plugins/security/tsconfig.json | 6 +- .../components/api_key/metadata_form.tsx | 2 +- .../api_key/security_privileges_form.tsx | 2 +- .../plugins/serverless_search/tsconfig.json | 1 + .../client_integration/helpers/mocks.tsx | 19 +--- .../type_settings/hdfs_settings.tsx | 2 +- .../steps/step_settings.tsx | 2 +- x-pack/plugins/snapshot_restore/tsconfig.json | 2 + .../expression/es_query_expression.test.tsx | 12 ++- .../expression/es_query_expression.tsx | 2 +- .../es_query/expression/expression.test.tsx | 4 +- x-pack/plugins/stack_alerts/tsconfig.json | 1 + .../__mocks__/@kbn/code-editor/index.tsx | 8 ++ .../connector_types/bedrock/params.test.tsx | 12 --- .../cases_webhook/webhook_connectors.test.tsx | 12 --- .../cases_webhook/webhook_params.test.tsx | 17 +--- .../d3security/params.test.tsx | 12 --- .../es_index/es_index_params.test.tsx | 13 --- .../connector_types/openai/params.test.tsx | 12 --- .../opsgenie/create_alert/index.test.tsx | 13 --- .../create_alert/json_editor.test.tsx | 13 --- .../connector_types/opsgenie/params.test.tsx | 12 --- .../tines/tines_params.test.tsx | 12 --- .../connector_types/torq/torq_params.test.tsx | 13 --- .../webhook/webhook_params.test.tsx | 13 --- x-pack/plugins/stack_connectors/tsconfig.json | 2 + .../__mocks__/@kbn/code-editor/index.ts | 8 ++ .../monitor_add_edit/fields/code_editor.tsx | 2 +- .../fields/request_body_field.test.tsx | 26 +---- .../fields/source_field.test.tsx | 17 ---- .../monitor_add_page.test.tsx | 17 ---- .../monitor_edit_page.test.tsx | 17 ---- x-pack/plugins/synthetics/tsconfig.json | 5 +- .../advanced_pivot_editor.tsx | 2 +- .../advanced_runtime_mappings_editor.tsx | 2 +- .../advanced_source_editor.tsx | 2 +- .../filter_agg/components/editor_form.tsx | 2 +- x-pack/plugins/transform/tsconfig.json | 3 +- .../public/application/code_editor.mock.tsx | 35 ------- ...son_editor_with_message_variables.test.tsx | 10 +- .../json_editor_with_message_variables.tsx | 2 +- .../plugins/triggers_actions_ui/tsconfig.json | 4 +- ...ics_edit_policy_extension_wrapper.test.tsx | 4 +- .../watch_create_json_page.test.tsx | 4 +- .../watch_create_threshold_page.test.tsx | 4 +- .../watch_edit_page.test.tsx | 4 +- .../json_watch_edit/json_watch_edit_form.tsx | 2 +- .../json_watch_edit_simulate.tsx | 2 +- .../action_fields/webhook_action_fields.tsx | 2 +- x-pack/plugins/watcher/tsconfig.json | 1 + yarn.lock | 6 +- 256 files changed, 671 insertions(+), 696 deletions(-) create mode 100644 packages/kbn-monaco/src/typings.d.ts create mode 100644 packages/shared-ux/code_editor/impl/BUILD.bazel rename packages/shared-ux/code_editor/{ => impl}/README.mdx (100%) rename packages/shared-ux/code_editor/{ => impl}/__snapshots__/code_editor.test.tsx.snap (88%) rename packages/shared-ux/code_editor/{ => impl}/code_editor.stories.tsx (100%) rename packages/shared-ux/code_editor/{ => impl}/code_editor.test.tsx (94%) rename packages/shared-ux/code_editor/{ => impl}/code_editor.tsx (100%) rename packages/shared-ux/code_editor/{ => impl}/editor.styles.ts (100%) create mode 100644 packages/shared-ux/code_editor/impl/index.tsx rename packages/shared-ux/code_editor/{ => impl}/jest.config.js (94%) rename packages/shared-ux/code_editor/{ => impl}/kibana.jsonc (100%) rename packages/shared-ux/code_editor/{ => impl}/languages/constants.ts (100%) rename packages/shared-ux/code_editor/{ => impl}/languages/css/constants.ts (100%) rename packages/shared-ux/code_editor/{ => impl}/languages/css/index.ts (100%) rename packages/shared-ux/code_editor/{ => impl}/languages/css/language.ts (64%) rename packages/shared-ux/code_editor/{ => impl}/languages/grok/constants.ts (100%) rename packages/shared-ux/code_editor/{ => impl}/languages/grok/index.ts (100%) rename packages/shared-ux/code_editor/{ => impl}/languages/grok/language.test.ts (100%) rename packages/shared-ux/code_editor/{ => impl}/languages/grok/language.ts (100%) rename packages/shared-ux/code_editor/{ => impl}/languages/handlebars/constants.ts (100%) rename packages/shared-ux/code_editor/{ => impl}/languages/handlebars/index.ts (100%) rename packages/shared-ux/code_editor/{ => impl}/languages/handlebars/language.ts (100%) rename packages/shared-ux/code_editor/{ => impl}/languages/hjson/constants.ts (100%) rename packages/shared-ux/code_editor/{ => impl}/languages/hjson/index.ts (100%) rename packages/shared-ux/code_editor/{ => impl}/languages/hjson/language.ts (100%) rename packages/shared-ux/code_editor/{ => impl}/languages/index.ts (100%) rename packages/shared-ux/code_editor/{ => impl}/languages/markdown/constants.ts (100%) rename packages/shared-ux/code_editor/{ => impl}/languages/markdown/index.ts (100%) rename packages/shared-ux/code_editor/{languages/yaml => impl/languages/markdown}/language.ts (64%) rename packages/shared-ux/code_editor/{ => impl}/languages/yaml/constants.ts (100%) rename packages/shared-ux/code_editor/{ => impl}/languages/yaml/index.ts (100%) rename packages/shared-ux/code_editor/{languages/markdown => impl/languages/yaml}/language.ts (63%) rename packages/shared-ux/code_editor/{ => impl}/mocks/storybook.ts (100%) rename packages/shared-ux/code_editor/{ => impl}/package.json (100%) rename packages/shared-ux/code_editor/{ => impl}/placeholder_widget.ts (100%) rename packages/shared-ux/code_editor/{ => impl}/register_languages.ts (100%) rename packages/shared-ux/code_editor/{ => impl}/remeasure_fonts.ts (100%) rename packages/shared-ux/code_editor/{ => impl}/tsconfig.json (80%) create mode 100644 packages/shared-ux/code_editor/mocks/README.md create mode 100644 packages/shared-ux/code_editor/mocks/code_editor_mock.tsx rename packages/shared-ux/code_editor/{ => mocks}/index.ts (84%) rename src/plugins/kibana_react/public/code_editor/code_editor.tsx => packages/shared-ux/code_editor/mocks/jest_helper.ts (58%) create mode 100644 packages/shared-ux/code_editor/mocks/kibana.jsonc rename packages/shared-ux/code_editor/{code_editor.test.helpers.tsx => mocks/monaco_mock/index.tsx} (66%) create mode 100644 packages/shared-ux/code_editor/mocks/package.json create mode 100644 packages/shared-ux/code_editor/mocks/tsconfig.json delete mode 100644 src/plugins/kibana_react/public/code_editor/README.md delete mode 100644 src/plugins/kibana_react/public/code_editor/code_editor_field.tsx delete mode 100644 src/plugins/kibana_react/public/code_editor/index.tsx create mode 100644 x-pack/plugins/stack_connectors/__mocks__/@kbn/code-editor/index.tsx create mode 100644 x-pack/plugins/synthetics/__mocks__/@kbn/code-editor/index.ts delete mode 100644 x-pack/plugins/triggers_actions_ui/public/application/code_editor.mock.tsx diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 4dae217dce6a..d2d3d6b0f1b3 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -86,7 +86,8 @@ x-pack/test/cloud_integration/plugins/saml_provider @elastic/kibana-core x-pack/plugins/cloud_integrations/cloud_links @elastic/kibana-core x-pack/plugins/cloud @elastic/kibana-core x-pack/plugins/cloud_security_posture @elastic/kibana-cloud-security-posture -packages/shared-ux/code_editor @elastic/appex-sharedux +packages/shared-ux/code_editor/impl @elastic/appex-sharedux +packages/shared-ux/code_editor/mocks @elastic/appex-sharedux packages/kbn-code-owners @elastic/appex-qa packages/kbn-coloring @elastic/kibana-visualizations packages/kbn-config @elastic/kibana-core diff --git a/examples/expressions_explorer/public/editor/expression_editor.tsx b/examples/expressions_explorer/public/editor/expression_editor.tsx index c940a21fada2..998a9e486ba1 100644 --- a/examples/expressions_explorer/public/editor/expression_editor.tsx +++ b/examples/expressions_explorer/public/editor/expression_editor.tsx @@ -7,7 +7,7 @@ */ import React from 'react'; -import { CodeEditor } from '@kbn/kibana-react-plugin/public'; +import { CodeEditor } from '@kbn/code-editor'; interface Props { value: string; diff --git a/examples/expressions_explorer/tsconfig.json b/examples/expressions_explorer/tsconfig.json index 717a79717359..b75817c68be7 100644 --- a/examples/expressions_explorer/tsconfig.json +++ b/examples/expressions_explorer/tsconfig.json @@ -22,5 +22,6 @@ "@kbn/i18n", "@kbn/i18n-react", "@kbn/core-ui-settings-browser", + "@kbn/code-editor", ] } diff --git a/package.json b/package.json index 23e49b0d4cb3..22ac58584521 100644 --- a/package.json +++ b/package.json @@ -192,7 +192,8 @@ "@kbn/cloud-links-plugin": "link:x-pack/plugins/cloud_integrations/cloud_links", "@kbn/cloud-plugin": "link:x-pack/plugins/cloud", "@kbn/cloud-security-posture-plugin": "link:x-pack/plugins/cloud_security_posture", - "@kbn/code-editor": "link:packages/shared-ux/code_editor", + "@kbn/code-editor": "link:packages/shared-ux/code_editor/impl", + "@kbn/code-editor-mock": "link:packages/shared-ux/code_editor/mocks", "@kbn/coloring": "link:packages/kbn-coloring", "@kbn/config": "link:packages/kbn-config", "@kbn/config-mocks": "link:packages/kbn-config-mocks", diff --git a/packages/kbn-management/settings/components/field_input/code_editor.tsx b/packages/kbn-management/settings/components/field_input/code_editor.tsx index 3f46778917fd..ac1ea672d8a1 100644 --- a/packages/kbn-management/settings/components/field_input/code_editor.tsx +++ b/packages/kbn-management/settings/components/field_input/code_editor.tsx @@ -15,11 +15,12 @@ import React, { useCallback } from 'react'; import { monaco, XJsonLang } from '@kbn/monaco'; + import { CodeEditor as KibanaReactCodeEditor, - MarkdownLang, type CodeEditorProps as KibanaReactCodeEditorProps, -} from '@kbn/kibana-react-plugin/public'; + MarkdownLang, +} from '@kbn/code-editor'; type Props = Pick; type Options = KibanaReactCodeEditorProps['options']; diff --git a/packages/kbn-management/settings/components/field_input/tsconfig.json b/packages/kbn-management/settings/components/field_input/tsconfig.json index bb4c6b4aa57d..d971549abb2d 100644 --- a/packages/kbn-management/settings/components/field_input/tsconfig.json +++ b/packages/kbn-management/settings/components/field_input/tsconfig.json @@ -19,7 +19,6 @@ "@kbn/management-settings-types", "@kbn/management-settings-field-definition", "@kbn/monaco", - "@kbn/kibana-react-plugin", "@kbn/management-settings-utilities", "@kbn/i18n-react", "@kbn/i18n", @@ -30,5 +29,6 @@ "@kbn/core-i18n-browser", "@kbn/core-analytics-browser-mocks", "@kbn/core-ui-settings-browser", + "@kbn/code-editor", ] } diff --git a/packages/kbn-monaco/index.ts b/packages/kbn-monaco/index.ts index 2ebb05bd0e39..e2e3c32d9d0f 100644 --- a/packages/kbn-monaco/index.ts +++ b/packages/kbn-monaco/index.ts @@ -8,7 +8,15 @@ import './src/register_globals'; -export { monaco } from './src/monaco_imports'; +export { + monaco, + cssConf, + cssLanguage, + markdownConf, + markdownLanguage, + yamlConf, + yamlLanguage, +} from './src/monaco_imports'; export { XJsonLang } from './src/xjson'; export { SQLLang } from './src/sql'; export { ESQL_LANG_ID, ESQL_THEME_ID, ESQLLang } from './src/esql'; diff --git a/packages/kbn-monaco/src/monaco_imports.ts b/packages/kbn-monaco/src/monaco_imports.ts index 9da2a3f4562f..cebdb7ffa104 100644 --- a/packages/kbn-monaco/src/monaco_imports.ts +++ b/packages/kbn-monaco/src/monaco_imports.ts @@ -28,4 +28,18 @@ import 'monaco-editor/esm/vs/basic-languages/javascript/javascript.contribution. import 'monaco-editor/esm/vs/basic-languages/xml/xml.contribution.js'; // Needed for basic xml support import 'monaco-editor/esm/vs/basic-languages/yaml/yaml.contribution'; // Needed for yaml support +// config for supported base languages +export { + conf as cssConf, + language as cssLanguage, +} from 'monaco-editor/esm/vs/basic-languages/css/css'; +export { + conf as markdownConf, + language as markdownLanguage, +} from 'monaco-editor/esm/vs/basic-languages/markdown/markdown'; +export { + conf as yamlConf, + language as yamlLanguage, +} from 'monaco-editor/esm/vs/basic-languages/yaml/yaml'; + export { monaco }; diff --git a/packages/kbn-monaco/src/typings.d.ts b/packages/kbn-monaco/src/typings.d.ts new file mode 100644 index 000000000000..64301b9a5968 --- /dev/null +++ b/packages/kbn-monaco/src/typings.d.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 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. + */ + +// Monaco languages support +declare module 'monaco-editor/esm/vs/basic-languages/markdown/markdown'; +declare module 'monaco-editor/esm/vs/basic-languages/css/css'; +declare module 'monaco-editor/esm/vs/basic-languages/yaml/yaml'; diff --git a/packages/kbn-text-based-editor/src/text_based_languages_editor.tsx b/packages/kbn-text-based-editor/src/text_based_languages_editor.tsx index 24966c78960b..3546fcec41af 100644 --- a/packages/kbn-text-based-editor/src/text_based_languages_editor.tsx +++ b/packages/kbn-text-based-editor/src/text_based_languages_editor.tsx @@ -39,8 +39,7 @@ import { EuiOutsideClickDetector, EuiToolTip, } from '@elastic/eui'; -import { CodeEditor } from '@kbn/kibana-react-plugin/public'; -import type { CodeEditorProps } from '@kbn/kibana-react-plugin/public'; +import { CodeEditor, CodeEditorProps } from '@kbn/code-editor'; import { textBasedLanguagedEditorStyles, diff --git a/packages/kbn-text-based-editor/tsconfig.json b/packages/kbn-text-based-editor/tsconfig.json index 72240c8aa060..1c71fc544155 100644 --- a/packages/kbn-text-based-editor/tsconfig.json +++ b/packages/kbn-text-based-editor/tsconfig.json @@ -24,7 +24,8 @@ "@kbn/expressions-plugin", "@kbn/data-views-plugin", "@kbn/index-management-plugin", - "@kbn/visualization-utils" + "@kbn/visualization-utils", + "@kbn/code-editor", ], "exclude": [ "target/**/*", diff --git a/packages/kbn-ui-shared-deps-src/BUILD.bazel b/packages/kbn-ui-shared-deps-src/BUILD.bazel index cd97c193f9f8..9e62a7418f15 100644 --- a/packages/kbn-ui-shared-deps-src/BUILD.bazel +++ b/packages/kbn-ui-shared-deps-src/BUILD.bazel @@ -35,6 +35,7 @@ webpack_cli( "//packages/kbn-peggy-loader", "//packages/shared-ux/error_boundary", "//packages/kbn-rison", + "//packages/shared-ux/code_editor/impl:code_editor", ], output_dir = True, args = [ diff --git a/packages/kbn-ui-shared-deps-src/src/definitions.js b/packages/kbn-ui-shared-deps-src/src/definitions.js index 9ae258dca6bc..7480303087b6 100644 --- a/packages/kbn-ui-shared-deps-src/src/definitions.js +++ b/packages/kbn-ui-shared-deps-src/src/definitions.js @@ -98,6 +98,7 @@ const externals = { classnames: '__kbnSharedDeps__.Classnames', '@tanstack/react-query': '__kbnSharedDeps__.ReactQuery', '@tanstack/react-query-devtools': '__kbnSharedDeps__.ReactQueryDevtools', + '@kbn/code-editor': '__kbnSharedDeps__.KbnCodeEditor', }; module.exports = { distDir, jsFilename, cssDistFilename, externals }; diff --git a/packages/kbn-ui-shared-deps-src/src/entry.js b/packages/kbn-ui-shared-deps-src/src/entry.js index 6ba856cbbc2d..d0585d0cacc0 100644 --- a/packages/kbn-ui-shared-deps-src/src/entry.js +++ b/packages/kbn-ui-shared-deps-src/src/entry.js @@ -74,3 +74,4 @@ export const History = require('history'); export const Classnames = require('classnames'); export const ReactQuery = require('@tanstack/react-query'); export const ReactQueryDevtools = require('@tanstack/react-query-devtools'); +export const KbnCodeEditor = require('@kbn/code-editor'); diff --git a/packages/kbn-unified-data-table/src/utils/get_render_cell_value.test.tsx b/packages/kbn-unified-data-table/src/utils/get_render_cell_value.test.tsx index 7db7ffedfdec..c59acdc81538 100644 --- a/packages/kbn-unified-data-table/src/utils/get_render_cell_value.test.tsx +++ b/packages/kbn-unified-data-table/src/utils/get_render_cell_value.test.tsx @@ -13,7 +13,8 @@ import { findTestSubject } from '@elastic/eui/lib/test'; import { mountWithIntl } from '@kbn/test-jest-helpers'; import { getRenderCellValueFn } from './get_render_cell_value'; import { dataViewMock } from '@kbn/discover-utils/src/__mocks__'; -import { CodeEditorProps, KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; +import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; +import { CodeEditorProps } from '@kbn/code-editor'; import { buildDataTableRecord } from '@kbn/discover-utils'; import type { EsHitRecord } from '@kbn/discover-utils/types'; import { FieldFormatsStart } from '@kbn/field-formats-plugin/public'; diff --git a/packages/shared-ux/code_editor/impl/BUILD.bazel b/packages/shared-ux/code_editor/impl/BUILD.bazel new file mode 100644 index 000000000000..ad571cb379af --- /dev/null +++ b/packages/shared-ux/code_editor/impl/BUILD.bazel @@ -0,0 +1,37 @@ +load("@build_bazel_rules_nodejs//:index.bzl", "js_library") + +SRCS = glob( + [ + "**/*.ts", + "**/*.tsx", + ], + exclude = [ + "**/test_helpers.ts", + "**/*.config.js", + "**/*.mock.*", + "**/*.test.*", + "**/*.stories.*", + "**/__snapshots__/**", + "**/integration_tests/**", + "**/mocks/**", + "**/scripts/**", + "**/storybook/**", + "**/test_fixtures/**", + "**/test_helpers/**", + ], +) + +BUNDLER_DEPS = [ + "@npm//react", + "@npm//tslib", + "@npm//react-monaco-editor", + "@npm//react-resize-detector", +] + +js_library( + name = "code_editor", + package_name = "@kbn/code-editor", + srcs = SRCS + ["package.json"], + deps = BUNDLER_DEPS, + visibility = ["//visibility:public"], +) diff --git a/packages/shared-ux/code_editor/README.mdx b/packages/shared-ux/code_editor/impl/README.mdx similarity index 100% rename from packages/shared-ux/code_editor/README.mdx rename to packages/shared-ux/code_editor/impl/README.mdx diff --git a/packages/shared-ux/code_editor/__snapshots__/code_editor.test.tsx.snap b/packages/shared-ux/code_editor/impl/__snapshots__/code_editor.test.tsx.snap similarity index 88% rename from packages/shared-ux/code_editor/__snapshots__/code_editor.test.tsx.snap rename to packages/shared-ux/code_editor/impl/__snapshots__/code_editor.test.tsx.snap index 790a4f05f8c5..4fb960f82cc7 100644 --- a/packages/shared-ux/code_editor/__snapshots__/code_editor.test.tsx.snap +++ b/packages/shared-ux/code_editor/impl/__snapshots__/code_editor.test.tsx.snap @@ -290,7 +290,7 @@ exports[` is rendered 1`] = ` - is rendered 1`] = `