diff --git a/.buildkite/ftr_configs.yml b/.buildkite/ftr_configs.yml index 16a8c6ee0b0bf..b03abf9a15c67 100644 --- a/.buildkite/ftr_configs.yml +++ b/.buildkite/ftr_configs.yml @@ -7,6 +7,7 @@ disabled: - x-pack/test/functional/config.base.js - x-pack/test/detection_engine_api_integration/security_and_spaces/config.base.ts - x-pack/test/functional_enterprise_search/base_config.ts + - x-pack/test/localization/config.base.ts - test/server_integration/config.base.js # QA suites that are run out-of-band @@ -116,6 +117,9 @@ enabled: - test/server_integration/http/ssl/config.js - test/ui_capabilities/newsfeed_err/config.ts - x-pack/test/accessibility/config.ts + - x-pack/test/localization/config.ja_jp.ts + - x-pack/test/localization/config.fr_fr.ts + - x-pack/test/localization/config.zh_cn.ts - x-pack/test/alerting_api_integration/basic/config.ts - x-pack/test/alerting_api_integration/security_and_spaces/group1/config.ts - x-pack/test/alerting_api_integration/security_and_spaces/group2/config.ts diff --git a/.buildkite/scripts/pipelines/pull_request/pipeline.ts b/.buildkite/scripts/pipelines/pull_request/pipeline.ts index ca18f62c60866..5722d8ea7d5a3 100644 --- a/.buildkite/scripts/pipelines/pull_request/pipeline.ts +++ b/.buildkite/scripts/pipelines/pull_request/pipeline.ts @@ -56,6 +56,7 @@ const uploadPipeline = (pipelineContent: string | object) => { if ( (await doAnyChangesMatch([ + /^packages\/kbn-securitysolution-.*/, /^x-pack\/plugins\/lists/, /^x-pack\/plugins\/security_solution/, /^x-pack\/plugins\/timelines/, diff --git a/.buildkite/scripts/steps/test/jest_parallel.sh b/.buildkite/scripts/steps/test/jest_parallel.sh index dfaa2db079dd8..8a7f94157d61b 100755 --- a/.buildkite/scripts/steps/test/jest_parallel.sh +++ b/.buildkite/scripts/steps/test/jest_parallel.sh @@ -26,6 +26,13 @@ echo "--- downloading jest test run order" download_artifact jest_run_order.json . configs=$(jq -r 'getpath([env.TEST_TYPE]) | .groups[env.JOB | tonumber].names | .[]' jest_run_order.json) +echo "+++ ⚠️ WARNING ⚠️" +echo " + console.log(), console.warn(), and console.error() output in jest tests causes a massive amount + of noise on CI without any percevable benefit, so they have been disabled. If you want to log + output in your test temporarily, you can modify 'packages/kbn-test/src/jest/setup/disable_console_logs.js' +" + while read -r config; do echo "--- $ node scripts/jest --config $config" diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 5415be755195b..e1b4caff71a88 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -12,6 +12,7 @@ /src/plugins/discover/ @elastic/kibana-data-discovery /src/plugins/saved_search/ @elastic/kibana-data-discovery /x-pack/plugins/discover_enhanced/ @elastic/kibana-data-discovery +/x-pack/test/functional/apps/discover/ @elastic/kibana-data-discovery /test/functional/apps/discover/ @elastic/kibana-data-discovery /test/functional/apps/context/ @elastic/kibana-data-discovery /test/api_integration/apis/unified_field_list/ @elastic/kibana-data-discovery @@ -22,6 +23,14 @@ /src/plugins/data_view_editor/ @elastic/kibana-data-discovery /src/plugins/data_view_field_editor/ @elastic/kibana-data-discovery /src/plugins/data_view_management/ @elastic/kibana-data-discovery +/src/plugins/data/ @elastic/kibana-visualizations @elastic/kibana-data-discovery +/src/plugins/field_formats/ @elastic/kibana-data-discovery +/x-pack/test/search_sessions_integration/ @elastic/kibana-data-discovery +/test/plugin_functional/test_suites/data_plugin @elastic/kibana-data-discovery +/examples/field_formats_example/ @elastic/kibana-data-discovery +/examples/partial_results_example/ @elastic/kibana-data-discovery +/examples/search_examples/ @elastic/kibana-data-discovery +/examples/demo_search/ @elastic/kibana-data-discovery # Vis Editors /x-pack/plugins/lens/ @elastic/kibana-visualizations @@ -55,29 +64,6 @@ /x-pack/plugins/graph/ @elastic/kibana-visualizations /x-pack/test/functional/apps/graph @elastic/kibana-visualizations -# Application Services -/examples/dashboard_embeddable_examples/ @elastic/kibana-app-services -/examples/demo_search/ @elastic/kibana-app-services -/examples/developer_examples/ @elastic/kibana-app-services -/examples/embeddable_examples/ @elastic/kibana-app-services -/examples/embeddable_explorer/ @elastic/kibana-app-services -/examples/field_formats_example/ @elastic/kibana-app-services -/examples/partial_results_example/ @elastic/kibana-app-services -/examples/search_examples/ @elastic/kibana-app-services -/src/plugins/data/ @elastic/kibana-visualizations @elastic/kibana-data-discovery -/src/plugins/embeddable/ @elastic/kibana-app-services -/src/plugins/field_formats/ @elastic/kibana-app-services -/src/plugins/inspector/ @elastic/kibana-app-services -/src/plugins/kibana_utils/ @elastic/kibana-app-services -/src/plugins/navigation/ @elastic/kibana-app-services -/src/plugins/inspector/ @elastic/kibana-app-services -/x-pack/plugins/embeddable_enhanced/ @elastic/kibana-app-services -/x-pack/plugins/runtime_fields @elastic/kibana-app-services -/src/plugins/dashboard/public/application/embeddable/viewport/print_media @elastic/kibana-app-services -/x-pack/test/search_sessions_integration/ @elastic/kibana-app-services -/test/plugin_functional/test_suites/panel_actions @elastic/kibana-app-services -/test/plugin_functional/test_suites/data_plugin @elastic/kibana-app-services - # Global Experience /src/plugins/bfetch/ @elastic/kibana-global-experience @@ -86,7 +72,7 @@ /src/plugins/share/ @elastic/kibana-global-experience /src/plugins/ui_actions/ @elastic/kibana-global-experience /src/plugins/ui_actions_enhanced/ @elastic/kibana-global-experience - +/src/plugins/navigation/ @elastic/kibana-global-experience /x-pack/plugins/notifications/ @elastic/kibana-global-experience ## Examples @@ -95,6 +81,7 @@ /examples/state_containers_examples/ @elastic/kibana-global-experience /examples/ui_action_examples/ @elastic/kibana-global-experience /examples/ui_actions_explorer/ @elastic/kibana-global-experience +/examples/developer_examples/ @elastic/kibana-global-experience /x-pack/examples/ui_actions_enhanced_examples/ @elastic/kibana-global-experience ### Overview Plugin and Packages @@ -119,7 +106,7 @@ /docs/setup/configuring-reporting.asciidoc @elastic/kibana-global-experience ### Global Experience Tagging -/src/plugins/saved_objects_tagging_oss @elastic/kibana-global-experience +/src/plugins/saved_objects_tagging_oss @elastic/kibana-global-experience /x-pack/plugins/saved_objects_tagging/ @elastic/kibana-global-experience /x-pack/test/saved_object_tagging/ @elastic/kibana-global-experience @@ -234,7 +221,14 @@ /test/functional/services/dashboard/ @elastic/kibana-presentation /x-pack/plugins/canvas/ @elastic/kibana-presentation /x-pack/plugins/dashboard_enhanced/ @elastic/kibana-presentation -/x-pack/test/functional/apps/canvas/ @elastic/kibana-presentation +/x-pack/test/functional/apps/canvas/ @elastic/kibana-presentation +/examples/dashboard_embeddable_examples/ @elastic/kibana-presentation +/examples/embeddable_examples/ @elastic/kibana-presentation +/examples/embeddable_explorer/ @elastic/kibana-presentation +/src/plugins/embeddable/ @elastic/kibana-presentation +/src/plugins/inspector/ @elastic/kibana-presentation +/x-pack/plugins/embeddable_enhanced/ @elastic/kibana-presentation +/test/plugin_functional/test_suites/panel_actions @elastic/kibana-presentation #CC# /src/plugins/kibana_react/public/code_editor/ @elastic/kibana-presentation # Machine Learning @@ -416,7 +410,8 @@ /x-pack/plugins/cross_cluster_replication/ @elastic/platform-deployment-management /x-pack/plugins/index_lifecycle_management/ @elastic/platform-deployment-management /x-pack/plugins/grokdebugger/ @elastic/platform-deployment-management -/x-pack/plugins/index_management/ @elastic/platform-deployment-management +/x-pack/plugins/index_management/ @elastic/platform-deployment-management +/x-pack/plugins/runtime_fields @elastic/platform-deployment-management /x-pack/plugins/license_api_guard/ @elastic/platform-deployment-management /x-pack/plugins/license_management/ @elastic/platform-deployment-management /x-pack/plugins/painless_lab/ @elastic/platform-deployment-management @@ -960,7 +955,7 @@ packages/kbn-logging-mocks @elastic/kibana-core packages/kbn-managed-vscode-config @elastic/kibana-operations packages/kbn-managed-vscode-config-cli @elastic/kibana-operations packages/kbn-mapbox-gl @elastic/kibana-gis -packages/kbn-monaco @elastic/kibana-app-services +packages/kbn-monaco @elastic/kibana-global-experience packages/kbn-optimizer @elastic/kibana-operations packages/kbn-optimizer-webpack-helpers @elastic/kibana-operations packages/kbn-osquery-io-ts-types @elastic/security-asset-management @@ -973,6 +968,7 @@ packages/kbn-plugin-helpers @elastic/kibana-operations packages/kbn-react-field @elastic/kibana-app-services packages/kbn-repo-source-classifier @elastic/kibana-operations packages/kbn-repo-source-classifier-cli @elastic/kibana-operations +packages/kbn-rison @elastic/kibana-operations packages/kbn-rule-data-utils @elastic/security-detections-response @elastic/actionable-observability @elastic/response-ops packages/kbn-safer-lodash-set @elastic/kibana-security packages/kbn-securitysolution-autocomplete @elastic/security-solution-platform @@ -1063,6 +1059,7 @@ packages/shared-ux/page/solution_nav @elastic/kibana-global-experience packages/shared-ux/prompt/no_data_views/impl @elastic/kibana-global-experience packages/shared-ux/prompt/no_data_views/mocks @elastic/kibana-global-experience packages/shared-ux/prompt/no_data_views/types @elastic/kibana-global-experience +packages/shared-ux/prompt/not_found @elastic/kibana-global-experience packages/shared-ux/router/impl @elastic/kibana-global-experience packages/shared-ux/router/mocks @elastic/kibana-global-experience packages/shared-ux/router/types @elastic/kibana-global-experience diff --git a/api_docs/actions.devdocs.json b/api_docs/actions.devdocs.json index daf7786bf9b0c..22b480c048a51 100644 --- a/api_docs/actions.devdocs.json +++ b/api_docs/actions.devdocs.json @@ -1967,7 +1967,7 @@ }, "<", "ActionTypeConfig", - ">[]>; getOAuthAccessToken: ({ type, options }: Readonly<{} & { options: Readonly<{} & { config: Readonly<{} & { clientId: string; jwtKeyId: string; userIdentifierValue: string; }>; tokenUrl: string; secrets: Readonly<{ privateKeyPassword?: string | undefined; } & { clientSecret: string; privateKey: string; }>; }> | Readonly<{} & { scope: string; config: Readonly<{} & { clientId: string; tenantId: string; }>; tokenUrl: string; secrets: Readonly<{} & { clientSecret: string; }>; }>; type: \"client\" | \"jwt\"; }>, configurationUtilities: ", + ">[]>; getOAuthAccessToken: ({ type, options }: Readonly<{} & { options: Readonly<{} & { config: Readonly<{} & { clientId: string; jwtKeyId: string; userIdentifierValue: string; }>; tokenUrl: string; secrets: Readonly<{ privateKeyPassword?: string | undefined; } & { clientSecret: string; privateKey: string; }>; }> | Readonly<{} & { scope: string; config: Readonly<{} & { clientId: string; tenantId: string; }>; tokenUrl: string; secrets: Readonly<{} & { clientSecret: string; }>; }>; type: \"jwt\" | \"client\"; }>, configurationUtilities: ", "ActionsConfigurationUtilities", ") => Promise<{ accessToken: string | null; }>; enqueueExecution: (options: ", "ExecuteOptions", diff --git a/api_docs/actions.mdx b/api_docs/actions.mdx index bfd911f56b0c1..ff19463641bdf 100644 --- a/api_docs/actions.mdx +++ b/api_docs/actions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/actions title: "actions" image: https://source.unsplash.com/400x175/?github description: API docs for the actions plugin -date: 2022-11-29 +date: 2022-12-06 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 1cd9b91a3ff85..4a35439d40109 100644 --- a/api_docs/advanced_settings.mdx +++ b/api_docs/advanced_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/advancedSettings title: "advancedSettings" image: https://source.unsplash.com/400x175/?github description: API docs for the advancedSettings plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'advancedSettings'] --- import advancedSettingsObj from './advanced_settings.devdocs.json'; diff --git a/api_docs/aiops.devdocs.json b/api_docs/aiops.devdocs.json index 6ee28ad0d4fa6..ce17371ced270 100644 --- a/api_docs/aiops.devdocs.json +++ b/api_docs/aiops.devdocs.json @@ -203,7 +203,7 @@ "label": "CHANGE_POINT_DETECTION_ENABLED", "description": [], "signature": [ - "false" + "true" ], "path": "x-pack/plugins/aiops/common/index.ts", "deprecated": false, diff --git a/api_docs/aiops.mdx b/api_docs/aiops.mdx index b02a001e37228..9db17d6564262 100644 --- a/api_docs/aiops.mdx +++ b/api_docs/aiops.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/aiops title: "aiops" image: https://source.unsplash.com/400x175/?github description: API docs for the aiops plugin -date: 2022-11-29 +date: 2022-12-06 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 9ad42cdce240f..df8867d62870f 100644 --- a/api_docs/alerting.devdocs.json +++ b/api_docs/alerting.devdocs.json @@ -3010,7 +3010,7 @@ "section": "def-common.SanitizedRule", "text": "SanitizedRule" }, - ">; muteAll: ({ id }: { id: string; }) => Promise; getAlertState: ({ id }: { id: string; }) => Promise; getAlertSummary: ({ id, dateStart, numberOfExecutions, }: ", + ">; muteAll: ({ id }: { id: string; }) => Promise; getAlertState: ({ id }: { id: string; }) => Promise; getAlertSummary: ({ id, dateStart, numberOfExecutions, }: ", "GetAlertSummaryParams", ") => Promise<", { @@ -5465,7 +5465,7 @@ "label": "status", "description": [], "signature": [ - "\"error\" | \"warning\" | \"unknown\" | \"pending\" | \"ok\" | \"active\"" + "\"error\" | \"warning\" | \"unknown\" | \"pending\" | \"active\" | \"ok\"" ], "path": "x-pack/plugins/alerting/common/rule.ts", "deprecated": false, @@ -6522,7 +6522,7 @@ "label": "AlertInstanceMeta", "description": [], "signature": [ - "{ lastScheduledActions?: ({ subgroup?: string | undefined; } & { group: string; date: Date; }) | undefined; }" + "{ lastScheduledActions?: ({ subgroup?: string | undefined; } & { group: string; date: Date; }) | undefined; flappingHistory?: boolean[] | undefined; flapping?: boolean | undefined; }" ], "path": "x-pack/plugins/alerting/common/alert_instance.ts", "deprecated": false, @@ -6716,7 +6716,7 @@ "label": "RawAlertInstance", "description": [], "signature": [ - "{ state?: { [x: string]: unknown; } | undefined; meta?: { lastScheduledActions?: ({ subgroup?: string | undefined; } & { group: string; date: Date; }) | undefined; } | undefined; }" + "{ state?: { [x: string]: unknown; } | undefined; meta?: { lastScheduledActions?: ({ subgroup?: string | undefined; } & { group: string; date: Date; }) | undefined; flappingHistory?: boolean[] | undefined; flapping?: boolean | undefined; } | undefined; }" ], "path": "x-pack/plugins/alerting/common/alert_instance.ts", "deprecated": false, @@ -6857,7 +6857,7 @@ "label": "RuleExecutionStatuses", "description": [], "signature": [ - "\"error\" | \"warning\" | \"unknown\" | \"pending\" | \"ok\" | \"active\"" + "\"error\" | \"warning\" | \"unknown\" | \"pending\" | \"active\" | \"ok\"" ], "path": "x-pack/plugins/alerting/common/rule.ts", "deprecated": false, @@ -6976,7 +6976,7 @@ "label": "RuleTaskState", "description": [], "signature": [ - "{ alertTypeState?: { [x: string]: unknown; } | undefined; alertInstances?: { [x: string]: { state?: { [x: string]: unknown; } | undefined; meta?: { lastScheduledActions?: ({ subgroup?: string | undefined; } & { group: string; date: Date; }) | undefined; } | undefined; }; } | undefined; previousStartedAt?: Date | null | undefined; }" + "{ alertTypeState?: { [x: string]: unknown; } | undefined; alertInstances?: { [x: string]: { state?: { [x: string]: unknown; } | undefined; meta?: { lastScheduledActions?: ({ subgroup?: string | undefined; } & { group: string; date: Date; }) | undefined; flappingHistory?: boolean[] | undefined; flapping?: boolean | undefined; } | undefined; }; } | undefined; alertRecoveredInstances?: { [x: string]: { state?: { [x: string]: unknown; } | undefined; meta?: { lastScheduledActions?: ({ subgroup?: string | undefined; } & { group: string; date: Date; }) | undefined; flappingHistory?: boolean[] | undefined; flapping?: boolean | undefined; } | undefined; }; } | undefined; previousStartedAt?: Date | null | undefined; }" ], "path": "x-pack/plugins/alerting/common/rule_task_instance.ts", "deprecated": false, @@ -7304,7 +7304,13 @@ "StringC", "; date: ", "Type", - "; }>]>; }>; }>" + "; }>]>; flappingHistory: ", + "ArrayC", + "<", + "BooleanC", + ">; flapping: ", + "BooleanC", + "; }>; }>" ], "path": "x-pack/plugins/alerting/common/alert_instance.ts", "deprecated": false, @@ -7436,7 +7442,45 @@ "StringC", "; date: ", "Type", - "; }>]>; }>; }>>; previousStartedAt: ", + "; }>]>; flappingHistory: ", + "ArrayC", + "<", + "BooleanC", + ">; flapping: ", + "BooleanC", + "; }>; }>>; alertRecoveredInstances: ", + "RecordC", + "<", + "StringC", + ", ", + "PartialC", + "<{ state: ", + "RecordC", + "<", + "StringC", + ", ", + "UnknownC", + ">; meta: ", + "PartialC", + "<{ lastScheduledActions: ", + "IntersectionC", + "<[", + "PartialC", + "<{ subgroup: ", + "StringC", + "; }>, ", + "TypeC", + "<{ group: ", + "StringC", + "; date: ", + "Type", + "; }>]>; flappingHistory: ", + "ArrayC", + "<", + "BooleanC", + ">; flapping: ", + "BooleanC", + "; }>; }>>; previousStartedAt: ", "UnionC", "<[", "NullC", diff --git a/api_docs/alerting.mdx b/api_docs/alerting.mdx index bd8f048f8a408..cf05c3d4a8c3d 100644 --- a/api_docs/alerting.mdx +++ b/api_docs/alerting.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/alerting title: "alerting" image: https://source.unsplash.com/400x175/?github description: API docs for the alerting plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'alerting'] --- import alertingObj from './alerting.devdocs.json'; diff --git a/api_docs/apm.devdocs.json b/api_docs/apm.devdocs.json index daf3593733b1b..7c7df2c2ef1e9 100644 --- a/api_docs/apm.devdocs.json +++ b/api_docs/apm.devdocs.json @@ -3123,7 +3123,15 @@ "section": "def-common.ServerRoute", "text": "ServerRoute" }, - "<\"GET /api/apm/sourcemaps\", undefined, ", + "<\"GET /api/apm/sourcemaps\", ", + "PartialC", + "<{ query: ", + "PartialC", + "<{ page: ", + "Type", + "; perPage: ", + "Type", + "; }>; }>, ", { "pluginId": "apm", "scope": "server", @@ -3133,7 +3141,7 @@ }, ", { artifacts: ", "ArtifactSourceMap", - "[]; } | undefined, ", + "[]; total: number; } | undefined, ", "APMRouteCreateOptions", ">; \"DELETE /internal/apm/settings/custom_links/{id}\": ", { diff --git a/api_docs/apm.mdx b/api_docs/apm.mdx index 6a43c1143adb4..fb33ac4a26637 100644 --- a/api_docs/apm.mdx +++ b/api_docs/apm.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/apm title: "apm" image: https://source.unsplash.com/400x175/?github description: API docs for the apm plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'apm'] --- import apmObj from './apm.devdocs.json'; diff --git a/api_docs/banners.mdx b/api_docs/banners.mdx index 946e5ae7c5928..831f5e5d75dfa 100644 --- a/api_docs/banners.mdx +++ b/api_docs/banners.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/banners title: "banners" image: https://source.unsplash.com/400x175/?github description: API docs for the banners plugin -date: 2022-11-29 +date: 2022-12-06 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 043b576f22483..5f14e199c7773 100644 --- a/api_docs/bfetch.mdx +++ b/api_docs/bfetch.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/bfetch title: "bfetch" image: https://source.unsplash.com/400x175/?github description: API docs for the bfetch plugin -date: 2022-11-29 +date: 2022-12-06 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 2686ecbdb5fbe..b4a93382f17aa 100644 --- a/api_docs/canvas.mdx +++ b/api_docs/canvas.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/canvas title: "canvas" image: https://source.unsplash.com/400x175/?github description: API docs for the canvas plugin -date: 2022-11-29 +date: 2022-12-06 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 f939a6becb496..e6ae7fa670928 100644 --- a/api_docs/cases.mdx +++ b/api_docs/cases.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cases title: "cases" image: https://source.unsplash.com/400x175/?github description: API docs for the cases plugin -date: 2022-11-29 +date: 2022-12-06 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 275a82f5e9d90..7748405cb8dd2 100644 --- a/api_docs/charts.mdx +++ b/api_docs/charts.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/charts title: "charts" image: https://source.unsplash.com/400x175/?github description: API docs for the charts plugin -date: 2022-11-29 +date: 2022-12-06 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 d717c5e1725af..6d1072645643c 100644 --- a/api_docs/cloud.mdx +++ b/api_docs/cloud.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloud title: "cloud" image: https://source.unsplash.com/400x175/?github description: API docs for the cloud plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloud'] --- import cloudObj from './cloud.devdocs.json'; diff --git a/api_docs/cloud_chat.mdx b/api_docs/cloud_chat.mdx index ef20eabe57160..38f299744c356 100644 --- a/api_docs/cloud_chat.mdx +++ b/api_docs/cloud_chat.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudChat title: "cloudChat" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudChat plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudChat'] --- import cloudChatObj from './cloud_chat.devdocs.json'; diff --git a/api_docs/cloud_experiments.mdx b/api_docs/cloud_experiments.mdx index d402d63ee2945..21ad542bcd77a 100644 --- a/api_docs/cloud_experiments.mdx +++ b/api_docs/cloud_experiments.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudExperiments title: "cloudExperiments" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudExperiments plugin -date: 2022-11-29 +date: 2022-12-06 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 0f94942318b9b..9781902a75b67 100644 --- a/api_docs/cloud_security_posture.mdx +++ b/api_docs/cloud_security_posture.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudSecurityPosture title: "cloudSecurityPosture" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudSecurityPosture plugin -date: 2022-11-29 +date: 2022-12-06 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 816d764a2a3e6..196a3ebf739a0 100644 --- a/api_docs/console.mdx +++ b/api_docs/console.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/console title: "console" image: https://source.unsplash.com/400x175/?github description: API docs for the console plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'console'] --- import consoleObj from './console.devdocs.json'; diff --git a/api_docs/controls.devdocs.json b/api_docs/controls.devdocs.json index 80a4e40f20e0d..5d59117226bfb 100644 --- a/api_docs/controls.devdocs.json +++ b/api_docs/controls.devdocs.json @@ -3224,7 +3224,7 @@ "section": "def-public.ControlGroupRendererProps", "text": "ControlGroupRendererProps" }, - "> & { readonly _result: ({ onEmbeddableLoad, getCreationOptions, }: ", + "> & { readonly _result: ({ onLoadComplete, getInitialInput, }: ", { "pluginId": "controls", "scope": "public", @@ -3369,6 +3369,105 @@ } ], "interfaces": [ + { + "parentPluginId": "controls", + "id": "def-public.AddDataControlProps", + "type": "Interface", + "tags": [], + "label": "AddDataControlProps", + "description": [], + "path": "src/plugins/controls/public/control_group/control_group_input_builder.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "controls", + "id": "def-public.AddDataControlProps.controlId", + "type": "string", + "tags": [], + "label": "controlId", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "src/plugins/controls/public/control_group/control_group_input_builder.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "controls", + "id": "def-public.AddDataControlProps.dataViewId", + "type": "string", + "tags": [], + "label": "dataViewId", + "description": [], + "path": "src/plugins/controls/public/control_group/control_group_input_builder.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "controls", + "id": "def-public.AddDataControlProps.fieldName", + "type": "string", + "tags": [], + "label": "fieldName", + "description": [], + "path": "src/plugins/controls/public/control_group/control_group_input_builder.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "controls", + "id": "def-public.AddDataControlProps.grow", + "type": "CompoundType", + "tags": [], + "label": "grow", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "src/plugins/controls/public/control_group/control_group_input_builder.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "controls", + "id": "def-public.AddDataControlProps.title", + "type": "string", + "tags": [], + "label": "title", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "src/plugins/controls/public/control_group/control_group_input_builder.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "controls", + "id": "def-public.AddDataControlProps.width", + "type": "CompoundType", + "tags": [], + "label": "width", + "description": [], + "signature": [ + { + "pluginId": "controls", + "scope": "common", + "docId": "kibControlsPluginApi", + "section": "def-common.ControlWidth", + "text": "ControlWidth" + }, + " | undefined" + ], + "path": "src/plugins/controls/public/control_group/control_group_input_builder.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, { "parentPluginId": "controls", "id": "def-public.CalloutProps", @@ -3672,13 +3771,13 @@ "children": [ { "parentPluginId": "controls", - "id": "def-public.ControlGroupRendererProps.onEmbeddableLoad", + "id": "def-public.ControlGroupRendererProps.onLoadComplete", "type": "Function", "tags": [], - "label": "onEmbeddableLoad", + "label": "onLoadComplete", "description": [], "signature": [ - "(controlGroupContainer: ", + "((controlGroup: ", { "pluginId": "controls", "scope": "public", @@ -3686,7 +3785,7 @@ "section": "def-public.ControlGroupContainer", "text": "ControlGroupContainer" }, - ") => void" + ") => void) | undefined" ], "path": "src/plugins/controls/public/control_group/control_group_renderer.tsx", "deprecated": false, @@ -3694,10 +3793,10 @@ "children": [ { "parentPluginId": "controls", - "id": "def-public.ControlGroupRendererProps.onEmbeddableLoad.$1", + "id": "def-public.ControlGroupRendererProps.onLoadComplete.$1", "type": "Object", "tags": [], - "label": "controlGroupContainer", + "label": "controlGroup", "description": [], "signature": [ { @@ -3718,13 +3817,13 @@ }, { "parentPluginId": "controls", - "id": "def-public.ControlGroupRendererProps.getCreationOptions", + "id": "def-public.ControlGroupRendererProps.getInitialInput", "type": "Function", "tags": [], - "label": "getCreationOptions", + "label": "getInitialInput", "description": [], "signature": [ - "(builder: { addDataControlFromField: (initialInput: Partial<", + "(initialInput: Partial<", { "pluginId": "controls", "scope": "common", @@ -3732,17 +3831,57 @@ "section": "def-common.ControlGroupInput", "text": "ControlGroupInput" }, - ">, newPanelInput: { title?: string | undefined; panelId?: string | undefined; fieldName: string; dataViewId: string; } & Partial<", + ">, builder: { addDataControlFromField: (initialInput: Partial<", { "pluginId": "controls", "scope": "common", "docId": "kibControlsPluginApi", - "section": "def-common.ControlPanelState", - "text": "ControlPanelState" + "section": "def-common.ControlGroupInput", + "text": "ControlGroupInput" }, - "<", - "ControlInput", - ">>) => Promise; }) => Promise, controlProps: ", + { + "pluginId": "controls", + "scope": "public", + "docId": "kibControlsPluginApi", + "section": "def-public.AddDataControlProps", + "text": "AddDataControlProps" + }, + ") => Promise; addOptionsListControl: (initialInput: Partial<", + { + "pluginId": "controls", + "scope": "common", + "docId": "kibControlsPluginApi", + "section": "def-common.ControlGroupInput", + "text": "ControlGroupInput" + }, + ">, controlProps: ", + { + "pluginId": "controls", + "scope": "public", + "docId": "kibControlsPluginApi", + "section": "def-public.AddOptionsListControlProps", + "text": "AddOptionsListControlProps" + }, + ") => void; addRangeSliderControl: (initialInput: Partial<", + { + "pluginId": "controls", + "scope": "common", + "docId": "kibControlsPluginApi", + "section": "def-common.ControlGroupInput", + "text": "ControlGroupInput" + }, + ">, controlProps: ", + "AddRangeSliderControlProps", + ") => void; addTimeSliderControl: (initialInput: Partial<", + { + "pluginId": "controls", + "scope": "common", + "docId": "kibControlsPluginApi", + "section": "def-common.ControlGroupInput", + "text": "ControlGroupInput" + }, + ">) => void; }) => Promise" + ], + "path": "src/plugins/controls/public/control_group/control_group_renderer.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "controls", + "id": "def-public.ControlGroupRendererProps.getInitialInput.$2", "type": "Object", "tags": [], "label": "builder", @@ -3772,17 +3934,49 @@ "section": "def-common.ControlGroupInput", "text": "ControlGroupInput" }, - ">, newPanelInput: { title?: string | undefined; panelId?: string | undefined; fieldName: string; dataViewId: string; } & Partial<", + ">, controlProps: ", + { + "pluginId": "controls", + "scope": "public", + "docId": "kibControlsPluginApi", + "section": "def-public.AddDataControlProps", + "text": "AddDataControlProps" + }, + ") => Promise; addOptionsListControl: (initialInput: Partial<", + { + "pluginId": "controls", + "scope": "common", + "docId": "kibControlsPluginApi", + "section": "def-common.ControlGroupInput", + "text": "ControlGroupInput" + }, + ">, controlProps: ", + { + "pluginId": "controls", + "scope": "public", + "docId": "kibControlsPluginApi", + "section": "def-public.AddOptionsListControlProps", + "text": "AddOptionsListControlProps" + }, + ") => void; addRangeSliderControl: (initialInput: Partial<", { "pluginId": "controls", "scope": "common", "docId": "kibControlsPluginApi", - "section": "def-common.ControlPanelState", - "text": "ControlPanelState" + "section": "def-common.ControlGroupInput", + "text": "ControlGroupInput" }, - "<", - "ControlInput", - ">>) => Promise; }" + ">, controlProps: ", + "AddRangeSliderControlProps", + ") => void; addTimeSliderControl: (initialInput: Partial<", + { + "pluginId": "controls", + "scope": "common", + "docId": "kibControlsPluginApi", + "section": "def-common.ControlGroupInput", + "text": "ControlGroupInput" + }, + ">) => void; }" ], "path": "src/plugins/controls/public/control_group/control_group_renderer.tsx", "deprecated": false, @@ -4244,6 +4438,28 @@ ], "enums": [], "misc": [ + { + "parentPluginId": "controls", + "id": "def-public.AddOptionsListControlProps", + "type": "Type", + "tags": [], + "label": "AddOptionsListControlProps", + "description": [], + "signature": [ + { + "pluginId": "controls", + "scope": "public", + "docId": "kibControlsPluginApi", + "section": "def-public.AddDataControlProps", + "text": "AddDataControlProps" + }, + " & { selectedOptions?: string[] | undefined; }" + ], + "path": "src/plugins/controls/public/control_group/control_group_input_builder.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "controls", "id": "def-public.CONTROL_GROUP_TYPE", @@ -4470,6 +4686,56 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "controls", + "id": "def-public.DataControlInput", + "type": "Type", + "tags": [], + "label": "DataControlInput", + "description": [], + "signature": [ + { + "pluginId": "embeddable", + "scope": "common", + "docId": "kibEmbeddablePluginApi", + "section": "def-common.EmbeddableInput", + "text": "EmbeddableInput" + }, + " & { query?: ", + { + "pluginId": "@kbn/es-query", + "scope": "common", + "docId": "kibKbnEsQueryPluginApi", + "section": "def-common.Query", + "text": "Query" + }, + " | undefined; filters?: ", + { + "pluginId": "@kbn/es-query", + "scope": "common", + "docId": "kibKbnEsQueryPluginApi", + "section": "def-common.Filter", + "text": "Filter" + }, + "[] | undefined; timeRange?: ", + { + "pluginId": "@kbn/es-query", + "scope": "common", + "docId": "kibKbnEsQueryPluginApi", + "section": "def-common.TimeRange", + "text": "TimeRange" + }, + " | undefined; timeslice?: [number, number] | undefined; controlStyle?: ", + "ControlStyle", + " | undefined; ignoreParentSettings?: ", + "ParentIgnoreSettings", + " | undefined; } & { fieldName: string; parentFieldName?: string | undefined; childFieldName?: string | undefined; dataViewId: string; }" + ], + "path": "src/plugins/controls/common/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "controls", "id": "def-public.OPTIONS_LIST_CONTROL", @@ -4516,7 +4782,289 @@ "initialIsOpen": false } ], - "objects": [] + "objects": [ + { + "parentPluginId": "controls", + "id": "def-public.controlGroupInputBuilder", + "type": "Object", + "tags": [], + "label": "controlGroupInputBuilder", + "description": [], + "path": "src/plugins/controls/public/control_group/control_group_input_builder.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "controls", + "id": "def-public.controlGroupInputBuilder.addDataControlFromField", + "type": "Function", + "tags": [], + "label": "addDataControlFromField", + "description": [], + "signature": [ + "(initialInput: Partial<", + { + "pluginId": "controls", + "scope": "common", + "docId": "kibControlsPluginApi", + "section": "def-common.ControlGroupInput", + "text": "ControlGroupInput" + }, + ">, controlProps: ", + { + "pluginId": "controls", + "scope": "public", + "docId": "kibControlsPluginApi", + "section": "def-public.AddDataControlProps", + "text": "AddDataControlProps" + }, + ") => Promise" + ], + "path": "src/plugins/controls/public/control_group/control_group_input_builder.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "controls", + "id": "def-public.controlGroupInputBuilder.addDataControlFromField.$1", + "type": "Object", + "tags": [], + "label": "initialInput", + "description": [], + "signature": [ + "Partial<", + { + "pluginId": "controls", + "scope": "common", + "docId": "kibControlsPluginApi", + "section": "def-common.ControlGroupInput", + "text": "ControlGroupInput" + }, + ">" + ], + "path": "src/plugins/controls/public/control_group/control_group_input_builder.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "controls", + "id": "def-public.controlGroupInputBuilder.addDataControlFromField.$2", + "type": "Object", + "tags": [], + "label": "controlProps", + "description": [], + "signature": [ + { + "pluginId": "controls", + "scope": "public", + "docId": "kibControlsPluginApi", + "section": "def-public.AddDataControlProps", + "text": "AddDataControlProps" + } + ], + "path": "src/plugins/controls/public/control_group/control_group_input_builder.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "controls", + "id": "def-public.controlGroupInputBuilder.addOptionsListControl", + "type": "Function", + "tags": [], + "label": "addOptionsListControl", + "description": [], + "signature": [ + "(initialInput: Partial<", + { + "pluginId": "controls", + "scope": "common", + "docId": "kibControlsPluginApi", + "section": "def-common.ControlGroupInput", + "text": "ControlGroupInput" + }, + ">, controlProps: ", + { + "pluginId": "controls", + "scope": "public", + "docId": "kibControlsPluginApi", + "section": "def-public.AddOptionsListControlProps", + "text": "AddOptionsListControlProps" + }, + ") => void" + ], + "path": "src/plugins/controls/public/control_group/control_group_input_builder.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "controls", + "id": "def-public.controlGroupInputBuilder.addOptionsListControl.$1", + "type": "Object", + "tags": [], + "label": "initialInput", + "description": [], + "signature": [ + "Partial<", + { + "pluginId": "controls", + "scope": "common", + "docId": "kibControlsPluginApi", + "section": "def-common.ControlGroupInput", + "text": "ControlGroupInput" + }, + ">" + ], + "path": "src/plugins/controls/public/control_group/control_group_input_builder.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "controls", + "id": "def-public.controlGroupInputBuilder.addOptionsListControl.$2", + "type": "CompoundType", + "tags": [], + "label": "controlProps", + "description": [], + "signature": [ + { + "pluginId": "controls", + "scope": "public", + "docId": "kibControlsPluginApi", + "section": "def-public.AddOptionsListControlProps", + "text": "AddOptionsListControlProps" + } + ], + "path": "src/plugins/controls/public/control_group/control_group_input_builder.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "controls", + "id": "def-public.controlGroupInputBuilder.addRangeSliderControl", + "type": "Function", + "tags": [], + "label": "addRangeSliderControl", + "description": [], + "signature": [ + "(initialInput: Partial<", + { + "pluginId": "controls", + "scope": "common", + "docId": "kibControlsPluginApi", + "section": "def-common.ControlGroupInput", + "text": "ControlGroupInput" + }, + ">, controlProps: ", + "AddRangeSliderControlProps", + ") => void" + ], + "path": "src/plugins/controls/public/control_group/control_group_input_builder.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "controls", + "id": "def-public.controlGroupInputBuilder.addRangeSliderControl.$1", + "type": "Object", + "tags": [], + "label": "initialInput", + "description": [], + "signature": [ + "Partial<", + { + "pluginId": "controls", + "scope": "common", + "docId": "kibControlsPluginApi", + "section": "def-common.ControlGroupInput", + "text": "ControlGroupInput" + }, + ">" + ], + "path": "src/plugins/controls/public/control_group/control_group_input_builder.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "controls", + "id": "def-public.controlGroupInputBuilder.addRangeSliderControl.$2", + "type": "CompoundType", + "tags": [], + "label": "controlProps", + "description": [], + "signature": [ + "AddRangeSliderControlProps" + ], + "path": "src/plugins/controls/public/control_group/control_group_input_builder.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "controls", + "id": "def-public.controlGroupInputBuilder.addTimeSliderControl", + "type": "Function", + "tags": [], + "label": "addTimeSliderControl", + "description": [], + "signature": [ + "(initialInput: Partial<", + { + "pluginId": "controls", + "scope": "common", + "docId": "kibControlsPluginApi", + "section": "def-common.ControlGroupInput", + "text": "ControlGroupInput" + }, + ">) => void" + ], + "path": "src/plugins/controls/public/control_group/control_group_input_builder.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "controls", + "id": "def-public.controlGroupInputBuilder.addTimeSliderControl.$1", + "type": "Object", + "tags": [], + "label": "initialInput", + "description": [], + "signature": [ + "Partial<", + { + "pluginId": "controls", + "scope": "common", + "docId": "kibControlsPluginApi", + "section": "def-common.ControlGroupInput", + "text": "ControlGroupInput" + }, + ">" + ], + "path": "src/plugins/controls/public/control_group/control_group_input_builder.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + } + ], + "initialIsOpen": false + } + ] }, "server": { "classes": [], diff --git a/api_docs/controls.mdx b/api_docs/controls.mdx index 51f6726478302..fa1bcf776d4d6 100644 --- a/api_docs/controls.mdx +++ b/api_docs/controls.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/controls title: "controls" image: https://source.unsplash.com/400x175/?github description: API docs for the controls plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'controls'] --- import controlsObj from './controls.devdocs.json'; @@ -21,10 +21,13 @@ Contact [Kibana Presentation](https://github.com/orgs/elastic/teams/kibana-prese | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 245 | 0 | 236 | 9 | +| 267 | 0 | 258 | 10 | ## Client +### Objects + + ### Functions diff --git a/api_docs/core.devdocs.json b/api_docs/core.devdocs.json index 6f0a2860610a5..a8e106fcb7b8b 100644 --- a/api_docs/core.devdocs.json +++ b/api_docs/core.devdocs.json @@ -17724,7 +17724,7 @@ "section": "def-common.AppStatus", "text": "AppStatus" }, - " | undefined; searchable?: boolean | undefined; deepLinks?: ", + " | undefined; tooltip?: string | undefined; searchable?: boolean | undefined; deepLinks?: ", { "pluginId": "@kbn/core-application-browser", "scope": "common", @@ -17740,7 +17740,7 @@ "section": "def-common.AppNavLinkStatus", "text": "AppNavLinkStatus" }, - " | undefined; defaultPath?: string | undefined; tooltip?: string | undefined; }" + " | undefined; defaultPath?: string | undefined; }" ], "path": "packages/core/application/core-application-browser/src/application.ts", "deprecated": false, diff --git a/api_docs/core.mdx b/api_docs/core.mdx index ea23977c90339..2c82717588c5d 100644 --- a/api_docs/core.mdx +++ b/api_docs/core.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/core title: "core" image: https://source.unsplash.com/400x175/?github description: API docs for the core plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'core'] --- import coreObj from './core.devdocs.json'; diff --git a/api_docs/custom_integrations.mdx b/api_docs/custom_integrations.mdx index c445593ea8e88..cd6737258ea79 100644 --- a/api_docs/custom_integrations.mdx +++ b/api_docs/custom_integrations.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/customIntegrations title: "customIntegrations" image: https://source.unsplash.com/400x175/?github description: API docs for the customIntegrations plugin -date: 2022-11-29 +date: 2022-12-06 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 f3e35ecfaf947..545c36050f22c 100644 --- a/api_docs/dashboard.mdx +++ b/api_docs/dashboard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dashboard title: "dashboard" image: https://source.unsplash.com/400x175/?github description: API docs for the dashboard plugin -date: 2022-11-29 +date: 2022-12-06 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 d219538b64e16..9168f7f6429fd 100644 --- a/api_docs/dashboard_enhanced.mdx +++ b/api_docs/dashboard_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dashboardEnhanced title: "dashboardEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the dashboardEnhanced plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dashboardEnhanced'] --- import dashboardEnhancedObj from './dashboard_enhanced.devdocs.json'; diff --git a/api_docs/data.devdocs.json b/api_docs/data.devdocs.json index 80a12e8e9bafe..49b2390727a5a 100644 --- a/api_docs/data.devdocs.json +++ b/api_docs/data.devdocs.json @@ -12345,10 +12345,6 @@ "plugin": "graph", "path": "x-pack/plugins/graph/public/plugin.ts" }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts" - }, { "plugin": "stackAlerts", "path": "x-pack/plugins/stack_alerts/public/rule_types/geo_containment/query_builder/expressions/boundary_index_expression.tsx" @@ -12927,11 +12923,11 @@ }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/utils.ts" + "path": "x-pack/plugins/security_solution/public/detections/containers/detection_engine/exceptions/get_es_query_filter.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/detections/containers/detection_engine/exceptions/get_es_query_filter.ts" + "path": "x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/utils.ts" }, { "plugin": "securitySolution", @@ -13129,6 +13125,14 @@ "plugin": "savedObjectsManagement", "path": "src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx" }, + { + "plugin": "controls", + "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" + }, + { + "plugin": "controls", + "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" + }, { "plugin": "unifiedFieldList", "path": "src/plugins/unified_field_list/public/services/field_stats/load_field_stats.ts" @@ -13153,14 +13157,6 @@ "plugin": "unifiedFieldList", "path": "src/plugins/unified_field_list/public/hooks/use_existing_fields.ts" }, - { - "plugin": "controls", - "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" - }, - { - "plugin": "controls", - "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" - }, { "plugin": "lens", "path": "x-pack/plugins/lens/public/data_views_service/loader.ts" @@ -13489,6 +13485,10 @@ "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/server/lib/sourcerer/routes/index.ts" }, + { + "plugin": "timelines", + "path": "x-pack/plugins/timelines/server/search_strategy/index_fields/index.ts" + }, { "plugin": "stackAlerts", "path": "x-pack/plugins/stack_alerts/public/rule_types/geo_containment/query_builder/expressions/boundary_index_expression.tsx" @@ -13533,10 +13533,6 @@ "plugin": "synthetics", "path": "x-pack/plugins/synthetics/public/legacy_uptime/components/overview/alerts/monitor_expressions/filters_expression_select.tsx" }, - { - "plugin": "timelines", - "path": "x-pack/plugins/timelines/server/search_strategy/index_fields/index.ts" - }, { "plugin": "transform", "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_details/step_details_form.tsx" @@ -20629,11 +20625,11 @@ }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/utils.ts" + "path": "x-pack/plugins/security_solution/public/detections/containers/detection_engine/exceptions/get_es_query_filter.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/detections/containers/detection_engine/exceptions/get_es_query_filter.ts" + "path": "x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/utils.ts" }, { "plugin": "securitySolution", @@ -20831,6 +20827,14 @@ "plugin": "savedObjectsManagement", "path": "src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx" }, + { + "plugin": "controls", + "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" + }, + { + "plugin": "controls", + "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" + }, { "plugin": "unifiedFieldList", "path": "src/plugins/unified_field_list/public/services/field_stats/load_field_stats.ts" @@ -20855,14 +20859,6 @@ "plugin": "unifiedFieldList", "path": "src/plugins/unified_field_list/public/hooks/use_existing_fields.ts" }, - { - "plugin": "controls", - "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" - }, - { - "plugin": "controls", - "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" - }, { "plugin": "lens", "path": "x-pack/plugins/lens/public/data_views_service/loader.ts" @@ -21191,6 +21187,10 @@ "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/server/lib/sourcerer/routes/index.ts" }, + { + "plugin": "timelines", + "path": "x-pack/plugins/timelines/server/search_strategy/index_fields/index.ts" + }, { "plugin": "stackAlerts", "path": "x-pack/plugins/stack_alerts/public/rule_types/geo_containment/query_builder/expressions/boundary_index_expression.tsx" @@ -21235,10 +21235,6 @@ "plugin": "synthetics", "path": "x-pack/plugins/synthetics/public/legacy_uptime/components/overview/alerts/monitor_expressions/filters_expression_select.tsx" }, - { - "plugin": "timelines", - "path": "x-pack/plugins/timelines/server/search_strategy/index_fields/index.ts" - }, { "plugin": "transform", "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_details/step_details_form.tsx" diff --git a/api_docs/data.mdx b/api_docs/data.mdx index 589209b5b7a87..d198d95574253 100644 --- a/api_docs/data.mdx +++ b/api_docs/data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/data title: "data" image: https://source.unsplash.com/400x175/?github description: API docs for the data plugin -date: 2022-11-29 +date: 2022-12-06 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 ee15def10af1c..fc0ac649b12de 100644 --- a/api_docs/data_query.mdx +++ b/api_docs/data_query.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/data-query title: "data.query" image: https://source.unsplash.com/400x175/?github description: API docs for the data.query plugin -date: 2022-11-29 +date: 2022-12-06 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 428135f8d5847..15b32b4c7d379 100644 --- a/api_docs/data_search.mdx +++ b/api_docs/data_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/data-search title: "data.search" image: https://source.unsplash.com/400x175/?github description: API docs for the data.search plugin -date: 2022-11-29 +date: 2022-12-06 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 968189de2ddb9..08c21e497f700 100644 --- a/api_docs/data_view_editor.mdx +++ b/api_docs/data_view_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViewEditor title: "dataViewEditor" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViewEditor plugin -date: 2022-11-29 +date: 2022-12-06 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 ba4e656235994..1b388650a7386 100644 --- a/api_docs/data_view_field_editor.mdx +++ b/api_docs/data_view_field_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViewFieldEditor title: "dataViewFieldEditor" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViewFieldEditor plugin -date: 2022-11-29 +date: 2022-12-06 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 22a840e79a570..4328a1d062a1d 100644 --- a/api_docs/data_view_management.mdx +++ b/api_docs/data_view_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViewManagement title: "dataViewManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViewManagement plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewManagement'] --- import dataViewManagementObj from './data_view_management.devdocs.json'; diff --git a/api_docs/data_views.devdocs.json b/api_docs/data_views.devdocs.json index e846a2cd0e773..eccf7c5366fa6 100644 --- a/api_docs/data_views.devdocs.json +++ b/api_docs/data_views.devdocs.json @@ -77,11 +77,11 @@ }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/utils.ts" + "path": "x-pack/plugins/security_solution/public/detections/containers/detection_engine/exceptions/get_es_query_filter.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/detections/containers/detection_engine/exceptions/get_es_query_filter.ts" + "path": "x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/utils.ts" }, { "plugin": "securitySolution", @@ -287,6 +287,14 @@ "plugin": "savedObjectsManagement", "path": "src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx" }, + { + "plugin": "controls", + "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" + }, + { + "plugin": "controls", + "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" + }, { "plugin": "unifiedFieldList", "path": "src/plugins/unified_field_list/public/services/field_stats/load_field_stats.ts" @@ -311,14 +319,6 @@ "plugin": "unifiedFieldList", "path": "src/plugins/unified_field_list/public/hooks/use_existing_fields.ts" }, - { - "plugin": "controls", - "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" - }, - { - "plugin": "controls", - "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" - }, { "plugin": "lens", "path": "x-pack/plugins/lens/public/data_views_service/loader.ts" @@ -647,6 +647,10 @@ "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/server/lib/sourcerer/routes/index.ts" }, + { + "plugin": "timelines", + "path": "x-pack/plugins/timelines/server/search_strategy/index_fields/index.ts" + }, { "plugin": "stackAlerts", "path": "x-pack/plugins/stack_alerts/public/rule_types/geo_containment/query_builder/expressions/boundary_index_expression.tsx" @@ -691,10 +695,6 @@ "plugin": "synthetics", "path": "x-pack/plugins/synthetics/public/legacy_uptime/components/overview/alerts/monitor_expressions/filters_expression_select.tsx" }, - { - "plugin": "timelines", - "path": "x-pack/plugins/timelines/server/search_strategy/index_fields/index.ts" - }, { "plugin": "transform", "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_details/step_details_form.tsx" @@ -8378,11 +8378,11 @@ }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/utils.ts" + "path": "x-pack/plugins/security_solution/public/detections/containers/detection_engine/exceptions/get_es_query_filter.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/detections/containers/detection_engine/exceptions/get_es_query_filter.ts" + "path": "x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/utils.ts" }, { "plugin": "securitySolution", @@ -8588,6 +8588,14 @@ "plugin": "savedObjectsManagement", "path": "src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx" }, + { + "plugin": "controls", + "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" + }, + { + "plugin": "controls", + "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" + }, { "plugin": "unifiedFieldList", "path": "src/plugins/unified_field_list/public/services/field_stats/load_field_stats.ts" @@ -8612,14 +8620,6 @@ "plugin": "unifiedFieldList", "path": "src/plugins/unified_field_list/public/hooks/use_existing_fields.ts" }, - { - "plugin": "controls", - "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" - }, - { - "plugin": "controls", - "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" - }, { "plugin": "lens", "path": "x-pack/plugins/lens/public/data_views_service/loader.ts" @@ -8948,6 +8948,10 @@ "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/server/lib/sourcerer/routes/index.ts" }, + { + "plugin": "timelines", + "path": "x-pack/plugins/timelines/server/search_strategy/index_fields/index.ts" + }, { "plugin": "stackAlerts", "path": "x-pack/plugins/stack_alerts/public/rule_types/geo_containment/query_builder/expressions/boundary_index_expression.tsx" @@ -8992,10 +8996,6 @@ "plugin": "synthetics", "path": "x-pack/plugins/synthetics/public/legacy_uptime/components/overview/alerts/monitor_expressions/filters_expression_select.tsx" }, - { - "plugin": "timelines", - "path": "x-pack/plugins/timelines/server/search_strategy/index_fields/index.ts" - }, { "plugin": "transform", "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_details/step_details_form.tsx" @@ -15760,11 +15760,11 @@ }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/utils.ts" + "path": "x-pack/plugins/security_solution/public/detections/containers/detection_engine/exceptions/get_es_query_filter.ts" }, { "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/detections/containers/detection_engine/exceptions/get_es_query_filter.ts" + "path": "x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/utils.ts" }, { "plugin": "securitySolution", @@ -15970,6 +15970,14 @@ "plugin": "savedObjectsManagement", "path": "src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx" }, + { + "plugin": "controls", + "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" + }, + { + "plugin": "controls", + "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" + }, { "plugin": "unifiedFieldList", "path": "src/plugins/unified_field_list/public/services/field_stats/load_field_stats.ts" @@ -15994,14 +16002,6 @@ "plugin": "unifiedFieldList", "path": "src/plugins/unified_field_list/public/hooks/use_existing_fields.ts" }, - { - "plugin": "controls", - "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" - }, - { - "plugin": "controls", - "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" - }, { "plugin": "lens", "path": "x-pack/plugins/lens/public/data_views_service/loader.ts" @@ -16330,6 +16330,10 @@ "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/server/lib/sourcerer/routes/index.ts" }, + { + "plugin": "timelines", + "path": "x-pack/plugins/timelines/server/search_strategy/index_fields/index.ts" + }, { "plugin": "stackAlerts", "path": "x-pack/plugins/stack_alerts/public/rule_types/geo_containment/query_builder/expressions/boundary_index_expression.tsx" @@ -16374,10 +16378,6 @@ "plugin": "synthetics", "path": "x-pack/plugins/synthetics/public/legacy_uptime/components/overview/alerts/monitor_expressions/filters_expression_select.tsx" }, - { - "plugin": "timelines", - "path": "x-pack/plugins/timelines/server/search_strategy/index_fields/index.ts" - }, { "plugin": "transform", "path": "x-pack/plugins/transform/public/app/sections/create_transform/components/step_details/step_details_form.tsx" diff --git a/api_docs/data_views.mdx b/api_docs/data_views.mdx index b023ceb250f89..e399aabd710a7 100644 --- a/api_docs/data_views.mdx +++ b/api_docs/data_views.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViews title: "dataViews" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViews plugin -date: 2022-11-29 +date: 2022-12-06 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 dfd9fd7b7d4c1..afb22249768d9 100644 --- a/api_docs/data_visualizer.mdx +++ b/api_docs/data_visualizer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataVisualizer title: "dataVisualizer" image: https://source.unsplash.com/400x175/?github description: API docs for the dataVisualizer plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataVisualizer'] --- import dataVisualizerObj from './data_visualizer.devdocs.json'; diff --git a/api_docs/deprecations_by_api.mdx b/api_docs/deprecations_by_api.mdx index 8e7b0b557758e..1f8ba6e1aa122 100644 --- a/api_docs/deprecations_by_api.mdx +++ b/api_docs/deprecations_by_api.mdx @@ -7,7 +7,7 @@ id: kibDevDocsDeprecationsByApi slug: /kibana-dev-docs/api-meta/deprecated-api-list-by-api title: Deprecated API usage by API description: A list of deprecated APIs, which plugins are still referencing them, and when they need to be removed by. -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -28,15 +28,15 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | @kbn/core-saved-objects-common, savedObjects, embeddable, visualizations, dashboard, fleet, infra, canvas, graph, actions, alerting, enterpriseSearch, securitySolution, taskManager, savedSearch, ml, @kbn/core-saved-objects-server-internal | - | | | core, savedObjects, embeddable, visualizations, dashboard, fleet, infra, canvas, graph, actions, alerting, enterpriseSearch, securitySolution, taskManager, savedSearch, ml, @kbn/core-saved-objects-server-internal | - | | | discover, maps, monitoring | - | -| | @kbn/es-query, securitySolution, timelines, lists, threatIntelligence, dataViews, unifiedSearch, triggersActionsUi, savedObjectsManagement, unifiedFieldList, controls, lens, aiops, ml, infra, visTypeTimeseries, apm, observability, dataVisualizer, fleet, canvas, graph, stackAlerts, synthetics, transform, upgradeAssistant, ux, maps, dataViewManagement, inputControlVis, visDefaultEditor, presentationUtil, visTypeTimelion, visTypeVega, discover, data | - | +| | @kbn/es-query, securitySolution, timelines, lists, threatIntelligence, dataViews, unifiedSearch, triggersActionsUi, savedObjectsManagement, controls, unifiedFieldList, lens, aiops, ml, infra, visTypeTimeseries, apm, observability, dataVisualizer, fleet, canvas, graph, stackAlerts, synthetics, transform, upgradeAssistant, ux, maps, dataViewManagement, inputControlVis, visDefaultEditor, presentationUtil, visTypeTimelion, visTypeVega, discover, data | - | | | discover | - | -| | @kbn/es-query, securitySolution, timelines, lists, threatIntelligence, dataViews, unifiedSearch, triggersActionsUi, savedObjectsManagement, unifiedFieldList, controls, lens, aiops, ml, infra, visTypeTimeseries, apm, observability, dataVisualizer, fleet, canvas, graph, stackAlerts, synthetics, transform, upgradeAssistant, ux, maps, dataViewManagement, inputControlVis, visDefaultEditor, presentationUtil, visTypeTimelion, visTypeVega, discover, data | - | -| | @kbn/es-query, securitySolution, timelines, lists, threatIntelligence, data, unifiedSearch, triggersActionsUi, savedObjectsManagement, unifiedFieldList, controls, lens, aiops, ml, infra, visTypeTimeseries, apm, observability, dataVisualizer, fleet, canvas, graph, stackAlerts, synthetics, transform, upgradeAssistant, ux, maps, dataViewManagement, inputControlVis, visDefaultEditor, presentationUtil, visTypeTimelion, visTypeVega, discover | - | +| | @kbn/es-query, securitySolution, timelines, lists, threatIntelligence, dataViews, unifiedSearch, triggersActionsUi, savedObjectsManagement, controls, unifiedFieldList, lens, aiops, ml, infra, visTypeTimeseries, apm, observability, dataVisualizer, fleet, canvas, graph, stackAlerts, synthetics, transform, upgradeAssistant, ux, maps, dataViewManagement, inputControlVis, visDefaultEditor, presentationUtil, visTypeTimelion, visTypeVega, discover, data | - | +| | @kbn/es-query, securitySolution, timelines, lists, threatIntelligence, data, unifiedSearch, triggersActionsUi, savedObjectsManagement, controls, unifiedFieldList, lens, aiops, ml, infra, visTypeTimeseries, apm, observability, dataVisualizer, fleet, canvas, graph, stackAlerts, synthetics, transform, upgradeAssistant, ux, maps, dataViewManagement, inputControlVis, visDefaultEditor, presentationUtil, visTypeTimelion, visTypeVega, discover | - | | | data, discover, embeddable | - | | | advancedSettings, discover | - | | | advancedSettings, discover | - | | | advancedSettings, discover | - | -| | infra, graph, securitySolution, stackAlerts, inputControlVis, savedObjects | - | +| | infra, graph, stackAlerts, inputControlVis, securitySolution, savedObjects | - | | | securitySolution | - | | | encryptedSavedObjects, actions, data, ml, logstash, securitySolution, cloudChat | - | | | lists, securitySolution, @kbn/securitysolution-io-ts-list-types | - | @@ -88,7 +88,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | @kbn/core-plugins-server-internal | - | | | spaces, security, alerting | 8.8.0 | | | spaces, security, actions, alerting, ml, remoteClusters, graph, indexLifecycleManagement, mapsEms, painlessLab, rollup, searchprofiler, securitySolution, snapshotRestore, transform, upgradeAssistant | 8.8.0 | -| | embeddable, discover, presentationUtil, dashboard, graph | 8.8.0 | +| | embeddable, presentationUtil, dashboard, discover, graph | 8.8.0 | | | apm, security, securitySolution | 8.8.0 | | | apm, security, securitySolution | 8.8.0 | | | @kbn/core-application-browser-internal, @kbn/core-application-browser-mocks, visualizations, dashboard, lens, maps, ml, securitySolution, security | 8.8.0 | diff --git a/api_docs/deprecations_by_plugin.mdx b/api_docs/deprecations_by_plugin.mdx index a6b569ba9ed18..8ca8a5c288905 100644 --- a/api_docs/deprecations_by_plugin.mdx +++ b/api_docs/deprecations_by_plugin.mdx @@ -7,7 +7,7 @@ id: kibDevDocsDeprecationsByPlugin slug: /kibana-dev-docs/api-meta/deprecated-api-list-by-plugin title: Deprecated API usage by plugin description: A list of deprecated APIs, which plugins are still referencing them, and when they need to be removed by. -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -846,13 +846,13 @@ migrates to using the Kibana Privilege model: https://github.com/elastic/kibana/ | ---------------|-----------|-----------| | | [wrap_search_source_client.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_preview/api/preview_rules/wrap_search_source_client.ts#:~:text=create) | - | | | [wrap_search_source_client.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_preview/api/preview_rules/wrap_search_source_client.test.ts#:~:text=fetch), [wrap_search_source_client.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_preview/api/preview_rules/wrap_search_source_client.test.ts#:~:text=fetch), [wrap_search_source_client.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_preview/api/preview_rules/wrap_search_source_client.test.ts#:~:text=fetch), [wrap_search_source_client.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_preview/api/preview_rules/wrap_search_source_client.test.ts#:~:text=fetch) | - | -| | [middleware.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts#:~:text=indexPatterns), [dependencies_start_mock.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/mock/endpoint/dependencies_start_mock.ts#:~:text=indexPatterns) | - | -| | [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/containers/source/index.tsx#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/containers/source/index.tsx#:~:text=title), [utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/utils.ts#:~:text=title), [get_es_query_filter.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/containers/detection_engine/exceptions/get_es_query_filter.ts#:~:text=title), [middleware.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts#:~:text=title), [get_query_filter.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/signals/get_query_filter.ts#:~:text=title), [index_pattern.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/mock/index_pattern.ts#:~:text=title), [utils.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/flyout_components/alerts_actions/utils.test.ts#:~:text=title), [validators.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/components/rules/eql_query_bar/validators.ts#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/components/rules/step_define_rule/index.tsx#:~:text=title)+ 18 more | - | +| | [dependencies_start_mock.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/mock/endpoint/dependencies_start_mock.ts#:~:text=indexPatterns) | - | +| | [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/containers/source/index.tsx#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/containers/source/index.tsx#:~:text=title), [get_es_query_filter.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/containers/detection_engine/exceptions/get_es_query_filter.ts#:~:text=title), [utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/utils.ts#:~:text=title), [middleware.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts#:~:text=title), [get_query_filter.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/signals/get_query_filter.ts#:~:text=title), [index_pattern.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/mock/index_pattern.ts#:~:text=title), [utils.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/flyout_components/alerts_actions/utils.test.ts#:~:text=title), [validators.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/components/rules/eql_query_bar/validators.ts#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/components/rules/step_define_rule/index.tsx#:~:text=title)+ 18 more | - | | | [wrap_search_source_client.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_preview/api/preview_rules/wrap_search_source_client.ts#:~:text=create) | - | | | [wrap_search_source_client.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_preview/api/preview_rules/wrap_search_source_client.test.ts#:~:text=fetch), [wrap_search_source_client.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_preview/api/preview_rules/wrap_search_source_client.test.ts#:~:text=fetch), [wrap_search_source_client.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_preview/api/preview_rules/wrap_search_source_client.test.ts#:~:text=fetch), [wrap_search_source_client.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/rule_preview/api/preview_rules/wrap_search_source_client.test.ts#:~:text=fetch) | - | | | [api.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/hooks/eql/api.ts#:~:text=options) | - | -| | [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/containers/source/index.tsx#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/containers/source/index.tsx#:~:text=title), [utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/utils.ts#:~:text=title), [get_es_query_filter.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/containers/detection_engine/exceptions/get_es_query_filter.ts#:~:text=title), [middleware.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts#:~:text=title), [get_query_filter.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/signals/get_query_filter.ts#:~:text=title), [index_pattern.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/mock/index_pattern.ts#:~:text=title), [utils.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/flyout_components/alerts_actions/utils.test.ts#:~:text=title), [validators.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/components/rules/eql_query_bar/validators.ts#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/components/rules/step_define_rule/index.tsx#:~:text=title)+ 18 more | - | -| | [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/containers/source/index.tsx#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/containers/source/index.tsx#:~:text=title), [utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/utils.ts#:~:text=title), [get_es_query_filter.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/containers/detection_engine/exceptions/get_es_query_filter.ts#:~:text=title), [middleware.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts#:~:text=title), [get_query_filter.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/signals/get_query_filter.ts#:~:text=title), [index_pattern.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/mock/index_pattern.ts#:~:text=title), [utils.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/flyout_components/alerts_actions/utils.test.ts#:~:text=title), [validators.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/components/rules/eql_query_bar/validators.ts#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/components/rules/step_define_rule/index.tsx#:~:text=title)+ 4 more | - | +| | [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/containers/source/index.tsx#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/containers/source/index.tsx#:~:text=title), [get_es_query_filter.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/containers/detection_engine/exceptions/get_es_query_filter.ts#:~:text=title), [utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/utils.ts#:~:text=title), [middleware.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts#:~:text=title), [get_query_filter.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/signals/get_query_filter.ts#:~:text=title), [index_pattern.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/mock/index_pattern.ts#:~:text=title), [utils.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/flyout_components/alerts_actions/utils.test.ts#:~:text=title), [validators.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/components/rules/eql_query_bar/validators.ts#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/components/rules/step_define_rule/index.tsx#:~:text=title)+ 18 more | - | +| | [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/containers/source/index.tsx#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/containers/source/index.tsx#:~:text=title), [get_es_query_filter.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/containers/detection_engine/exceptions/get_es_query_filter.ts#:~:text=title), [utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/utils.ts#:~:text=title), [middleware.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts#:~:text=title), [get_query_filter.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/signals/get_query_filter.ts#:~:text=title), [index_pattern.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/common/mock/index_pattern.ts#:~:text=title), [utils.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/flyout_components/alerts_actions/utils.test.ts#:~:text=title), [validators.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/components/rules/eql_query_bar/validators.ts#:~:text=title), [index.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/public/detections/components/rules/step_define_rule/index.tsx#:~:text=title)+ 4 more | - | | | [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [fleet_integration.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts#:~:text=mode), [fleet_integration.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts#:~:text=mode), [create_default_policy.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_default_policy.test.ts#:~:text=mode), [create_default_policy.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_default_policy.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode)+ 7 more | 8.8.0 | | | [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [policy_config.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [fleet_integration.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts#:~:text=mode), [fleet_integration.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts#:~:text=mode), [create_default_policy.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_default_policy.test.ts#:~:text=mode), [create_default_policy.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_default_policy.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode)+ 7 more | 8.8.0 | | | [query.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/security_solution/server/lib/detection_engine/signals/executors/query.ts#:~:text=license%24) | 8.8.0 | diff --git a/api_docs/deprecations_by_team.mdx b/api_docs/deprecations_by_team.mdx index e4a7b90c05eea..800c6ecd38273 100644 --- a/api_docs/deprecations_by_team.mdx +++ b/api_docs/deprecations_by_team.mdx @@ -7,7 +7,7 @@ id: kibDevDocsDeprecationsDueByTeam slug: /kibana-dev-docs/api-meta/deprecations-due-by-team title: Deprecated APIs due to be removed, by team description: Lists the teams that are referencing deprecated APIs with a remove by date. -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- diff --git a/api_docs/dev_tools.mdx b/api_docs/dev_tools.mdx index f6ec38372735f..6cc8a050865da 100644 --- a/api_docs/dev_tools.mdx +++ b/api_docs/dev_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/devTools title: "devTools" image: https://source.unsplash.com/400x175/?github description: API docs for the devTools plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'devTools'] --- import devToolsObj from './dev_tools.devdocs.json'; diff --git a/api_docs/discover.devdocs.json b/api_docs/discover.devdocs.json index 32ec559942db0..c2dc34959d5b0 100644 --- a/api_docs/discover.devdocs.json +++ b/api_docs/discover.devdocs.json @@ -628,6 +628,22 @@ "path": "src/plugins/discover/public/locator.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "discover", + "id": "def-public.DiscoverAppLocatorParams.breakdownField", + "type": "string", + "tags": [], + "label": "breakdownField", + "description": [ + "\nBreakdown field" + ], + "signature": [ + "string | undefined" + ], + "path": "src/plugins/discover/public/locator.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false @@ -1295,6 +1311,20 @@ "path": "src/plugins/saved_search/public/services/saved_searches/types.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "discover", + "id": "def-public.SavedSearch.breakdownField", + "type": "string", + "tags": [], + "label": "breakdownField", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "src/plugins/saved_search/public/services/saved_searches/types.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false diff --git a/api_docs/discover.mdx b/api_docs/discover.mdx index 960be9cb2ca2b..58335dd854878 100644 --- a/api_docs/discover.mdx +++ b/api_docs/discover.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/discover title: "discover" image: https://source.unsplash.com/400x175/?github description: API docs for the discover plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'discover'] --- import discoverObj from './discover.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Data Discovery](https://github.com/orgs/elastic/teams/kibana-data-disco | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 98 | 0 | 81 | 4 | +| 100 | 0 | 82 | 4 | ## Client diff --git a/api_docs/discover_enhanced.mdx b/api_docs/discover_enhanced.mdx index 6acd323a8399a..3faa50733265a 100644 --- a/api_docs/discover_enhanced.mdx +++ b/api_docs/discover_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/discoverEnhanced title: "discoverEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the discoverEnhanced plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'discoverEnhanced'] --- import discoverEnhancedObj from './discover_enhanced.devdocs.json'; diff --git a/api_docs/embeddable.mdx b/api_docs/embeddable.mdx index 6a89dc52f3556..b972c0f166e76 100644 --- a/api_docs/embeddable.mdx +++ b/api_docs/embeddable.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/embeddable title: "embeddable" image: https://source.unsplash.com/400x175/?github description: API docs for the embeddable plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'embeddable'] --- import embeddableObj from './embeddable.devdocs.json'; diff --git a/api_docs/embeddable_enhanced.mdx b/api_docs/embeddable_enhanced.mdx index 7bc58d4f14c52..0f08c9373088e 100644 --- a/api_docs/embeddable_enhanced.mdx +++ b/api_docs/embeddable_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/embeddableEnhanced title: "embeddableEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the embeddableEnhanced plugin -date: 2022-11-29 +date: 2022-12-06 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 25326a1747fa2..1c25d847b99e2 100644 --- a/api_docs/encrypted_saved_objects.mdx +++ b/api_docs/encrypted_saved_objects.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/encryptedSavedObjects title: "encryptedSavedObjects" image: https://source.unsplash.com/400x175/?github description: API docs for the encryptedSavedObjects plugin -date: 2022-11-29 +date: 2022-12-06 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 9ffad9328a9fe..51ab2b0bbcc61 100644 --- a/api_docs/enterprise_search.mdx +++ b/api_docs/enterprise_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/enterpriseSearch title: "enterpriseSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the enterpriseSearch plugin -date: 2022-11-29 +date: 2022-12-06 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 c0b5edb29bff4..40e1fd571a8d7 100644 --- a/api_docs/es_ui_shared.mdx +++ b/api_docs/es_ui_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/esUiShared title: "esUiShared" image: https://source.unsplash.com/400x175/?github description: API docs for the esUiShared plugin -date: 2022-11-29 +date: 2022-12-06 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 bc2ab212ef9bd..4ea55ef4ad838 100644 --- a/api_docs/event_annotation.mdx +++ b/api_docs/event_annotation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/eventAnnotation title: "eventAnnotation" image: https://source.unsplash.com/400x175/?github description: API docs for the eventAnnotation plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'eventAnnotation'] --- import eventAnnotationObj from './event_annotation.devdocs.json'; diff --git a/api_docs/event_log.devdocs.json b/api_docs/event_log.devdocs.json index af0bd4e00e28c..d25c528e84274 100644 --- a/api_docs/event_log.devdocs.json +++ b/api_docs/event_log.devdocs.json @@ -1499,7 +1499,7 @@ "label": "data", "description": [], "signature": [ - "(Readonly<{ error?: Readonly<{ type?: string | undefined; id?: string | undefined; message?: string | undefined; code?: string | undefined; stack_trace?: string | undefined; } & {}> | undefined; tags?: string[] | undefined; log?: Readonly<{ logger?: string | undefined; level?: string | undefined; } & {}> | undefined; user?: Readonly<{ name?: string | undefined; } & {}> | undefined; message?: string | undefined; kibana?: Readonly<{ alert?: Readonly<{ rule?: Readonly<{ consumer?: string | undefined; execution?: Readonly<{ status?: string | undefined; metrics?: Readonly<{ number_of_triggered_actions?: string | number | undefined; number_of_generated_actions?: string | number | undefined; alert_counts?: Readonly<{ recovered?: string | number | undefined; active?: string | number | undefined; new?: string | number | undefined; } & {}> | undefined; number_of_searches?: string | number | undefined; total_indexing_duration_ms?: string | number | undefined; es_search_duration_ms?: string | number | undefined; total_search_duration_ms?: string | number | undefined; execution_gap_duration_s?: string | number | undefined; rule_type_run_duration_ms?: string | number | undefined; process_alerts_duration_ms?: string | number | undefined; trigger_actions_duration_ms?: string | number | undefined; process_rule_duration_ms?: string | number | undefined; claim_to_start_duration_ms?: string | number | undefined; prepare_rule_duration_ms?: string | number | undefined; total_run_duration_ms?: string | number | undefined; total_enrichment_duration_ms?: string | number | undefined; } & {}> | undefined; uuid?: string | undefined; status_order?: string | number | undefined; } & {}> | undefined; rule_type_id?: string | undefined; } & {}> | undefined; flapping?: boolean | undefined; } & {}> | undefined; version?: string | undefined; alerting?: Readonly<{ status?: string | undefined; outcome?: string | undefined; instance_id?: string | undefined; action_group_id?: string | undefined; action_subgroup?: string | undefined; } & {}> | undefined; server_uuid?: string | undefined; task?: Readonly<{ id?: string | undefined; schedule_delay?: string | number | undefined; scheduled?: string | undefined; } & {}> | undefined; saved_objects?: Readonly<{ type?: string | undefined; id?: string | undefined; namespace?: string | undefined; rel?: string | undefined; type_id?: string | undefined; } & {}>[] | undefined; space_ids?: string[] | undefined; } & {}> | undefined; ecs?: Readonly<{ version?: string | undefined; } & {}> | undefined; rule?: Readonly<{ name?: string | undefined; description?: string | undefined; category?: string | undefined; id?: string | undefined; uuid?: string | undefined; version?: string | undefined; license?: string | undefined; reference?: string | undefined; author?: string[] | undefined; ruleset?: string | undefined; } & {}> | undefined; event?: Readonly<{ start?: string | undefined; category?: string[] | undefined; type?: string[] | undefined; id?: string | undefined; reason?: string | undefined; created?: string | undefined; outcome?: string | undefined; end?: string | undefined; original?: string | undefined; duration?: string | number | undefined; kind?: string | undefined; hash?: string | undefined; code?: string | undefined; url?: string | undefined; action?: string | undefined; severity?: string | number | undefined; dataset?: string | undefined; ingested?: string | undefined; module?: string | undefined; provider?: string | undefined; reference?: string | undefined; risk_score?: number | undefined; risk_score_norm?: number | undefined; sequence?: string | number | undefined; timezone?: string | undefined; } & {}> | undefined; '@timestamp'?: string | undefined; } & {}> | undefined)[]" + "(Readonly<{ error?: Readonly<{ type?: string | undefined; id?: string | undefined; message?: string | undefined; code?: string | undefined; stack_trace?: string | undefined; } & {}> | undefined; tags?: string[] | undefined; log?: Readonly<{ logger?: string | undefined; level?: string | undefined; } & {}> | undefined; user?: Readonly<{ name?: string | undefined; } & {}> | undefined; message?: string | undefined; kibana?: Readonly<{ alert?: Readonly<{ rule?: Readonly<{ consumer?: string | undefined; execution?: Readonly<{ status?: string | undefined; metrics?: Readonly<{ number_of_triggered_actions?: string | number | undefined; number_of_generated_actions?: string | number | undefined; alert_counts?: Readonly<{ active?: string | number | undefined; recovered?: string | number | undefined; new?: string | number | undefined; } & {}> | undefined; number_of_searches?: string | number | undefined; total_indexing_duration_ms?: string | number | undefined; es_search_duration_ms?: string | number | undefined; total_search_duration_ms?: string | number | undefined; execution_gap_duration_s?: string | number | undefined; rule_type_run_duration_ms?: string | number | undefined; process_alerts_duration_ms?: string | number | undefined; trigger_actions_duration_ms?: string | number | undefined; process_rule_duration_ms?: string | number | undefined; claim_to_start_duration_ms?: string | number | undefined; prepare_rule_duration_ms?: string | number | undefined; total_run_duration_ms?: string | number | undefined; total_enrichment_duration_ms?: string | number | undefined; } & {}> | undefined; uuid?: string | undefined; status_order?: string | number | undefined; } & {}> | undefined; rule_type_id?: string | undefined; } & {}> | undefined; flapping?: boolean | undefined; } & {}> | undefined; version?: string | undefined; alerting?: Readonly<{ status?: string | undefined; outcome?: string | undefined; instance_id?: string | undefined; action_group_id?: string | undefined; action_subgroup?: string | undefined; } & {}> | undefined; server_uuid?: string | undefined; task?: Readonly<{ id?: string | undefined; schedule_delay?: string | number | undefined; scheduled?: string | undefined; } & {}> | undefined; saved_objects?: Readonly<{ type?: string | undefined; id?: string | undefined; namespace?: string | undefined; rel?: string | undefined; type_id?: string | undefined; } & {}>[] | undefined; space_ids?: string[] | undefined; } & {}> | undefined; ecs?: Readonly<{ version?: string | undefined; } & {}> | undefined; rule?: Readonly<{ name?: string | undefined; description?: string | undefined; category?: string | undefined; id?: string | undefined; uuid?: string | undefined; version?: string | undefined; license?: string | undefined; reference?: string | undefined; author?: string[] | undefined; ruleset?: string | undefined; } & {}> | undefined; event?: Readonly<{ start?: string | undefined; category?: string[] | undefined; type?: string[] | undefined; id?: string | undefined; reason?: string | undefined; created?: string | undefined; outcome?: string | undefined; end?: string | undefined; original?: string | undefined; duration?: string | number | undefined; kind?: string | undefined; hash?: string | undefined; url?: string | undefined; code?: string | undefined; action?: string | undefined; severity?: string | number | undefined; dataset?: string | undefined; ingested?: string | undefined; module?: string | undefined; provider?: string | undefined; reference?: string | undefined; risk_score?: number | undefined; risk_score_norm?: number | undefined; sequence?: string | number | undefined; timezone?: string | undefined; } & {}> | undefined; '@timestamp'?: string | undefined; } & {}> | undefined)[]" ], "path": "x-pack/plugins/event_log/server/es/cluster_client_adapter.ts", "deprecated": false, @@ -1519,7 +1519,7 @@ "label": "IEvent", "description": [], "signature": [ - "DeepPartial | undefined; tags?: string[] | undefined; log?: Readonly<{ logger?: string | undefined; level?: string | undefined; } & {}> | undefined; user?: Readonly<{ name?: string | undefined; } & {}> | undefined; message?: string | undefined; kibana?: Readonly<{ alert?: Readonly<{ rule?: Readonly<{ consumer?: string | undefined; execution?: Readonly<{ status?: string | undefined; metrics?: Readonly<{ number_of_triggered_actions?: string | number | undefined; number_of_generated_actions?: string | number | undefined; alert_counts?: Readonly<{ recovered?: string | number | undefined; active?: string | number | undefined; new?: string | number | undefined; } & {}> | undefined; number_of_searches?: string | number | undefined; total_indexing_duration_ms?: string | number | undefined; es_search_duration_ms?: string | number | undefined; total_search_duration_ms?: string | number | undefined; execution_gap_duration_s?: string | number | undefined; rule_type_run_duration_ms?: string | number | undefined; process_alerts_duration_ms?: string | number | undefined; trigger_actions_duration_ms?: string | number | undefined; process_rule_duration_ms?: string | number | undefined; claim_to_start_duration_ms?: string | number | undefined; prepare_rule_duration_ms?: string | number | undefined; total_run_duration_ms?: string | number | undefined; total_enrichment_duration_ms?: string | number | undefined; } & {}> | undefined; uuid?: string | undefined; status_order?: string | number | undefined; } & {}> | undefined; rule_type_id?: string | undefined; } & {}> | undefined; flapping?: boolean | undefined; } & {}> | undefined; version?: string | undefined; alerting?: Readonly<{ status?: string | undefined; outcome?: string | undefined; instance_id?: string | undefined; action_group_id?: string | undefined; action_subgroup?: string | undefined; } & {}> | undefined; server_uuid?: string | undefined; task?: Readonly<{ id?: string | undefined; schedule_delay?: string | number | undefined; scheduled?: string | undefined; } & {}> | undefined; saved_objects?: Readonly<{ type?: string | undefined; id?: string | undefined; namespace?: string | undefined; rel?: string | undefined; type_id?: string | undefined; } & {}>[] | undefined; space_ids?: string[] | undefined; } & {}> | undefined; ecs?: Readonly<{ version?: string | undefined; } & {}> | undefined; rule?: Readonly<{ name?: string | undefined; description?: string | undefined; category?: string | undefined; id?: string | undefined; uuid?: string | undefined; version?: string | undefined; license?: string | undefined; reference?: string | undefined; author?: string[] | undefined; ruleset?: string | undefined; } & {}> | undefined; event?: Readonly<{ start?: string | undefined; category?: string[] | undefined; type?: string[] | undefined; id?: string | undefined; reason?: string | undefined; created?: string | undefined; outcome?: string | undefined; end?: string | undefined; original?: string | undefined; duration?: string | number | undefined; kind?: string | undefined; hash?: string | undefined; code?: string | undefined; url?: string | undefined; action?: string | undefined; severity?: string | number | undefined; dataset?: string | undefined; ingested?: string | undefined; module?: string | undefined; provider?: string | undefined; reference?: string | undefined; risk_score?: number | undefined; risk_score_norm?: number | undefined; sequence?: string | number | undefined; timezone?: string | undefined; } & {}> | undefined; '@timestamp'?: string | undefined; } & {}>>> | undefined" + "DeepPartial | undefined; tags?: string[] | undefined; log?: Readonly<{ logger?: string | undefined; level?: string | undefined; } & {}> | undefined; user?: Readonly<{ name?: string | undefined; } & {}> | undefined; message?: string | undefined; kibana?: Readonly<{ alert?: Readonly<{ rule?: Readonly<{ consumer?: string | undefined; execution?: Readonly<{ status?: string | undefined; metrics?: Readonly<{ number_of_triggered_actions?: string | number | undefined; number_of_generated_actions?: string | number | undefined; alert_counts?: Readonly<{ active?: string | number | undefined; recovered?: string | number | undefined; new?: string | number | undefined; } & {}> | undefined; number_of_searches?: string | number | undefined; total_indexing_duration_ms?: string | number | undefined; es_search_duration_ms?: string | number | undefined; total_search_duration_ms?: string | number | undefined; execution_gap_duration_s?: string | number | undefined; rule_type_run_duration_ms?: string | number | undefined; process_alerts_duration_ms?: string | number | undefined; trigger_actions_duration_ms?: string | number | undefined; process_rule_duration_ms?: string | number | undefined; claim_to_start_duration_ms?: string | number | undefined; prepare_rule_duration_ms?: string | number | undefined; total_run_duration_ms?: string | number | undefined; total_enrichment_duration_ms?: string | number | undefined; } & {}> | undefined; uuid?: string | undefined; status_order?: string | number | undefined; } & {}> | undefined; rule_type_id?: string | undefined; } & {}> | undefined; flapping?: boolean | undefined; } & {}> | undefined; version?: string | undefined; alerting?: Readonly<{ status?: string | undefined; outcome?: string | undefined; instance_id?: string | undefined; action_group_id?: string | undefined; action_subgroup?: string | undefined; } & {}> | undefined; server_uuid?: string | undefined; task?: Readonly<{ id?: string | undefined; schedule_delay?: string | number | undefined; scheduled?: string | undefined; } & {}> | undefined; saved_objects?: Readonly<{ type?: string | undefined; id?: string | undefined; namespace?: string | undefined; rel?: string | undefined; type_id?: string | undefined; } & {}>[] | undefined; space_ids?: string[] | undefined; } & {}> | undefined; ecs?: Readonly<{ version?: string | undefined; } & {}> | undefined; rule?: Readonly<{ name?: string | undefined; description?: string | undefined; category?: string | undefined; id?: string | undefined; uuid?: string | undefined; version?: string | undefined; license?: string | undefined; reference?: string | undefined; author?: string[] | undefined; ruleset?: string | undefined; } & {}> | undefined; event?: Readonly<{ start?: string | undefined; category?: string[] | undefined; type?: string[] | undefined; id?: string | undefined; reason?: string | undefined; created?: string | undefined; outcome?: string | undefined; end?: string | undefined; original?: string | undefined; duration?: string | number | undefined; kind?: string | undefined; hash?: string | undefined; url?: string | undefined; code?: string | undefined; action?: string | undefined; severity?: string | number | undefined; dataset?: string | undefined; ingested?: string | undefined; module?: string | undefined; provider?: string | undefined; reference?: string | undefined; risk_score?: number | undefined; risk_score_norm?: number | undefined; sequence?: string | number | undefined; timezone?: string | undefined; } & {}> | undefined; '@timestamp'?: string | undefined; } & {}>>> | undefined" ], "path": "x-pack/plugins/event_log/generated/schemas.ts", "deprecated": false, @@ -1534,7 +1534,7 @@ "label": "IValidatedEvent", "description": [], "signature": [ - "Readonly<{ error?: Readonly<{ type?: string | undefined; id?: string | undefined; message?: string | undefined; code?: string | undefined; stack_trace?: string | undefined; } & {}> | undefined; tags?: string[] | undefined; log?: Readonly<{ logger?: string | undefined; level?: string | undefined; } & {}> | undefined; user?: Readonly<{ name?: string | undefined; } & {}> | undefined; message?: string | undefined; kibana?: Readonly<{ alert?: Readonly<{ rule?: Readonly<{ consumer?: string | undefined; execution?: Readonly<{ status?: string | undefined; metrics?: Readonly<{ number_of_triggered_actions?: string | number | undefined; number_of_generated_actions?: string | number | undefined; alert_counts?: Readonly<{ recovered?: string | number | undefined; active?: string | number | undefined; new?: string | number | undefined; } & {}> | undefined; number_of_searches?: string | number | undefined; total_indexing_duration_ms?: string | number | undefined; es_search_duration_ms?: string | number | undefined; total_search_duration_ms?: string | number | undefined; execution_gap_duration_s?: string | number | undefined; rule_type_run_duration_ms?: string | number | undefined; process_alerts_duration_ms?: string | number | undefined; trigger_actions_duration_ms?: string | number | undefined; process_rule_duration_ms?: string | number | undefined; claim_to_start_duration_ms?: string | number | undefined; prepare_rule_duration_ms?: string | number | undefined; total_run_duration_ms?: string | number | undefined; total_enrichment_duration_ms?: string | number | undefined; } & {}> | undefined; uuid?: string | undefined; status_order?: string | number | undefined; } & {}> | undefined; rule_type_id?: string | undefined; } & {}> | undefined; flapping?: boolean | undefined; } & {}> | undefined; version?: string | undefined; alerting?: Readonly<{ status?: string | undefined; outcome?: string | undefined; instance_id?: string | undefined; action_group_id?: string | undefined; action_subgroup?: string | undefined; } & {}> | undefined; server_uuid?: string | undefined; task?: Readonly<{ id?: string | undefined; schedule_delay?: string | number | undefined; scheduled?: string | undefined; } & {}> | undefined; saved_objects?: Readonly<{ type?: string | undefined; id?: string | undefined; namespace?: string | undefined; rel?: string | undefined; type_id?: string | undefined; } & {}>[] | undefined; space_ids?: string[] | undefined; } & {}> | undefined; ecs?: Readonly<{ version?: string | undefined; } & {}> | undefined; rule?: Readonly<{ name?: string | undefined; description?: string | undefined; category?: string | undefined; id?: string | undefined; uuid?: string | undefined; version?: string | undefined; license?: string | undefined; reference?: string | undefined; author?: string[] | undefined; ruleset?: string | undefined; } & {}> | undefined; event?: Readonly<{ start?: string | undefined; category?: string[] | undefined; type?: string[] | undefined; id?: string | undefined; reason?: string | undefined; created?: string | undefined; outcome?: string | undefined; end?: string | undefined; original?: string | undefined; duration?: string | number | undefined; kind?: string | undefined; hash?: string | undefined; code?: string | undefined; url?: string | undefined; action?: string | undefined; severity?: string | number | undefined; dataset?: string | undefined; ingested?: string | undefined; module?: string | undefined; provider?: string | undefined; reference?: string | undefined; risk_score?: number | undefined; risk_score_norm?: number | undefined; sequence?: string | number | undefined; timezone?: string | undefined; } & {}> | undefined; '@timestamp'?: string | undefined; } & {}> | undefined" + "Readonly<{ error?: Readonly<{ type?: string | undefined; id?: string | undefined; message?: string | undefined; code?: string | undefined; stack_trace?: string | undefined; } & {}> | undefined; tags?: string[] | undefined; log?: Readonly<{ logger?: string | undefined; level?: string | undefined; } & {}> | undefined; user?: Readonly<{ name?: string | undefined; } & {}> | undefined; message?: string | undefined; kibana?: Readonly<{ alert?: Readonly<{ rule?: Readonly<{ consumer?: string | undefined; execution?: Readonly<{ status?: string | undefined; metrics?: Readonly<{ number_of_triggered_actions?: string | number | undefined; number_of_generated_actions?: string | number | undefined; alert_counts?: Readonly<{ active?: string | number | undefined; recovered?: string | number | undefined; new?: string | number | undefined; } & {}> | undefined; number_of_searches?: string | number | undefined; total_indexing_duration_ms?: string | number | undefined; es_search_duration_ms?: string | number | undefined; total_search_duration_ms?: string | number | undefined; execution_gap_duration_s?: string | number | undefined; rule_type_run_duration_ms?: string | number | undefined; process_alerts_duration_ms?: string | number | undefined; trigger_actions_duration_ms?: string | number | undefined; process_rule_duration_ms?: string | number | undefined; claim_to_start_duration_ms?: string | number | undefined; prepare_rule_duration_ms?: string | number | undefined; total_run_duration_ms?: string | number | undefined; total_enrichment_duration_ms?: string | number | undefined; } & {}> | undefined; uuid?: string | undefined; status_order?: string | number | undefined; } & {}> | undefined; rule_type_id?: string | undefined; } & {}> | undefined; flapping?: boolean | undefined; } & {}> | undefined; version?: string | undefined; alerting?: Readonly<{ status?: string | undefined; outcome?: string | undefined; instance_id?: string | undefined; action_group_id?: string | undefined; action_subgroup?: string | undefined; } & {}> | undefined; server_uuid?: string | undefined; task?: Readonly<{ id?: string | undefined; schedule_delay?: string | number | undefined; scheduled?: string | undefined; } & {}> | undefined; saved_objects?: Readonly<{ type?: string | undefined; id?: string | undefined; namespace?: string | undefined; rel?: string | undefined; type_id?: string | undefined; } & {}>[] | undefined; space_ids?: string[] | undefined; } & {}> | undefined; ecs?: Readonly<{ version?: string | undefined; } & {}> | undefined; rule?: Readonly<{ name?: string | undefined; description?: string | undefined; category?: string | undefined; id?: string | undefined; uuid?: string | undefined; version?: string | undefined; license?: string | undefined; reference?: string | undefined; author?: string[] | undefined; ruleset?: string | undefined; } & {}> | undefined; event?: Readonly<{ start?: string | undefined; category?: string[] | undefined; type?: string[] | undefined; id?: string | undefined; reason?: string | undefined; created?: string | undefined; outcome?: string | undefined; end?: string | undefined; original?: string | undefined; duration?: string | number | undefined; kind?: string | undefined; hash?: string | undefined; url?: string | undefined; code?: string | undefined; action?: string | undefined; severity?: string | number | undefined; dataset?: string | undefined; ingested?: string | undefined; module?: string | undefined; provider?: string | undefined; reference?: string | undefined; risk_score?: number | undefined; risk_score_norm?: number | undefined; sequence?: string | number | undefined; timezone?: string | undefined; } & {}> | undefined; '@timestamp'?: string | undefined; } & {}> | undefined" ], "path": "x-pack/plugins/event_log/generated/schemas.ts", "deprecated": false, diff --git a/api_docs/event_log.mdx b/api_docs/event_log.mdx index c279f6e5b05e1..47e36c70b1092 100644 --- a/api_docs/event_log.mdx +++ b/api_docs/event_log.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/eventLog title: "eventLog" image: https://source.unsplash.com/400x175/?github description: API docs for the eventLog plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'eventLog'] --- import eventLogObj from './event_log.devdocs.json'; diff --git a/api_docs/expression_error.mdx b/api_docs/expression_error.mdx index 7b9e87ee96ed2..c98c67e26ebd5 100644 --- a/api_docs/expression_error.mdx +++ b/api_docs/expression_error.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionError title: "expressionError" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionError plugin -date: 2022-11-29 +date: 2022-12-06 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 0d1c2cbe68b72..54980395d540a 100644 --- a/api_docs/expression_gauge.mdx +++ b/api_docs/expression_gauge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionGauge title: "expressionGauge" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionGauge plugin -date: 2022-11-29 +date: 2022-12-06 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 9c66b9ad05a38..2ef98aa58496f 100644 --- a/api_docs/expression_heatmap.mdx +++ b/api_docs/expression_heatmap.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionHeatmap title: "expressionHeatmap" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionHeatmap plugin -date: 2022-11-29 +date: 2022-12-06 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 2a36e47356513..17756263a9a36 100644 --- a/api_docs/expression_image.mdx +++ b/api_docs/expression_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionImage title: "expressionImage" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionImage plugin -date: 2022-11-29 +date: 2022-12-06 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 5bfb6eebc8188..4703bf686e102 100644 --- a/api_docs/expression_legacy_metric_vis.mdx +++ b/api_docs/expression_legacy_metric_vis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionLegacyMetricVis title: "expressionLegacyMetricVis" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionLegacyMetricVis plugin -date: 2022-11-29 +date: 2022-12-06 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 10fea40dc0e4c..56f4a0d5ffa0d 100644 --- a/api_docs/expression_metric.mdx +++ b/api_docs/expression_metric.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionMetric title: "expressionMetric" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionMetric plugin -date: 2022-11-29 +date: 2022-12-06 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 0c83a2c76614d..4540e673800ac 100644 --- a/api_docs/expression_metric_vis.mdx +++ b/api_docs/expression_metric_vis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionMetricVis title: "expressionMetricVis" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionMetricVis plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionMetricVis'] --- import expressionMetricVisObj from './expression_metric_vis.devdocs.json'; diff --git a/api_docs/expression_partition_vis.devdocs.json b/api_docs/expression_partition_vis.devdocs.json index cd8bf44d3cfa0..46b022d98fc9b 100644 --- a/api_docs/expression_partition_vis.devdocs.json +++ b/api_docs/expression_partition_vis.devdocs.json @@ -472,6 +472,20 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "expressionPartitionVis", + "id": "def-common.LabelsParams.colorOverrides", + "type": "Object", + "tags": [], + "label": "colorOverrides", + "description": [], + "signature": [ + "{ [x: string]: string; }" + ], + "path": "src/plugins/chart_expressions/expression_partition_vis/common/types/expression_renderers.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "expressionPartitionVis", "id": "def-common.LabelsParams.truncate", @@ -542,7 +556,7 @@ "section": "def-common.MosaicVisConfig", "text": "MosaicVisConfig" }, - " extends Omit" + " extends Omit" ], "path": "src/plugins/chart_expressions/expression_partition_vis/common/types/expression_renderers.ts", "deprecated": false, @@ -1078,7 +1092,7 @@ "section": "def-common.ValueFormats", "text": "ValueFormats" }, - "; percentDecimals: number; truncate?: number | null | undefined; last_level?: boolean | undefined; }" + "; percentDecimals: number; colorOverrides: Record; truncate?: number | null | undefined; last_level?: boolean | undefined; }" ], "path": "src/plugins/chart_expressions/expression_partition_vis/common/types/expression_functions.ts", "deprecated": false, diff --git a/api_docs/expression_partition_vis.mdx b/api_docs/expression_partition_vis.mdx index 9519a3a8756c8..29e876af2e085 100644 --- a/api_docs/expression_partition_vis.mdx +++ b/api_docs/expression_partition_vis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionPartitionVis title: "expressionPartitionVis" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionPartitionVis plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionPartitionVis'] --- import expressionPartitionVisObj from './expression_partition_vis.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Vis Editors](https://github.com/orgs/elastic/teams/kibana-visualization | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 71 | 0 | 71 | 2 | +| 72 | 0 | 72 | 2 | ## Client diff --git a/api_docs/expression_repeat_image.mdx b/api_docs/expression_repeat_image.mdx index 9aeaddb52218a..5cb0fdc2e8d90 100644 --- a/api_docs/expression_repeat_image.mdx +++ b/api_docs/expression_repeat_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionRepeatImage title: "expressionRepeatImage" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionRepeatImage plugin -date: 2022-11-29 +date: 2022-12-06 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 9300f2300876a..25a9194b7fdc4 100644 --- a/api_docs/expression_reveal_image.mdx +++ b/api_docs/expression_reveal_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionRevealImage title: "expressionRevealImage" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionRevealImage plugin -date: 2022-11-29 +date: 2022-12-06 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 bb63ccf91561a..47f8ce5c9c3f7 100644 --- a/api_docs/expression_shape.mdx +++ b/api_docs/expression_shape.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionShape title: "expressionShape" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionShape plugin -date: 2022-11-29 +date: 2022-12-06 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 a44cc313e03bf..0eb8c9e8d98de 100644 --- a/api_docs/expression_tagcloud.mdx +++ b/api_docs/expression_tagcloud.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionTagcloud title: "expressionTagcloud" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionTagcloud plugin -date: 2022-11-29 +date: 2022-12-06 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 a82a93f13b88a..fa79f4d4769e1 100644 --- a/api_docs/expression_x_y.mdx +++ b/api_docs/expression_x_y.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionXY title: "expressionXY" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionXY plugin -date: 2022-11-29 +date: 2022-12-06 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 2f16aaf8e2938..c412c816d8d47 100644 --- a/api_docs/expressions.mdx +++ b/api_docs/expressions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressions title: "expressions" image: https://source.unsplash.com/400x175/?github description: API docs for the expressions plugin -date: 2022-11-29 +date: 2022-12-06 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 9566eee5c52d0..d7499f356373c 100644 --- a/api_docs/features.mdx +++ b/api_docs/features.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/features title: "features" image: https://source.unsplash.com/400x175/?github description: API docs for the features plugin -date: 2022-11-29 +date: 2022-12-06 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 4d97e92a2b2bd..065653ee0f558 100644 --- a/api_docs/field_formats.mdx +++ b/api_docs/field_formats.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/fieldFormats title: "fieldFormats" image: https://source.unsplash.com/400x175/?github description: API docs for the fieldFormats plugin -date: 2022-11-29 +date: 2022-12-06 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 f0b3663dc0538..0f649447b182c 100644 --- a/api_docs/file_upload.mdx +++ b/api_docs/file_upload.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/fileUpload title: "fileUpload" image: https://source.unsplash.com/400x175/?github description: API docs for the fileUpload plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fileUpload'] --- import fileUploadObj from './file_upload.devdocs.json'; diff --git a/api_docs/files.devdocs.json b/api_docs/files.devdocs.json index 761cb3e7578f2..664a95623f5a9 100644 --- a/api_docs/files.devdocs.json +++ b/api_docs/files.devdocs.json @@ -2,655 +2,109 @@ "id": "files", "client": { "classes": [], - "functions": [ - { - "parentPluginId": "files", - "id": "def-public.FilePicker", - "type": "Function", - "tags": [], - "label": "FilePicker", - "description": [], - "signature": [ - "(props: ", - { - "pluginId": "files", - "scope": "public", - "docId": "kibFilesPluginApi", - "section": "def-public.Props", - "text": "Props" - }, - ") => JSX.Element" - ], - "path": "src/plugins/files/public/components/file_picker/index.tsx", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "files", - "id": "def-public.FilePicker.$1", - "type": "Object", - "tags": [], - "label": "props", - "description": [], - "signature": [ - { - "pluginId": "files", - "scope": "public", - "docId": "kibFilesPluginApi", - "section": "def-public.Props", - "text": "Props" - }, - "" - ], - "path": "src/plugins/files/public/components/file_picker/index.tsx", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [], - "initialIsOpen": false - }, - { - "parentPluginId": "files", - "id": "def-public.FilesContext", - "type": "Function", - "tags": [], - "label": "FilesContext", - "description": [], - "signature": [ - "({ client, children }: React.PropsWithChildren) => JSX.Element" - ], - "path": "src/plugins/files/public/components/context.tsx", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "files", - "id": "def-public.FilesContext.$1", - "type": "CompoundType", - "tags": [], - "label": "{ client, children }", - "description": [], - "signature": [ - "React.PropsWithChildren" - ], - "path": "src/plugins/files/public/components/context.tsx", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [], - "initialIsOpen": false - }, - { - "parentPluginId": "files", - "id": "def-public.UploadFile", - "type": "Function", - "tags": [], - "label": "UploadFile", - "description": [], - "signature": [ - "(props: ", - { - "pluginId": "files", - "scope": "public", - "docId": "kibFilesPluginApi", - "section": "def-public.UploadFileProps", - "text": "UploadFileProps" - }, - ") => JSX.Element" - ], - "path": "src/plugins/files/public/components/upload_file/index.tsx", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "files", - "id": "def-public.UploadFile.$1", - "type": "CompoundType", - "tags": [], - "label": "props", - "description": [], - "signature": [ - { - "pluginId": "files", - "scope": "public", - "docId": "kibFilesPluginApi", - "section": "def-public.UploadFileProps", - "text": "UploadFileProps" - } - ], - "path": "src/plugins/files/public/components/upload_file/index.tsx", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [], - "initialIsOpen": false - } - ], - "interfaces": [ - { - "parentPluginId": "files", - "id": "def-public.FilesClient", - "type": "Interface", - "tags": [], - "label": "FilesClient", - "description": [ - "\nA client that can be used to manage a specific {@link FileKind}." - ], - "signature": [ - { - "pluginId": "files", - "scope": "public", - "docId": "kibFilesPluginApi", - "section": "def-public.FilesClient", - "text": "FilesClient" - }, - " extends GlobalEndpoints" - ], - "path": "src/plugins/files/public/types.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "files", - "id": "def-public.FilesClient.create", - "type": "Function", - "tags": [], - "label": "create", - "description": [ - "\nCreate a new file object with the provided metadata.\n" - ], - "signature": [ - "(args: Readonly<{ meta?: Readonly<{} & {}> | undefined; alt?: string | undefined; mimeType?: string | undefined; } & { name: string; }> & { abortSignal?: AbortSignal | undefined; } & { kind: string; }) => Promise<{ file: ", - { - "pluginId": "files", - "scope": "common", - "docId": "kibFilesPluginApi", - "section": "def-common.FileJSON", - "text": "FileJSON" - }, - "; }>" - ], - "path": "src/plugins/files/public/types.ts", - "deprecated": false, - "trackAdoption": false, - "returnComment": [], - "children": [ - { - "parentPluginId": "files", - "id": "def-public.FilesClient.create.$1", - "type": "CompoundType", - "tags": [], - "label": "args", - "description": [ - "- create file args" - ], - "signature": [ - "E[\"inputs\"][\"body\"] & E[\"inputs\"][\"params\"] & E[\"inputs\"][\"query\"] & { abortSignal?: AbortSignal | undefined; } & { kind: string; } & ExtraArgs" - ], - "path": "src/plugins/files/public/types.ts", - "deprecated": false, - "trackAdoption": false - } - ] - }, - { - "parentPluginId": "files", - "id": "def-public.FilesClient.delete", - "type": "Function", - "tags": [], - "label": "delete", - "description": [ - "\nDelete a file object and all associated share and content objects.\n" - ], - "signature": [ - "(args: Readonly<{} & { id: string; }> & { abortSignal?: AbortSignal | undefined; } & { kind: string; }) => Promise<{ ok: true; }>" - ], - "path": "src/plugins/files/public/types.ts", - "deprecated": false, - "trackAdoption": false, - "returnComment": [], - "children": [ - { - "parentPluginId": "files", - "id": "def-public.FilesClient.delete.$1", - "type": "CompoundType", - "tags": [], - "label": "args", - "description": [ - "- delete file args" - ], - "signature": [ - "E[\"inputs\"][\"body\"] & E[\"inputs\"][\"params\"] & E[\"inputs\"][\"query\"] & { abortSignal?: AbortSignal | undefined; } & { kind: string; } & ExtraArgs" - ], - "path": "src/plugins/files/public/types.ts", - "deprecated": false, - "trackAdoption": false - } - ] - }, - { - "parentPluginId": "files", - "id": "def-public.FilesClient.getById", - "type": "Function", - "tags": [], - "label": "getById", - "description": [ - "\nGet a file object by ID.\n" - ], - "signature": [ - "(args: Readonly<{} & { id: string; }> & { abortSignal?: AbortSignal | undefined; } & { kind: string; }) => Promise<{ file: ", - { - "pluginId": "files", - "scope": "common", - "docId": "kibFilesPluginApi", - "section": "def-common.FileJSON", - "text": "FileJSON" - }, - "; }>" - ], - "path": "src/plugins/files/public/types.ts", - "deprecated": false, - "trackAdoption": false, - "returnComment": [], - "children": [ - { - "parentPluginId": "files", - "id": "def-public.FilesClient.getById.$1", - "type": "CompoundType", - "tags": [], - "label": "args", - "description": [ - "- get file by ID args" - ], - "signature": [ - "E[\"inputs\"][\"body\"] & E[\"inputs\"][\"params\"] & E[\"inputs\"][\"query\"] & { abortSignal?: AbortSignal | undefined; } & { kind: string; } & ExtraArgs" - ], - "path": "src/plugins/files/public/types.ts", - "deprecated": false, - "trackAdoption": false - } - ] - }, - { - "parentPluginId": "files", - "id": "def-public.FilesClient.list", - "type": "Function", - "tags": [], - "label": "list", - "description": [ - "\nList all file objects, of a given {@link FileKind}.\n" - ], - "signature": [ - "(args: Readonly<{ name?: string | string[] | undefined; status?: string | string[] | undefined; meta?: Readonly<{} & {}> | undefined; extension?: string | string[] | undefined; } & {}> & Readonly<{ page?: number | undefined; perPage?: number | undefined; } & {}> & { abortSignal?: AbortSignal | undefined; } & { kind: string; }) => Promise<{ files: ", - { - "pluginId": "files", - "scope": "common", - "docId": "kibFilesPluginApi", - "section": "def-common.FileJSON", - "text": "FileJSON" - }, - "[]; total: number; }>" - ], - "path": "src/plugins/files/public/types.ts", - "deprecated": false, - "trackAdoption": false, - "returnComment": [], - "children": [ - { - "parentPluginId": "files", - "id": "def-public.FilesClient.list.$1", - "type": "CompoundType", - "tags": [], - "label": "args", - "description": [ - "- list files args" - ], - "signature": [ - "E[\"inputs\"][\"body\"] & E[\"inputs\"][\"params\"] & E[\"inputs\"][\"query\"] & { abortSignal?: AbortSignal | undefined; } & { kind: string; } & ExtraArgs" - ], - "path": "src/plugins/files/public/types.ts", - "deprecated": false, - "trackAdoption": false - } - ] - }, - { - "parentPluginId": "files", - "id": "def-public.FilesClient.update", - "type": "Function", - "tags": [], - "label": "update", - "description": [ - "\nUpdate a set of of metadata values of the file object.\n" - ], - "signature": [ - "(args: Readonly<{ name?: string | undefined; meta?: Readonly<{} & {}> | undefined; alt?: string | undefined; } & {}> & Readonly<{} & { id: string; }> & { abortSignal?: AbortSignal | undefined; } & { kind: string; }) => Promise<{ file: ", - { - "pluginId": "files", - "scope": "common", - "docId": "kibFilesPluginApi", - "section": "def-common.FileJSON", - "text": "FileJSON" - }, - "; }>" - ], - "path": "src/plugins/files/public/types.ts", - "deprecated": false, - "trackAdoption": false, - "returnComment": [], - "children": [ - { - "parentPluginId": "files", - "id": "def-public.FilesClient.update.$1", - "type": "CompoundType", - "tags": [], - "label": "args", - "description": [ - "- update file args" - ], - "signature": [ - "E[\"inputs\"][\"body\"] & E[\"inputs\"][\"params\"] & E[\"inputs\"][\"query\"] & { abortSignal?: AbortSignal | undefined; } & { kind: string; } & ExtraArgs" - ], - "path": "src/plugins/files/public/types.ts", - "deprecated": false, - "trackAdoption": false - } - ] - }, - { - "parentPluginId": "files", - "id": "def-public.FilesClient.upload", - "type": "Function", - "tags": [], - "label": "upload", - "description": [ - "\nStream the contents of the file to Kibana server for storage.\n" - ], - "signature": [ - "(args: Readonly<{} & { id: string; }> & Readonly<{ selfDestructOnAbort?: boolean | undefined; } & {}> & { body: unknown; kind: string; abortSignal?: AbortSignal | undefined; contentType?: string | undefined; }) => Promise<{ ok: true; size: number; }>" - ], - "path": "src/plugins/files/public/types.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "files", - "id": "def-public.FilesClient.upload.$1", - "type": "CompoundType", - "tags": [], - "label": "args", - "description": [ - "- upload file args" - ], - "signature": [ - "Readonly<{} & { id: string; }> & Readonly<{ selfDestructOnAbort?: boolean | undefined; } & {}> & { body: unknown; kind: string; abortSignal?: AbortSignal | undefined; contentType?: string | undefined; }" - ], - "path": "src/plugins/files/public/types.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "files", - "id": "def-public.FilesClient.download", - "type": "Function", - "tags": [], - "label": "download", - "description": [ - "\nStream a download of the file object's content.\n" - ], - "signature": [ - "(args: Readonly<{ fileName?: string | undefined; } & { id: string; }> & { abortSignal?: AbortSignal | undefined; } & { kind: string; }) => Promise" - ], - "path": "src/plugins/files/public/types.ts", - "deprecated": false, - "trackAdoption": false, - "returnComment": [], - "children": [ - { - "parentPluginId": "files", - "id": "def-public.FilesClient.download.$1", - "type": "CompoundType", - "tags": [], - "label": "args", - "description": [ - "- download file args" - ], - "signature": [ - "E[\"inputs\"][\"body\"] & E[\"inputs\"][\"params\"] & E[\"inputs\"][\"query\"] & { abortSignal?: AbortSignal | undefined; } & { kind: string; } & ExtraArgs" - ], - "path": "src/plugins/files/public/types.ts", - "deprecated": false, - "trackAdoption": false - } - ] - }, - { - "parentPluginId": "files", - "id": "def-public.FilesClient.getDownloadHref", - "type": "Function", - "tags": [], - "label": "getDownloadHref", - "description": [ - "\nGet a string for downloading a file that can be passed to a button element's\nhref for download.\n" - ], - "signature": [ - "(args: Pick<", - { - "pluginId": "files", - "scope": "common", - "docId": "kibFilesPluginApi", - "section": "def-common.FileJSON", - "text": "FileJSON" - }, - ", \"id\" | \"fileKind\">) => string" - ], - "path": "src/plugins/files/public/types.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "files", - "id": "def-public.FilesClient.getDownloadHref.$1", - "type": "Object", - "tags": [], - "label": "args", - "description": [ - "- get download URL args" - ], - "signature": [ - "Pick<", - { - "pluginId": "files", - "scope": "common", - "docId": "kibFilesPluginApi", - "section": "def-common.FileJSON", - "text": "FileJSON" - }, - ", \"id\" | \"fileKind\">" - ], - "path": "src/plugins/files/public/types.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, + "functions": [], + "interfaces": [ + { + "parentPluginId": "files", + "id": "def-public.FilesClient", + "type": "Interface", + "tags": [], + "label": "FilesClient", + "description": [ + "\nA client that can be used to manage a specific {@link FileKind}." + ], + "signature": [ + "FilesClient", + " extends ", + "BaseFilesClient", + "" + ], + "path": "src/plugins/files/common/files_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ { "parentPluginId": "files", - "id": "def-public.FilesClient.share", + "id": "def-public.FilesClient.getMetrics", "type": "Function", - "tags": [ - "note" - ], - "label": "share", + "tags": [], + "label": "getMetrics", "description": [ - "\nShare a file by creating a new file share instance.\n" + "\nGet metrics of file system, like storage usage.\n" ], "signature": [ - "(args: Readonly<{ name?: string | undefined; validUntil?: number | undefined; } & {}> & Readonly<{} & { fileId: string; }> & { abortSignal?: AbortSignal | undefined; } & { kind: string; }) => Promise<", + "() => Promise<", { "pluginId": "files", "scope": "common", "docId": "kibFilesPluginApi", - "section": "def-common.FileShareJSONWithToken", - "text": "FileShareJSONWithToken" + "section": "def-common.FilesMetrics", + "text": "FilesMetrics" }, ">" ], - "path": "src/plugins/files/public/types.ts", - "deprecated": false, - "trackAdoption": false, - "returnComment": [], - "children": [ - { - "parentPluginId": "files", - "id": "def-public.FilesClient.share.$1", - "type": "CompoundType", - "tags": [], - "label": "args", - "description": [ - "- File share arguments" - ], - "signature": [ - "E[\"inputs\"][\"body\"] & E[\"inputs\"][\"params\"] & E[\"inputs\"][\"query\"] & { abortSignal?: AbortSignal | undefined; } & { kind: string; } & ExtraArgs" - ], - "path": "src/plugins/files/public/types.ts", - "deprecated": false, - "trackAdoption": false - } - ] - }, - { - "parentPluginId": "files", - "id": "def-public.FilesClient.unshare", - "type": "Function", - "tags": [], - "label": "unshare", - "description": [ - "\nDelete a file share instance.\n" - ], - "signature": [ - "(args: Readonly<{} & { id: string; }> & { abortSignal?: AbortSignal | undefined; } & { kind: string; }) => Promise<{ ok: true; }>" - ], - "path": "src/plugins/files/public/types.ts", + "path": "src/plugins/files/common/files_client.ts", "deprecated": false, "trackAdoption": false, - "returnComment": [], - "children": [ - { - "parentPluginId": "files", - "id": "def-public.FilesClient.unshare.$1", - "type": "CompoundType", - "tags": [], - "label": "args", - "description": [ - "- File unshare arguments" - ], - "signature": [ - "E[\"inputs\"][\"body\"] & E[\"inputs\"][\"params\"] & E[\"inputs\"][\"query\"] & { abortSignal?: AbortSignal | undefined; } & { kind: string; } & ExtraArgs" - ], - "path": "src/plugins/files/public/types.ts", - "deprecated": false, - "trackAdoption": false - } - ] + "children": [], + "returnComment": [] }, { "parentPluginId": "files", - "id": "def-public.FilesClient.getShare", + "id": "def-public.FilesClient.publicDownload", "type": "Function", "tags": [], - "label": "getShare", + "label": "publicDownload", "description": [ - "\nGet a file share instance.\n" + "\nDownload a file, bypassing regular security by way of a\nsecret share token.\n" ], "signature": [ - "(args: Readonly<{} & { id: string; }> & { abortSignal?: AbortSignal | undefined; } & { kind: string; }) => Promise<{ share: ", - { - "pluginId": "files", - "scope": "common", - "docId": "kibFilesPluginApi", - "section": "def-common.FileShareJSON", - "text": "FileShareJSON" - }, - "; }>" + "(args: { token: string; fileName?: string | undefined; }) => any" ], - "path": "src/plugins/files/public/types.ts", + "path": "src/plugins/files/common/files_client.ts", "deprecated": false, "trackAdoption": false, - "returnComment": [], "children": [ { "parentPluginId": "files", - "id": "def-public.FilesClient.getShare.$1", - "type": "CompoundType", + "id": "def-public.FilesClient.publicDownload.$1", + "type": "Object", "tags": [], "label": "args", - "description": [ - "- Get file share arguments" - ], - "signature": [ - "E[\"inputs\"][\"body\"] & E[\"inputs\"][\"params\"] & E[\"inputs\"][\"query\"] & { abortSignal?: AbortSignal | undefined; } & { kind: string; } & ExtraArgs" - ], - "path": "src/plugins/files/public/types.ts", + "description": [], + "path": "src/plugins/files/common/files_client.ts", "deprecated": false, - "trackAdoption": false + "trackAdoption": false, + "children": [ + { + "parentPluginId": "files", + "id": "def-public.FilesClient.publicDownload.$1.token", + "type": "string", + "tags": [], + "label": "token", + "description": [], + "path": "src/plugins/files/common/files_client.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "files", + "id": "def-public.FilesClient.publicDownload.$1.fileName", + "type": "string", + "tags": [], + "label": "fileName", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "src/plugins/files/common/files_client.ts", + "deprecated": false, + "trackAdoption": false + } + ] } - ] - }, - { - "parentPluginId": "files", - "id": "def-public.FilesClient.listShares", - "type": "Function", - "tags": [], - "label": "listShares", - "description": [ - "\nList all file shares. Optionally scoping to a specific\nfile.\n" - ], - "signature": [ - "(args: Readonly<{ page?: number | undefined; perPage?: number | undefined; forFileId?: string | undefined; } & {}> & { abortSignal?: AbortSignal | undefined; } & { kind: string; }) => Promise<{ shares: ", - { - "pluginId": "files", - "scope": "common", - "docId": "kibFilesPluginApi", - "section": "def-common.FileShareJSON", - "text": "FileShareJSON" - }, - "[]; }>" ], - "path": "src/plugins/files/public/types.ts", - "deprecated": false, - "trackAdoption": false, - "returnComment": [], - "children": [ - { - "parentPluginId": "files", - "id": "def-public.FilesClient.listShares.$1", - "type": "CompoundType", - "tags": [], - "label": "args", - "description": [ - "- Get file share arguments" - ], - "signature": [ - "E[\"inputs\"][\"body\"] & E[\"inputs\"][\"params\"] & E[\"inputs\"][\"query\"] & { abortSignal?: AbortSignal | undefined; } & { kind: string; } & ExtraArgs" - ], - "path": "src/plugins/files/public/types.ts", - "deprecated": false, - "trackAdoption": false - } - ] + "returnComment": [] } ], "initialIsOpen": false @@ -664,7 +118,7 @@ "description": [ "\nA factory for creating a {@link ScopedFilesClient}" ], - "path": "src/plugins/files/public/types.ts", + "path": "src/plugins/files/common/files_client.ts", "deprecated": false, "trackAdoption": false, "children": [ @@ -679,16 +133,10 @@ ], "signature": [ "() => ", - { - "pluginId": "files", - "scope": "public", - "docId": "kibFilesPluginApi", - "section": "def-public.FilesClient", - "text": "FilesClient" - }, + "FilesClient", "" ], - "path": "src/plugins/files/public/types.ts", + "path": "src/plugins/files/common/files_client.ts", "deprecated": false, "trackAdoption": false, "children": [], @@ -705,16 +153,10 @@ ], "signature": [ "(fileKind: string) => ", - { - "pluginId": "files", - "scope": "public", - "docId": "kibFilesPluginApi", - "section": "def-public.ScopedFilesClient", - "text": "ScopedFilesClient" - }, + "ScopedFilesClient", "" ], - "path": "src/plugins/files/public/types.ts", + "path": "src/plugins/files/common/files_client.ts", "deprecated": false, "trackAdoption": false, "children": [ @@ -724,197 +166,19 @@ "type": "string", "tags": [], "label": "fileKind", - "description": [ - "- The {@link FileKind } to create a client for." - ], - "signature": [ - "string" - ], - "path": "src/plugins/files/public/types.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - } - ], - "initialIsOpen": false - }, - { - "parentPluginId": "files", - "id": "def-public.Props", - "type": "Interface", - "tags": [], - "label": "Props", - "description": [], - "signature": [ - { - "pluginId": "files", - "scope": "public", - "docId": "kibFilesPluginApi", - "section": "def-public.Props", - "text": "Props" - }, - "" - ], - "path": "src/plugins/files/public/components/file_picker/file_picker.tsx", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "files", - "id": "def-public.Props.kind", - "type": "Uncategorized", - "tags": [], - "label": "kind", - "description": [ - "\nThe file kind that was passed to the registry." - ], - "signature": [ - "Kind" - ], - "path": "src/plugins/files/public/components/file_picker/file_picker.tsx", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "files", - "id": "def-public.Props.onClose", - "type": "Function", - "tags": [], - "label": "onClose", - "description": [ - "\nWill be called when the modal is closed" - ], - "signature": [ - "() => void" - ], - "path": "src/plugins/files/public/components/file_picker/file_picker.tsx", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [] - }, - { - "parentPluginId": "files", - "id": "def-public.Props.onDone", - "type": "Function", - "tags": [], - "label": "onDone", - "description": [ - "\nWill be called after a user has a selected a set of files" - ], - "signature": [ - "(files: ", - { - "pluginId": "files", - "scope": "common", - "docId": "kibFilesPluginApi", - "section": "def-common.FileJSON", - "text": "FileJSON" - }, - "[]) => void" - ], - "path": "src/plugins/files/public/components/file_picker/file_picker.tsx", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "files", - "id": "def-public.Props.onDone.$1", - "type": "Array", - "tags": [], - "label": "files", - "description": [], - "signature": [ - { - "pluginId": "files", - "scope": "common", - "docId": "kibFilesPluginApi", - "section": "def-common.FileJSON", - "text": "FileJSON" - }, - "[]" - ], - "path": "src/plugins/files/public/components/file_picker/file_picker.tsx", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "files", - "id": "def-public.Props.onUpload", - "type": "Function", - "tags": [], - "label": "onUpload", - "description": [ - "\nWhen a user has successfully uploaded some files this callback will be called" - ], - "signature": [ - "((done: ", - "DoneNotification", - "[]) => void) | undefined" - ], - "path": "src/plugins/files/public/components/file_picker/file_picker.tsx", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "files", - "id": "def-public.Props.onUpload.$1", - "type": "Array", - "tags": [], - "label": "done", - "description": [], + "description": [ + "- The {@link FileKind } to create a client for." + ], "signature": [ - "DoneNotification", - "[]" + "string" ], - "path": "src/plugins/files/public/components/file_picker/file_picker.tsx", + "path": "src/plugins/files/common/files_client.ts", "deprecated": false, "trackAdoption": false, "isRequired": true } ], "returnComment": [] - }, - { - "parentPluginId": "files", - "id": "def-public.Props.pageSize", - "type": "number", - "tags": [], - "label": "pageSize", - "description": [ - "\nThe number of results to show per page." - ], - "signature": [ - "number | undefined" - ], - "path": "src/plugins/files/public/components/file_picker/file_picker.tsx", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "files", - "id": "def-public.Props.multiple", - "type": "CompoundType", - "tags": [ - "default" - ], - "label": "multiple", - "description": [ - "\nWhether you can select one or more files\n" - ], - "signature": [ - "boolean | undefined" - ], - "path": "src/plugins/files/public/components/file_picker/file_picker.tsx", - "deprecated": false, - "trackAdoption": false } ], "initialIsOpen": false @@ -930,63 +194,7 @@ "label": "FilesClientResponses", "description": [], "signature": [ - "{ create: { file: ", - { - "pluginId": "files", - "scope": "common", - "docId": "kibFilesPluginApi", - "section": "def-common.FileJSON", - "text": "FileJSON" - }, - "; }; delete: { ok: true; }; getById: { file: ", - { - "pluginId": "files", - "scope": "common", - "docId": "kibFilesPluginApi", - "section": "def-common.FileJSON", - "text": "FileJSON" - }, - "; }; list: { files: ", - { - "pluginId": "files", - "scope": "common", - "docId": "kibFilesPluginApi", - "section": "def-common.FileJSON", - "text": "FileJSON" - }, - "[]; total: number; }; update: { file: ", - { - "pluginId": "files", - "scope": "common", - "docId": "kibFilesPluginApi", - "section": "def-common.FileJSON", - "text": "FileJSON" - }, - "; }; upload: { ok: true; size: number; }; download: any; getDownloadHref: string; share: ", - { - "pluginId": "files", - "scope": "common", - "docId": "kibFilesPluginApi", - "section": "def-common.FileShareJSON", - "text": "FileShareJSON" - }, - " & { token: string; }; unshare: { ok: true; }; getShare: { share: ", - { - "pluginId": "files", - "scope": "common", - "docId": "kibFilesPluginApi", - "section": "def-common.FileShareJSON", - "text": "FileShareJSON" - }, - "; }; listShares: { shares: ", - { - "pluginId": "files", - "scope": "common", - "docId": "kibFilesPluginApi", - "section": "def-common.FileShareJSON", - "text": "FileShareJSON" - }, - "[]; }; getMetrics: ", + "{ getMetrics: ", { "pluginId": "files", "scope": "common", @@ -995,16 +203,20 @@ "text": "FilesMetrics" }, "; publicDownload: any; find: { files: ", - { - "pluginId": "files", - "scope": "common", - "docId": "kibFilesPluginApi", - "section": "def-common.FileJSON", - "text": "FileJSON" - }, - "[]; total: number; }; bulkDelete: Result; }" + "FileJSON", + "[]; total: number; }; bulkDelete: { succeeded: string[]; failed?: [id: string, reason: string][] | undefined; }; create: { file: ", + "FileJSON", + "; }; delete: { ok: true; }; getById: { file: ", + "FileJSON", + "; }; list: { files: ", + "FileJSON", + "[]; total: number; }; update: { file: ", + "FileJSON", + "; }; upload: { ok: true; size: number; }; download: any; getDownloadHref: string; share: any; unshare: { ok: true; }; getShare: { share: FileShareJSON; }; listShares: { shares: FileShareJSON[]; }; getFileKind: ", + "FileKind", + "; }" ], - "path": "src/plugins/files/public/types.ts", + "path": "src/plugins/files/common/files_client.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -1019,71 +231,7 @@ "\nA files client that is scoped to a specific {@link FileKind}.\n\nMore convenient if you want to re-use the same client for the same file kind\nand not specify the kind every time." ], "signature": [ - "{ create: (arg: Omit | undefined; alt?: string | undefined; mimeType?: string | undefined; } & { name: string; }> & { abortSignal?: AbortSignal | undefined; } & { kind: string; }, \"kind\">) => Promise<{ file: ", - { - "pluginId": "files", - "scope": "common", - "docId": "kibFilesPluginApi", - "section": "def-common.FileJSON", - "text": "FileJSON" - }, - "; }>; delete: (arg: Omit & { abortSignal?: AbortSignal | undefined; } & { kind: string; }, \"kind\">) => Promise<{ ok: true; }>; getById: (arg: Omit & { abortSignal?: AbortSignal | undefined; } & { kind: string; }, \"kind\">) => Promise<{ file: ", - { - "pluginId": "files", - "scope": "common", - "docId": "kibFilesPluginApi", - "section": "def-common.FileJSON", - "text": "FileJSON" - }, - "; }>; list: (arg?: Omit | undefined; extension?: string | string[] | undefined; } & {}> & Readonly<{ page?: number | undefined; perPage?: number | undefined; } & {}> & { abortSignal?: AbortSignal | undefined; } & { kind: string; }, \"kind\"> | undefined) => Promise<{ files: ", - { - "pluginId": "files", - "scope": "common", - "docId": "kibFilesPluginApi", - "section": "def-common.FileJSON", - "text": "FileJSON" - }, - "[]; total: number; }>; update: (arg: Omit | undefined; alt?: string | undefined; } & {}> & Readonly<{} & { id: string; }> & { abortSignal?: AbortSignal | undefined; } & { kind: string; }, \"kind\">) => Promise<{ file: ", - { - "pluginId": "files", - "scope": "common", - "docId": "kibFilesPluginApi", - "section": "def-common.FileJSON", - "text": "FileJSON" - }, - "; }>; upload: (arg: Omit & Readonly<{ selfDestructOnAbort?: boolean | undefined; } & {}> & { body: unknown; kind: string; abortSignal?: AbortSignal | undefined; contentType?: string | undefined; }, \"kind\">) => Promise<{ ok: true; size: number; }>; download: (arg: Omit & { abortSignal?: AbortSignal | undefined; } & { kind: string; }, \"kind\">) => Promise; getDownloadHref: (arg: Omit, \"id\" | \"fileKind\">, \"kind\">) => string; share: (arg: Omit & Readonly<{} & { fileId: string; }> & { abortSignal?: AbortSignal | undefined; } & { kind: string; }, \"kind\">) => Promise<", - { - "pluginId": "files", - "scope": "common", - "docId": "kibFilesPluginApi", - "section": "def-common.FileShareJSONWithToken", - "text": "FileShareJSONWithToken" - }, - ">; unshare: (arg: Omit & { abortSignal?: AbortSignal | undefined; } & { kind: string; }, \"kind\">) => Promise<{ ok: true; }>; getShare: (arg: Omit & { abortSignal?: AbortSignal | undefined; } & { kind: string; }, \"kind\">) => Promise<{ share: ", - { - "pluginId": "files", - "scope": "common", - "docId": "kibFilesPluginApi", - "section": "def-common.FileShareJSON", - "text": "FileShareJSON" - }, - "; }>; listShares: (arg: Omit & { abortSignal?: AbortSignal | undefined; } & { kind: string; }, \"kind\">) => Promise<{ shares: ", - { - "pluginId": "files", - "scope": "common", - "docId": "kibFilesPluginApi", - "section": "def-common.FileShareJSON", - "text": "FileShareJSON" - }, - "[]; }>; getMetrics: (arg: Omit) => Promise<", + "{ getMetrics: (arg: Omit) => Promise<", { "pluginId": "files", "scope": "common", @@ -1091,39 +239,55 @@ "section": "def-common.FilesMetrics", "text": "FilesMetrics" }, - ">; publicDownload: (arg: Omit & Readonly<{} & { token: string; }> & { abortSignal?: AbortSignal | undefined; }, \"kind\">) => Promise; find: (arg: Omit | undefined; extension?: string | string[] | undefined; kind?: string | string[] | undefined; } & {}> & Readonly<{ page?: number | undefined; perPage?: number | undefined; } & {}> & { abortSignal?: AbortSignal | undefined; }, \"kind\">) => Promise<{ files: ", - { - "pluginId": "files", - "scope": "common", - "docId": "kibFilesPluginApi", - "section": "def-common.FileJSON", - "text": "FileJSON" - }, - "[]; total: number; }>; bulkDelete: (arg: Omit & { abortSignal?: AbortSignal | undefined; }, \"kind\">) => Promise; }" - ], - "path": "src/plugins/files/public/types.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - }, - { - "parentPluginId": "files", - "id": "def-public.UploadFileProps", - "type": "Type", - "tags": [], - "label": "UploadFileProps", - "description": [], - "signature": [ - { - "pluginId": "files", - "scope": "public", - "docId": "kibFilesPluginApi", - "section": "def-public.Props", - "text": "Props" - }, - " & { lazyLoadFallback?: React.ReactNode; }" + ">; publicDownload: (arg: Omit<{ token: string; fileName?: string | undefined; }, \"kind\">) => any; find: (arg: Omit<{ kind?: string | string[] | undefined; status?: string | string[] | undefined; extension?: string | string[] | undefined; name?: string | string[] | undefined; meta?: M | undefined; } & ", + "Pagination", + " & ", + "Abortable", + ", \"kind\">) => Promise<{ files: ", + "FileJSON", + "[]; total: number; }>; bulkDelete: (arg: Omit<{ ids: string[]; } & ", + "Abortable", + ", \"kind\">) => Promise<{ succeeded: string[]; failed?: [id: string, reason: string][] | undefined; }>; create: (arg: Omit<{ name: string; meta?: M | undefined; alt?: string | undefined; mimeType?: string | undefined; kind: string; } & ", + "Abortable", + ", \"kind\">) => Promise<{ file: ", + "FileJSON", + "; }>; delete: (arg: Omit<{ id: string; kind: string; } & ", + "Abortable", + ", \"kind\">) => Promise<{ ok: true; }>; getById: (arg: Omit<{ id: string; kind: string; } & ", + "Abortable", + ", \"kind\">) => Promise<{ file: ", + "FileJSON", + "; }>; list: (arg?: Omit<{ kind: string; status?: string | string[] | undefined; extension?: string | string[] | undefined; name?: string | string[] | undefined; meta?: M | undefined; } & ", + "Pagination", + " & ", + "Abortable", + ", \"kind\"> | undefined) => Promise<{ files: ", + "FileJSON", + "[]; total: number; }>; update: (arg: Omit<{ id: string; kind: string; name?: string | undefined; meta?: M | undefined; alt?: string | undefined; } & ", + "Abortable", + ", \"kind\">) => Promise<{ file: ", + "FileJSON", + "; }>; upload: (arg: Omit<{ id: string; body: unknown; kind: string; abortSignal?: AbortSignal | undefined; contentType?: string | undefined; selfDestructOnAbort?: boolean | undefined; } & ", + "Abortable", + ", \"kind\">) => Promise<{ ok: true; size: number; }>; download: (arg: Omit<{ fileName?: string | undefined; id: string; kind: string; } & ", + "Abortable", + ", \"kind\">) => Promise; getDownloadHref: (arg: Omit, \"id\" | \"fileKind\">, \"kind\">) => string; share: (arg: Omit<{ name?: string | undefined; validUntil?: number | undefined; fileId: string; kind: string; } & ", + "Abortable", + ", \"kind\">) => Promise; unshare: (arg: Omit<{ id: string; kind: string; } & ", + "Abortable", + ", \"kind\">) => Promise<{ ok: true; }>; getShare: (arg: Omit<{ id: string; kind: string; } & ", + "Abortable", + ", \"kind\">) => Promise<{ share: FileShareJSON; }>; listShares: (arg: Omit<{ forFileId?: string | undefined; kind: string; } & ", + "Pagination", + " & ", + "Abortable", + ", \"kind\">) => Promise<{ shares: FileShareJSON[]; }>; getFileKind: (arg: Omit) => ", + "FileKind", + "; }" ], - "path": "src/plugins/files/public/components/upload_file/index.tsx", + "path": "src/plugins/files/common/files_client.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -1427,13 +591,7 @@ "\nA factory for creating an {@link FilesClient} instance. This requires a\nregistered {@link FileKind}.\n" ], "signature": [ - { - "pluginId": "files", - "scope": "public", - "docId": "kibFilesPluginApi", - "section": "def-public.FilesClientFactory", - "text": "FilesClientFactory" - } + "FilesClientFactory" ], "path": "src/plugins/files/public/plugin.ts", "deprecated": false, @@ -1456,13 +614,7 @@ ], "signature": [ "(fileKind: ", - { - "pluginId": "files", - "scope": "common", - "docId": "kibFilesPluginApi", - "section": "def-common.FileKind", - "text": "FileKind" - }, + "FileKind", ") => void" ], "path": "src/plugins/files/public/plugin.ts", @@ -1479,13 +631,7 @@ "- the file kind to register" ], "signature": [ - { - "pluginId": "files", - "scope": "common", - "docId": "kibFilesPluginApi", - "section": "def-common.FileKind", - "text": "FileKind" - } + "FileKind" ], "path": "src/plugins/files/public/plugin.ts", "deprecated": false, @@ -1508,13 +654,7 @@ "description": [], "signature": [ "{ filesClientFactory: ", - { - "pluginId": "files", - "scope": "public", - "docId": "kibFilesPluginApi", - "section": "def-public.FilesClientFactory", - "text": "FilesClientFactory" - }, + "FilesClientFactory", "; }" ], "path": "src/plugins/files/public/plugin.ts", @@ -3649,21 +2789,9 @@ ], "signature": [ "Required> & ", - { - "pluginId": "files", - "scope": "common", - "docId": "kibFilesPluginApi", - "section": "def-common.BaseFileMetadata", - "text": "BaseFileMetadata" - }, + "BaseFileMetadata", " & { FileKind: string; Meta?: M | undefined; }" ], "path": "src/plugins/files/server/file_client/file_metadata_client/file_metadata_client.ts", @@ -4382,13 +3510,7 @@ "text": "FindFileArgs" }, ") => Promise<{ files: ", - { - "pluginId": "files", - "scope": "common", - "docId": "kibFilesPluginApi", - "section": "def-common.FileJSON", - "text": "FileJSON" - }, + "FileJSON", "[]; total: number; }>" ], "path": "src/plugins/files/server/file_service/file_service.ts", @@ -5246,13 +4368,7 @@ ], "signature": [ "{ name?: string | undefined; created?: string | undefined; Status?: \"AWAITING_UPLOAD\" | \"UPLOADING\" | \"READY\" | \"UPLOAD_ERROR\" | \"DELETED\" | undefined; Updated?: string | undefined; mime_type?: string | undefined; size?: number | undefined; hash?: { [hashName: string]: string | undefined; md5?: string | undefined; sha1?: string | undefined; sha256?: string | undefined; sha384?: string | undefined; sha512?: string | undefined; ssdeep?: string | undefined; tlsh?: string | undefined; } | undefined; user?: { name?: string | undefined; id?: string | undefined; } | undefined; extension?: string | undefined; Alt?: string | undefined; ChunkSize?: number | undefined; Compression?: ", - { - "pluginId": "files", - "scope": "common", - "docId": "kibFilesPluginApi", - "section": "def-common.FileCompression", - "text": "FileCompression" - }, + "FileCompression", " | undefined; FileKind?: string | undefined; Meta?: M | undefined; }" ], "path": "src/plugins/files/server/file_client/file_metadata_client/file_metadata_client.ts", @@ -5417,13 +4533,7 @@ ], "signature": [ "(fileKind: ", - { - "pluginId": "files", - "scope": "common", - "docId": "kibFilesPluginApi", - "section": "def-common.FileKind", - "text": "FileKind" - }, + "FileKind", ") => void" ], "path": "src/plugins/files/server/types.ts", @@ -5441,13 +4551,7 @@ "- the file kind to register" ], "signature": [ - { - "pluginId": "files", - "scope": "common", - "docId": "kibFilesPluginApi", - "section": "def-common.FileKind", - "text": "FileKind" - } + "FileKind" ], "path": "src/plugins/files/server/types.ts", "deprecated": false, @@ -5586,13 +4690,7 @@ "\nFile metadata in camelCase form." ], "signature": [ - { - "pluginId": "files", - "scope": "common", - "docId": "kibFilesPluginApi", - "section": "def-common.FileJSON", - "text": "FileJSON" - }, + "FileJSON", "" ], "path": "src/plugins/files/common/types.ts", @@ -5913,13 +5011,7 @@ ], "signature": [ "() => ", - { - "pluginId": "files", - "scope": "common", - "docId": "kibFilesPluginApi", - "section": "def-common.FileJSON", - "text": "FileJSON" - }, + "FileJSON", "" ], "path": "src/plugins/files/common/types.ts", @@ -5941,16 +5033,10 @@ "\nAttributes of a file that represent a serialised version of the file." ], "signature": [ - { - "pluginId": "files", - "scope": "common", - "docId": "kibFilesPluginApi", - "section": "def-common.FileJSON", - "text": "FileJSON" - }, + "FileJSON", "" ], - "path": "src/plugins/files/common/types.ts", + "path": "packages/shared-ux/file/types/index.d.ts", "deprecated": false, "trackAdoption": false, "children": [ @@ -5963,7 +5049,7 @@ "description": [ "\nUnique file ID." ], - "path": "src/plugins/files/common/types.ts", + "path": "packages/shared-ux/file/types/index.d.ts", "deprecated": false, "trackAdoption": false }, @@ -5976,7 +5062,7 @@ "description": [ "\nISO string of when this file was created" ], - "path": "src/plugins/files/common/types.ts", + "path": "packages/shared-ux/file/types/index.d.ts", "deprecated": false, "trackAdoption": false }, @@ -5989,7 +5075,7 @@ "description": [ "\nISO string of when the file was updated" ], - "path": "src/plugins/files/common/types.ts", + "path": "packages/shared-ux/file/types/index.d.ts", "deprecated": false, "trackAdoption": false }, @@ -6004,7 +5090,7 @@ "description": [ "\nFile name.\n" ], - "path": "src/plugins/files/common/types.ts", + "path": "packages/shared-ux/file/types/index.d.ts", "deprecated": false, "trackAdoption": false }, @@ -6020,7 +5106,7 @@ "signature": [ "string | undefined" ], - "path": "src/plugins/files/common/types.ts", + "path": "packages/shared-ux/file/types/index.d.ts", "deprecated": false, "trackAdoption": false }, @@ -6036,7 +5122,7 @@ "signature": [ "number | undefined" ], - "path": "src/plugins/files/common/types.ts", + "path": "packages/shared-ux/file/types/index.d.ts", "deprecated": false, "trackAdoption": false }, @@ -6054,7 +5140,7 @@ "signature": [ "string | undefined" ], - "path": "src/plugins/files/common/types.ts", + "path": "packages/shared-ux/file/types/index.d.ts", "deprecated": false, "trackAdoption": false }, @@ -6070,7 +5156,7 @@ "signature": [ "Meta | undefined" ], - "path": "src/plugins/files/common/types.ts", + "path": "packages/shared-ux/file/types/index.d.ts", "deprecated": false, "trackAdoption": false }, @@ -6086,7 +5172,7 @@ "signature": [ "string | undefined" ], - "path": "src/plugins/files/common/types.ts", + "path": "packages/shared-ux/file/types/index.d.ts", "deprecated": false, "trackAdoption": false }, @@ -6101,7 +5187,7 @@ "description": [ "\nA unique kind that governs various aspects of the file. A consumer of the\nfiles service must register a file kind and link their files to a specific\nkind.\n" ], - "path": "src/plugins/files/common/types.ts", + "path": "packages/shared-ux/file/types/index.d.ts", "deprecated": false, "trackAdoption": false }, @@ -6117,7 +5203,7 @@ "signature": [ "\"AWAITING_UPLOAD\" | \"UPLOADING\" | \"READY\" | \"UPLOAD_ERROR\" | \"DELETED\"" ], - "path": "src/plugins/files/common/types.ts", + "path": "packages/shared-ux/file/types/index.d.ts", "deprecated": false, "trackAdoption": false }, @@ -6133,7 +5219,7 @@ "signature": [ "{ name?: string | undefined; id?: string | undefined; } | undefined" ], - "path": "src/plugins/files/common/types.ts", + "path": "packages/shared-ux/file/types/index.d.ts", "deprecated": false, "trackAdoption": false } @@ -6144,14 +5230,10 @@ "parentPluginId": "files", "id": "def-common.FileKind", "type": "Interface", - "tags": [ - "note" - ], + "tags": [], "label": "FileKind", - "description": [ - "\nA descriptor of meta values associated with a set or \"kind\" of files.\n" - ], - "path": "src/plugins/files/common/types.ts", + "description": [], + "path": "packages/shared-ux/file/types/index.d.ts", "deprecated": false, "trackAdoption": false, "children": [ @@ -6164,7 +5246,7 @@ "description": [ "\nUnique file kind ID" ], - "path": "src/plugins/files/common/types.ts", + "path": "packages/shared-ux/file/types/index.d.ts", "deprecated": false, "trackAdoption": false }, @@ -6182,7 +5264,7 @@ "signature": [ "number | undefined" ], - "path": "src/plugins/files/common/types.ts", + "path": "packages/shared-ux/file/types/index.d.ts", "deprecated": false, "trackAdoption": false }, @@ -6200,30 +5282,23 @@ "signature": [ "string[] | undefined" ], - "path": "src/plugins/files/common/types.ts", + "path": "packages/shared-ux/file/types/index.d.ts", "deprecated": false, "trackAdoption": false }, { "parentPluginId": "files", "id": "def-common.FileKind.blobStoreSettings", - "type": "Object", + "type": "Any", "tags": [], "label": "blobStoreSettings", "description": [ "\nBlob store specific settings that enable configuration of storage\ndetails." ], "signature": [ - { - "pluginId": "files", - "scope": "common", - "docId": "kibFilesPluginApi", - "section": "def-common.BlobStorageSettings", - "text": "BlobStorageSettings" - }, - " | undefined" + "any" ], - "path": "src/plugins/files/common/types.ts", + "path": "packages/shared-ux/file/types/index.d.ts", "deprecated": false, "trackAdoption": false }, @@ -6239,9 +5314,9 @@ "\nSpecify which HTTP routes to create for the file kind.\n\nYou can always create your own HTTP routes for working with files but\nthis interface allows you to expose basic CRUD operations, upload, download\nand sharing of files over a RESTful-like interface.\n" ], "signature": [ - "{ create?: HttpEndpointDefinition | undefined; update?: HttpEndpointDefinition | undefined; delete?: HttpEndpointDefinition | undefined; getById?: HttpEndpointDefinition | undefined; list?: HttpEndpointDefinition | undefined; download?: HttpEndpointDefinition | undefined; share?: HttpEndpointDefinition | undefined; }" + "{ create?: any; update?: any; delete?: any; getById?: any; list?: any; download?: any; share?: any; }" ], - "path": "src/plugins/files/common/types.ts", + "path": "packages/shared-ux/file/types/index.d.ts", "deprecated": false, "trackAdoption": false } @@ -6537,24 +5612,12 @@ ], "signature": [ "{ name?: string | undefined; mime_type?: string | undefined; created?: string | undefined; size?: number | undefined; hash?: { [hashName: string]: string | undefined; md5?: string | undefined; sha1?: string | undefined; sha256?: string | undefined; sha384?: string | undefined; sha512?: string | undefined; ssdeep?: string | undefined; tlsh?: string | undefined; } | undefined; user?: { name?: string | undefined; id?: string | undefined; } | undefined; extension?: string | undefined; Alt?: string | undefined; Updated?: string | undefined; Status?: ", - { - "pluginId": "files", - "scope": "common", - "docId": "kibFilesPluginApi", - "section": "def-common.FileStatus", - "text": "FileStatus" - }, + "FileStatus", " | undefined; ChunkSize?: number | undefined; Compression?: ", - { - "pluginId": "files", - "scope": "common", - "docId": "kibFilesPluginApi", - "section": "def-common.FileCompression", - "text": "FileCompression" - }, + "FileCompression", " | undefined; }" ], - "path": "src/plugins/files/common/types.ts", + "path": "packages/shared-ux/file/types/index.d.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -6605,7 +5668,7 @@ "signature": [ "\"none\" | \"br\" | \"gzip\" | \"deflate\"" ], - "path": "src/plugins/files/common/types.ts", + "path": "packages/shared-ux/file/types/index.d.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -6621,24 +5684,12 @@ ], "signature": [ "Required> & ", - { - "pluginId": "files", - "scope": "common", - "docId": "kibFilesPluginApi", - "section": "def-common.BaseFileMetadata", - "text": "BaseFileMetadata" - }, + "BaseFileMetadata", " & { FileKind: string; Meta?: Meta | undefined; }" ], - "path": "src/plugins/files/common/types.ts", + "path": "packages/shared-ux/file/types/index.d.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -6661,13 +5712,7 @@ "text": "SavedObject" }, "<", - { - "pluginId": "files", - "scope": "common", - "docId": "kibFilesPluginApi", - "section": "def-common.FileMetadata", - "text": "FileMetadata" - }, + "FileMetadata", ">" ], "path": "src/plugins/files/common/types.ts", @@ -6724,13 +5769,11 @@ "type": "Type", "tags": [], "label": "FileStatus", - "description": [ - "\nStatus of a file.\n\nAWAITING_UPLOAD - A file object has been created but does not have any contents.\nUPLOADING - File contents are being uploaded.\nREADY - File contents have been uploaded and are ready for to be downloaded.\nUPLOAD_ERROR - An attempt was made to upload file contents but failed.\nDELETED - The file contents have been or are being deleted." - ], + "description": [], "signature": [ "\"AWAITING_UPLOAD\" | \"UPLOADING\" | \"READY\" | \"UPLOAD_ERROR\" | \"DELETED\"" ], - "path": "src/plugins/files/common/types.ts", + "path": "packages/shared-ux/file/types/index.d.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false diff --git a/api_docs/files.mdx b/api_docs/files.mdx index 69a05a4001989..4e63b994fb9d2 100644 --- a/api_docs/files.mdx +++ b/api_docs/files.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/files title: "files" image: https://source.unsplash.com/400x175/?github description: API docs for the files plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'files'] --- import filesObj from './files.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-app-services](https://github.com/orgs/elastic/teams/tea | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 287 | 0 | 50 | 3 | +| 252 | 1 | 45 | 5 | ## Client @@ -34,9 +34,6 @@ Contact [@elastic/kibana-app-services](https://github.com/orgs/elastic/teams/tea ### Objects -### Functions - - ### Interfaces diff --git a/api_docs/files_management.mdx b/api_docs/files_management.mdx index 78ddf608f4bf0..334f957e480d1 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: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'filesManagement'] --- import filesManagementObj from './files_management.devdocs.json'; diff --git a/api_docs/fleet.devdocs.json b/api_docs/fleet.devdocs.json index 2a3246e0b2b07..ce10a6d3a887a 100644 --- a/api_docs/fleet.devdocs.json +++ b/api_docs/fleet.devdocs.json @@ -9058,7 +9058,7 @@ "label": "status", "description": [], "signature": [ - "\"active\" | \"inactive\"" + "\"inactive\" | \"active\"" ], "path": "x-pack/plugins/fleet/common/types/models/agent_policy.ts", "deprecated": false, @@ -10647,7 +10647,7 @@ "label": "agent", "description": [], "signature": [ - "{ monitoring: { namespace?: string | undefined; use_output?: string | undefined; enabled: boolean; metrics: boolean; logs: boolean; }; download: { source_uri: string; }; } | undefined" + "{ monitoring: { namespace?: string | undefined; use_output?: string | undefined; enabled: boolean; metrics: boolean; logs: boolean; }; download: { sourceURI: string; }; } | undefined" ], "path": "x-pack/plugins/fleet/common/types/models/agent_policy.ts", "deprecated": false, @@ -15149,6 +15149,21 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "fleet", + "id": "def-common.FLEET_CLOUD_SECURITY_POSTURE_KSPM_POLICY_TEMPLATE", + "type": "string", + "tags": [], + "label": "FLEET_CLOUD_SECURITY_POSTURE_KSPM_POLICY_TEMPLATE", + "description": [], + "signature": [ + "\"kspm\"" + ], + "path": "x-pack/plugins/fleet/common/constants/epm.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "fleet", "id": "def-common.FLEET_CLOUD_SECURITY_POSTURE_PACKAGE", @@ -17629,6 +17644,22 @@ "trackAdoption": false, "children": [], "returnComment": [] + }, + { + "parentPluginId": "fleet", + "id": "def-common.appRoutesService.postHealthCheckPath", + "type": "Function", + "tags": [], + "label": "postHealthCheckPath", + "description": [], + "signature": [ + "() => string" + ], + "path": "x-pack/plugins/fleet/common/services/routes.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] } ], "initialIsOpen": false diff --git a/api_docs/fleet.mdx b/api_docs/fleet.mdx index d328e6d2e8ccb..1b92c59893390 100644 --- a/api_docs/fleet.mdx +++ b/api_docs/fleet.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/fleet title: "fleet" image: https://source.unsplash.com/400x175/?github description: API docs for the fleet plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fleet'] --- import fleetObj from './fleet.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Fleet](https://github.com/orgs/elastic/teams/fleet) for questions regar | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 1025 | 3 | 920 | 19 | +| 1027 | 3 | 922 | 19 | ## Client diff --git a/api_docs/global_search.mdx b/api_docs/global_search.mdx index ea1b184e723d5..9ab3b37ee0964 100644 --- a/api_docs/global_search.mdx +++ b/api_docs/global_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/globalSearch title: "globalSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the globalSearch plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'globalSearch'] --- import globalSearchObj from './global_search.devdocs.json'; diff --git a/api_docs/guided_onboarding.devdocs.json b/api_docs/guided_onboarding.devdocs.json index 922e9e6561fee..526cf2cbe6f8e 100644 --- a/api_docs/guided_onboarding.devdocs.json +++ b/api_docs/guided_onboarding.devdocs.json @@ -87,7 +87,13 @@ "() => ", "Observable", "<", - "PluginState", + { + "pluginId": "guidedOnboarding", + "scope": "common", + "docId": "kibGuidedOnboardingPluginApi", + "section": "def-common.PluginState", + "text": "PluginState" + }, " | undefined>" ], "path": "src/plugins/guided_onboarding/public/types.ts", @@ -129,7 +135,13 @@ "description": [], "signature": [ "(state: { status?: ", - "PluginStatus", + { + "pluginId": "guidedOnboarding", + "scope": "common", + "docId": "kibGuidedOnboardingPluginApi", + "section": "def-common.PluginStatus", + "text": "PluginStatus" + }, " | undefined; guide?: ", { "pluginId": "@kbn/guided-onboarding", @@ -139,7 +151,13 @@ "text": "GuideState" }, " | undefined; }, panelState: boolean) => Promise<{ pluginState: ", - "PluginState", + { + "pluginId": "guidedOnboarding", + "scope": "common", + "docId": "kibGuidedOnboardingPluginApi", + "section": "def-common.PluginState", + "text": "PluginState" + }, "; } | undefined>" ], "path": "src/plugins/guided_onboarding/public/types.ts", @@ -165,7 +183,13 @@ "label": "status", "description": [], "signature": [ - "PluginStatus", + { + "pluginId": "guidedOnboarding", + "scope": "common", + "docId": "kibGuidedOnboardingPluginApi", + "section": "def-common.PluginStatus", + "text": "PluginStatus" + }, " | undefined" ], "path": "src/plugins/guided_onboarding/public/types.ts", @@ -238,7 +262,13 @@ "text": "GuideState" }, " | undefined) => Promise<{ pluginState: ", - "PluginState", + { + "pluginId": "guidedOnboarding", + "scope": "common", + "docId": "kibGuidedOnboardingPluginApi", + "section": "def-common.PluginState", + "text": "PluginState" + }, "; } | undefined>" ], "path": "src/plugins/guided_onboarding/public/types.ts", @@ -308,7 +338,13 @@ "text": "GuideState" }, ") => Promise<{ pluginState: ", - "PluginState", + { + "pluginId": "guidedOnboarding", + "scope": "common", + "docId": "kibGuidedOnboardingPluginApi", + "section": "def-common.PluginState", + "text": "PluginState" + }, "; } | undefined>" ], "path": "src/plugins/guided_onboarding/public/types.ts", @@ -356,7 +392,13 @@ "text": "GuideId" }, ") => Promise<{ pluginState: ", - "PluginState", + { + "pluginId": "guidedOnboarding", + "scope": "common", + "docId": "kibGuidedOnboardingPluginApi", + "section": "def-common.PluginState", + "text": "PluginState" + }, "; } | undefined>" ], "path": "src/plugins/guided_onboarding/public/types.ts", @@ -489,7 +531,13 @@ "text": "GuideStepIds" }, ") => Promise<{ pluginState: ", - "PluginState", + { + "pluginId": "guidedOnboarding", + "scope": "common", + "docId": "kibGuidedOnboardingPluginApi", + "section": "def-common.PluginState", + "text": "PluginState" + }, "; } | undefined>" ], "path": "src/plugins/guided_onboarding/public/types.ts", @@ -566,7 +614,13 @@ "text": "GuideStepIds" }, ") => Promise<{ pluginState: ", - "PluginState", + { + "pluginId": "guidedOnboarding", + "scope": "common", + "docId": "kibGuidedOnboardingPluginApi", + "section": "def-common.PluginState", + "text": "PluginState" + }, "; } | undefined>" ], "path": "src/plugins/guided_onboarding/public/types.ts", @@ -661,7 +715,13 @@ "description": [], "signature": [ "(integration?: string | undefined) => Promise<{ pluginState: ", - "PluginState", + { + "pluginId": "guidedOnboarding", + "scope": "common", + "docId": "kibGuidedOnboardingPluginApi", + "section": "def-common.PluginState", + "text": "PluginState" + }, "; } | undefined>" ], "path": "src/plugins/guided_onboarding/public/types.ts", @@ -695,7 +755,13 @@ "description": [], "signature": [ "() => Promise<{ pluginState: ", - "PluginState", + { + "pluginId": "guidedOnboarding", + "scope": "common", + "docId": "kibGuidedOnboardingPluginApi", + "section": "def-common.PluginState", + "text": "PluginState" + }, "; } | undefined>" ], "path": "src/plugins/guided_onboarding/public/types.ts", @@ -718,85 +784,68 @@ "path": "src/plugins/guided_onboarding/public/types.ts", "deprecated": false, "trackAdoption": false - } - ], - "initialIsOpen": false - } - ], - "enums": [], - "misc": [], - "objects": [ - { - "parentPluginId": "guidedOnboarding", - "id": "def-public.guidesConfig", - "type": "Object", - "tags": [], - "label": "guidesConfig", - "description": [], - "path": "src/plugins/guided_onboarding/public/constants/guides_config/index.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "guidedOnboarding", - "id": "def-public.guidesConfig.security", - "type": "Object", - "tags": [], - "label": "security", - "description": [], - "signature": [ - "GuideConfig" - ], - "path": "src/plugins/guided_onboarding/public/constants/guides_config/index.ts", - "deprecated": false, - "trackAdoption": false }, { "parentPluginId": "guidedOnboarding", - "id": "def-public.guidesConfig.observability", - "type": "Object", - "tags": [], - "label": "observability", - "description": [], - "signature": [ - "GuideConfig" - ], - "path": "src/plugins/guided_onboarding/public/constants/guides_config/index.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "guidedOnboarding", - "id": "def-public.guidesConfig.search", - "type": "Object", + "id": "def-public.GuidedOnboardingApi.getGuideConfig", + "type": "Function", "tags": [], - "label": "search", + "label": "getGuideConfig", "description": [], "signature": [ - "GuideConfig" + "(guideId: ", + { + "pluginId": "@kbn/guided-onboarding", + "scope": "common", + "docId": "kibKbnGuidedOnboardingPluginApi", + "section": "def-common.GuideId", + "text": "GuideId" + }, + ") => Promise<", + { + "pluginId": "guidedOnboarding", + "scope": "common", + "docId": "kibGuidedOnboardingPluginApi", + "section": "def-common.GuideConfig", + "text": "GuideConfig" + }, + " | undefined>" ], - "path": "src/plugins/guided_onboarding/public/constants/guides_config/index.ts", + "path": "src/plugins/guided_onboarding/public/types.ts", "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "guidedOnboarding", - "id": "def-public.guidesConfig.testGuide", - "type": "Object", - "tags": [], - "label": "testGuide", - "description": [], - "signature": [ - "GuideConfig" + "trackAdoption": false, + "children": [ + { + "parentPluginId": "guidedOnboarding", + "id": "def-public.GuidedOnboardingApi.getGuideConfig.$1", + "type": "CompoundType", + "tags": [], + "label": "guideId", + "description": [], + "signature": [ + { + "pluginId": "@kbn/guided-onboarding", + "scope": "common", + "docId": "kibKbnGuidedOnboardingPluginApi", + "section": "def-common.GuideId", + "text": "GuideId" + } + ], + "path": "src/plugins/guided_onboarding/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } ], - "path": "src/plugins/guided_onboarding/public/constants/guides_config/index.ts", - "deprecated": false, - "trackAdoption": false + "returnComment": [] } ], "initialIsOpen": false } ], + "enums": [], + "misc": [], + "objects": [], "setup": { "parentPluginId": "guidedOnboarding", "id": "def-public.GuidedOnboardingPluginSetup", @@ -887,9 +936,538 @@ "common": { "classes": [], "functions": [], - "interfaces": [], + "interfaces": [ + { + "parentPluginId": "guidedOnboarding", + "id": "def-common.GuideConfig", + "type": "Interface", + "tags": [], + "label": "GuideConfig", + "description": [], + "path": "src/plugins/guided_onboarding/common/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "guidedOnboarding", + "id": "def-common.GuideConfig.title", + "type": "string", + "tags": [], + "label": "title", + "description": [], + "path": "src/plugins/guided_onboarding/common/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "guidedOnboarding", + "id": "def-common.GuideConfig.description", + "type": "string", + "tags": [], + "label": "description", + "description": [], + "path": "src/plugins/guided_onboarding/common/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "guidedOnboarding", + "id": "def-common.GuideConfig.guideName", + "type": "string", + "tags": [], + "label": "guideName", + "description": [], + "path": "src/plugins/guided_onboarding/common/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "guidedOnboarding", + "id": "def-common.GuideConfig.docs", + "type": "Object", + "tags": [], + "label": "docs", + "description": [], + "signature": [ + "{ text: string; url: string; } | undefined" + ], + "path": "src/plugins/guided_onboarding/common/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "guidedOnboarding", + "id": "def-common.GuideConfig.completedGuideRedirectLocation", + "type": "Object", + "tags": [], + "label": "completedGuideRedirectLocation", + "description": [], + "signature": [ + "{ appID: string; path: string; } | undefined" + ], + "path": "src/plugins/guided_onboarding/common/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "guidedOnboarding", + "id": "def-common.GuideConfig.steps", + "type": "Array", + "tags": [], + "label": "steps", + "description": [], + "signature": [ + { + "pluginId": "guidedOnboarding", + "scope": "common", + "docId": "kibGuidedOnboardingPluginApi", + "section": "def-common.StepConfig", + "text": "StepConfig" + }, + "[]" + ], + "path": "src/plugins/guided_onboarding/common/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "guidedOnboarding", + "id": "def-common.PluginState", + "type": "Interface", + "tags": [], + "label": "PluginState", + "description": [], + "path": "src/plugins/guided_onboarding/common/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "guidedOnboarding", + "id": "def-common.PluginState.status", + "type": "CompoundType", + "tags": [], + "label": "status", + "description": [], + "signature": [ + "\"error\" | \"complete\" | \"not_started\" | \"in_progress\" | \"quit\" | \"skipped\"" + ], + "path": "src/plugins/guided_onboarding/common/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "guidedOnboarding", + "id": "def-common.PluginState.isActivePeriod", + "type": "boolean", + "tags": [], + "label": "isActivePeriod", + "description": [], + "path": "src/plugins/guided_onboarding/common/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "guidedOnboarding", + "id": "def-common.PluginState.activeGuide", + "type": "Object", + "tags": [], + "label": "activeGuide", + "description": [], + "signature": [ + { + "pluginId": "@kbn/guided-onboarding", + "scope": "common", + "docId": "kibKbnGuidedOnboardingPluginApi", + "section": "def-common.GuideState", + "text": "GuideState" + }, + " | undefined" + ], + "path": "src/plugins/guided_onboarding/common/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "guidedOnboarding", + "id": "def-common.StepConfig", + "type": "Interface", + "tags": [], + "label": "StepConfig", + "description": [], + "path": "src/plugins/guided_onboarding/common/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "guidedOnboarding", + "id": "def-common.StepConfig.id", + "type": "CompoundType", + "tags": [], + "label": "id", + "description": [], + "signature": [ + "\"add_data\" | \"view_dashboard\" | \"tour_observability\" | \"rules\" | \"alertsCases\" | \"search_experience\" | \"step1\" | \"step2\" | \"step3\"" + ], + "path": "src/plugins/guided_onboarding/common/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "guidedOnboarding", + "id": "def-common.StepConfig.title", + "type": "string", + "tags": [], + "label": "title", + "description": [], + "path": "src/plugins/guided_onboarding/common/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "guidedOnboarding", + "id": "def-common.StepConfig.description", + "type": "string", + "tags": [], + "label": "description", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "src/plugins/guided_onboarding/common/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "guidedOnboarding", + "id": "def-common.StepConfig.descriptionList", + "type": "Array", + "tags": [], + "label": "descriptionList", + "description": [], + "signature": [ + "React.ReactNode[] | undefined" + ], + "path": "src/plugins/guided_onboarding/common/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "guidedOnboarding", + "id": "def-common.StepConfig.location", + "type": "Object", + "tags": [], + "label": "location", + "description": [], + "signature": [ + "{ appID: string; path: string; } | undefined" + ], + "path": "src/plugins/guided_onboarding/common/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "guidedOnboarding", + "id": "def-common.StepConfig.status", + "type": "CompoundType", + "tags": [], + "label": "status", + "description": [], + "signature": [ + { + "pluginId": "@kbn/guided-onboarding", + "scope": "common", + "docId": "kibKbnGuidedOnboardingPluginApi", + "section": "def-common.StepStatus", + "text": "StepStatus" + }, + " | undefined" + ], + "path": "src/plugins/guided_onboarding/common/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "guidedOnboarding", + "id": "def-common.StepConfig.integration", + "type": "string", + "tags": [], + "label": "integration", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "src/plugins/guided_onboarding/common/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "guidedOnboarding", + "id": "def-common.StepConfig.manualCompletion", + "type": "Object", + "tags": [], + "label": "manualCompletion", + "description": [], + "signature": [ + "{ title: string; description: string; readyToCompleteOnNavigation?: boolean | undefined; } | undefined" + ], + "path": "src/plugins/guided_onboarding/common/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + } + ], "enums": [], - "misc": [], - "objects": [] + "misc": [ + { + "parentPluginId": "guidedOnboarding", + "id": "def-common.API_BASE_PATH", + "type": "string", + "tags": [], + "label": "API_BASE_PATH", + "description": [], + "signature": [ + "\"/api/guided_onboarding\"" + ], + "path": "src/plugins/guided_onboarding/common/constants.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "guidedOnboarding", + "id": "def-common.GuidesConfig", + "type": "Type", + "tags": [], + "label": "GuidesConfig", + "description": [], + "signature": [ + "{ search: ", + { + "pluginId": "guidedOnboarding", + "scope": "common", + "docId": "kibGuidedOnboardingPluginApi", + "section": "def-common.GuideConfig", + "text": "GuideConfig" + }, + "; security: ", + { + "pluginId": "guidedOnboarding", + "scope": "common", + "docId": "kibGuidedOnboardingPluginApi", + "section": "def-common.GuideConfig", + "text": "GuideConfig" + }, + "; observability: ", + { + "pluginId": "guidedOnboarding", + "scope": "common", + "docId": "kibGuidedOnboardingPluginApi", + "section": "def-common.GuideConfig", + "text": "GuideConfig" + }, + "; testGuide: ", + { + "pluginId": "guidedOnboarding", + "scope": "common", + "docId": "kibGuidedOnboardingPluginApi", + "section": "def-common.GuideConfig", + "text": "GuideConfig" + }, + "; }" + ], + "path": "src/plugins/guided_onboarding/common/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "guidedOnboarding", + "id": "def-common.PLUGIN_ID", + "type": "string", + "tags": [], + "label": "PLUGIN_ID", + "description": [], + "signature": [ + "\"guidedOnboarding\"" + ], + "path": "src/plugins/guided_onboarding/common/constants.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "guidedOnboarding", + "id": "def-common.PLUGIN_NAME", + "type": "string", + "tags": [], + "label": "PLUGIN_NAME", + "description": [], + "signature": [ + "\"guidedOnboarding\"" + ], + "path": "src/plugins/guided_onboarding/common/constants.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "guidedOnboarding", + "id": "def-common.PluginStatus", + "type": "Type", + "tags": [], + "label": "PluginStatus", + "description": [ + "\nGuided onboarding overall status:\n not_started: no guides have been started yet\n in_progress: a guide is currently active\n complete: at least one guide has been completed\n quit: the user quit a guide before completion\n skipped: the user skipped on the landing page\n error: unable to retrieve the plugin state from saved objects" + ], + "signature": [ + "\"error\" | \"complete\" | \"not_started\" | \"in_progress\" | \"quit\" | \"skipped\"" + ], + "path": "src/plugins/guided_onboarding/common/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + } + ], + "objects": [ + { + "parentPluginId": "guidedOnboarding", + "id": "def-common.testGuideConfig", + "type": "Object", + "tags": [], + "label": "testGuideConfig", + "description": [], + "path": "src/plugins/guided_onboarding/common/test_guide_config.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "guidedOnboarding", + "id": "def-common.testGuideConfig.title", + "type": "string", + "tags": [], + "label": "title", + "description": [], + "path": "src/plugins/guided_onboarding/common/test_guide_config.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "guidedOnboarding", + "id": "def-common.testGuideConfig.description", + "type": "string", + "tags": [], + "label": "description", + "description": [], + "path": "src/plugins/guided_onboarding/common/test_guide_config.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "guidedOnboarding", + "id": "def-common.testGuideConfig.guideName", + "type": "string", + "tags": [], + "label": "guideName", + "description": [], + "path": "src/plugins/guided_onboarding/common/test_guide_config.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "guidedOnboarding", + "id": "def-common.testGuideConfig.completedGuideRedirectLocation", + "type": "Object", + "tags": [], + "label": "completedGuideRedirectLocation", + "description": [], + "path": "src/plugins/guided_onboarding/common/test_guide_config.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "guidedOnboarding", + "id": "def-common.testGuideConfig.completedGuideRedirectLocation.appID", + "type": "string", + "tags": [], + "label": "appID", + "description": [], + "path": "src/plugins/guided_onboarding/common/test_guide_config.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "guidedOnboarding", + "id": "def-common.testGuideConfig.completedGuideRedirectLocation.path", + "type": "string", + "tags": [], + "label": "path", + "description": [], + "path": "src/plugins/guided_onboarding/common/test_guide_config.ts", + "deprecated": false, + "trackAdoption": false + } + ] + }, + { + "parentPluginId": "guidedOnboarding", + "id": "def-common.testGuideConfig.docs", + "type": "Object", + "tags": [], + "label": "docs", + "description": [], + "path": "src/plugins/guided_onboarding/common/test_guide_config.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "guidedOnboarding", + "id": "def-common.testGuideConfig.docs.text", + "type": "string", + "tags": [], + "label": "text", + "description": [], + "path": "src/plugins/guided_onboarding/common/test_guide_config.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "guidedOnboarding", + "id": "def-common.testGuideConfig.docs.url", + "type": "string", + "tags": [], + "label": "url", + "description": [], + "path": "src/plugins/guided_onboarding/common/test_guide_config.ts", + "deprecated": false, + "trackAdoption": false + } + ] + }, + { + "parentPluginId": "guidedOnboarding", + "id": "def-common.testGuideConfig.steps", + "type": "Array", + "tags": [], + "label": "steps", + "description": [], + "signature": [ + "({ id: \"step1\"; title: string; descriptionList: string[]; location: { appID: string; path: string; }; integration: string; } | { id: \"step2\"; title: string; descriptionList: string[]; location: { appID: string; path: string; }; manualCompletion: { title: string; description: string; readyToCompleteOnNavigation: true; }; } | { id: \"step3\"; title: string; description: string; manualCompletion: { title: string; description: string; }; location: { appID: string; path: string; }; })[]" + ], + "path": "src/plugins/guided_onboarding/common/test_guide_config.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + } + ] } } \ No newline at end of file diff --git a/api_docs/guided_onboarding.mdx b/api_docs/guided_onboarding.mdx index e1149c95144cf..b4e513b13febe 100644 --- a/api_docs/guided_onboarding.mdx +++ b/api_docs/guided_onboarding.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/guidedOnboarding title: "guidedOnboarding" image: https://source.unsplash.com/400x175/?github description: API docs for the guidedOnboarding plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'guidedOnboarding'] --- import guidedOnboardingObj from './guided_onboarding.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Journey Onboarding](https://github.com/orgs/elastic/teams/platform-onbo | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 43 | 0 | 43 | 3 | +| 76 | 0 | 75 | 0 | ## Client @@ -31,9 +31,6 @@ Contact [Journey Onboarding](https://github.com/orgs/elastic/teams/platform-onbo ### Start -### Objects - - ### Interfaces @@ -45,3 +42,14 @@ Contact [Journey Onboarding](https://github.com/orgs/elastic/teams/platform-onbo ### Start +## Common + +### Objects + + +### Interfaces + + +### Consts, variables and types + + diff --git a/api_docs/home.mdx b/api_docs/home.mdx index 7123879afedf2..7c88b4c2d9494 100644 --- a/api_docs/home.mdx +++ b/api_docs/home.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/home title: "home" image: https://source.unsplash.com/400x175/?github description: API docs for the home plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'home'] --- import homeObj from './home.devdocs.json'; diff --git a/api_docs/index_lifecycle_management.mdx b/api_docs/index_lifecycle_management.mdx index 3fedb8c3e2001..beaa6e117d095 100644 --- a/api_docs/index_lifecycle_management.mdx +++ b/api_docs/index_lifecycle_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/indexLifecycleManagement title: "indexLifecycleManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the indexLifecycleManagement plugin -date: 2022-11-29 +date: 2022-12-06 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 eba1bbf7f8380..6130a5f4a0b2b 100644 --- a/api_docs/index_management.mdx +++ b/api_docs/index_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/indexManagement title: "indexManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the indexManagement plugin -date: 2022-11-29 +date: 2022-12-06 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 ff6d0d8438dc1..d3bf04c9aa359 100644 --- a/api_docs/infra.mdx +++ b/api_docs/infra.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/infra title: "infra" image: https://source.unsplash.com/400x175/?github description: API docs for the infra plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'infra'] --- import infraObj from './infra.devdocs.json'; diff --git a/api_docs/inspector.mdx b/api_docs/inspector.mdx index ec0bea48ab18d..dd02144506fac 100644 --- a/api_docs/inspector.mdx +++ b/api_docs/inspector.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/inspector title: "inspector" image: https://source.unsplash.com/400x175/?github description: API docs for the inspector plugin -date: 2022-11-29 +date: 2022-12-06 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 4bc91c8007b53..6a5f7832fac3d 100644 --- a/api_docs/interactive_setup.mdx +++ b/api_docs/interactive_setup.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/interactiveSetup title: "interactiveSetup" image: https://source.unsplash.com/400x175/?github description: API docs for the interactiveSetup plugin -date: 2022-11-29 +date: 2022-12-06 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 88294719b36ea..c425c4cbc8c2f 100644 --- a/api_docs/kbn_ace.mdx +++ b/api_docs/kbn_ace.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ace title: "@kbn/ace" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ace plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ace'] --- import kbnAceObj from './kbn_ace.devdocs.json'; diff --git a/api_docs/kbn_aiops_components.mdx b/api_docs/kbn_aiops_components.mdx index 75f06ecc8b881..d4a709746abc1 100644 --- a/api_docs/kbn_aiops_components.mdx +++ b/api_docs/kbn_aiops_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-aiops-components title: "@kbn/aiops-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/aiops-components plugin -date: 2022-11-29 +date: 2022-12-06 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 d5e5a1ed6db5c..90f1047c1ff4f 100644 --- a/api_docs/kbn_aiops_utils.mdx +++ b/api_docs/kbn_aiops_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-aiops-utils title: "@kbn/aiops-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/aiops-utils plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/aiops-utils'] --- import kbnAiopsUtilsObj from './kbn_aiops_utils.devdocs.json'; diff --git a/api_docs/kbn_alerts.mdx b/api_docs/kbn_alerts.mdx index 62cc425b3e786..65beb5bc8ec9a 100644 --- a/api_docs/kbn_alerts.mdx +++ b/api_docs/kbn_alerts.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerts title: "@kbn/alerts" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerts plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerts'] --- import kbnAlertsObj from './kbn_alerts.devdocs.json'; diff --git a/api_docs/kbn_analytics.mdx b/api_docs/kbn_analytics.mdx index f097cb6356bc8..d4117d431d084 100644 --- a/api_docs/kbn_analytics.mdx +++ b/api_docs/kbn_analytics.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics title: "@kbn/analytics" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics plugin -date: 2022-11-29 +date: 2022-12-06 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 2133f34e129b9..1257c600b388f 100644 --- a/api_docs/kbn_analytics_client.mdx +++ b/api_docs/kbn_analytics_client.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-client title: "@kbn/analytics-client" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-client plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-client'] --- import kbnAnalyticsClientObj from './kbn_analytics_client.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx b/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx index 5913f1a162b26..acc0e843ccbf6 100644 --- a/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx +++ b/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-elastic-v3-browser title: "@kbn/analytics-shippers-elastic-v3-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-elastic-v3-browser plugin -date: 2022-11-29 +date: 2022-12-06 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 90a2caa58eb9f..6a61e0d734e90 100644 --- a/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx +++ b/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-elastic-v3-common title: "@kbn/analytics-shippers-elastic-v3-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-elastic-v3-common plugin -date: 2022-11-29 +date: 2022-12-06 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 4884b48e9fe8f..eede385a167f7 100644 --- a/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx +++ b/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-elastic-v3-server title: "@kbn/analytics-shippers-elastic-v3-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-elastic-v3-server plugin -date: 2022-11-29 +date: 2022-12-06 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 672f73466298d..f05383c9823c9 100644 --- a/api_docs/kbn_analytics_shippers_fullstory.mdx +++ b/api_docs/kbn_analytics_shippers_fullstory.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-fullstory title: "@kbn/analytics-shippers-fullstory" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-fullstory plugin -date: 2022-11-29 +date: 2022-12-06 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 5dd8f19d2f64d..311054668f3ac 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: 2022-11-29 +date: 2022-12-06 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 9faffcf5ce698..90b5fea1d2130 100644 --- a/api_docs/kbn_apm_config_loader.mdx +++ b/api_docs/kbn_apm_config_loader.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-config-loader title: "@kbn/apm-config-loader" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-config-loader plugin -date: 2022-11-29 +date: 2022-12-06 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 835fd0af87b9e..9defe8f2a6888 100644 --- a/api_docs/kbn_apm_synthtrace.mdx +++ b/api_docs/kbn_apm_synthtrace.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-synthtrace title: "@kbn/apm-synthtrace" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-synthtrace plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-synthtrace'] --- import kbnApmSynthtraceObj from './kbn_apm_synthtrace.devdocs.json'; diff --git a/api_docs/kbn_apm_utils.mdx b/api_docs/kbn_apm_utils.mdx index f4dc547194f12..922b0c2d40f0b 100644 --- a/api_docs/kbn_apm_utils.mdx +++ b/api_docs/kbn_apm_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-utils title: "@kbn/apm-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-utils plugin -date: 2022-11-29 +date: 2022-12-06 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 374b3817d8b13..ae640a234c3b0 100644 --- a/api_docs/kbn_axe_config.mdx +++ b/api_docs/kbn_axe_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-axe-config title: "@kbn/axe-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/axe-config plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/axe-config'] --- import kbnAxeConfigObj from './kbn_axe_config.devdocs.json'; diff --git a/api_docs/kbn_cases_components.mdx b/api_docs/kbn_cases_components.mdx index fb24b12a064d0..6d77f5edbaaaa 100644 --- a/api_docs/kbn_cases_components.mdx +++ b/api_docs/kbn_cases_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cases-components title: "@kbn/cases-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cases-components plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cases-components'] --- import kbnCasesComponentsObj from './kbn_cases_components.devdocs.json'; diff --git a/api_docs/kbn_chart_icons.mdx b/api_docs/kbn_chart_icons.mdx index d6aaced0201c6..01996752e5152 100644 --- a/api_docs/kbn_chart_icons.mdx +++ b/api_docs/kbn_chart_icons.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-chart-icons title: "@kbn/chart-icons" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/chart-icons plugin -date: 2022-11-29 +date: 2022-12-06 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 b4887ec2e338b..29892f3b08110 100644 --- a/api_docs/kbn_ci_stats_core.mdx +++ b/api_docs/kbn_ci_stats_core.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ci-stats-core title: "@kbn/ci-stats-core" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ci-stats-core plugin -date: 2022-11-29 +date: 2022-12-06 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 fa4c05e089846..04c8f83cd7f69 100644 --- a/api_docs/kbn_ci_stats_performance_metrics.mdx +++ b/api_docs/kbn_ci_stats_performance_metrics.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ci-stats-performance-metrics title: "@kbn/ci-stats-performance-metrics" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ci-stats-performance-metrics plugin -date: 2022-11-29 +date: 2022-12-06 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 c7a3b618967c1..a9df84629653a 100644 --- a/api_docs/kbn_ci_stats_reporter.mdx +++ b/api_docs/kbn_ci_stats_reporter.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ci-stats-reporter title: "@kbn/ci-stats-reporter" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ci-stats-reporter plugin -date: 2022-11-29 +date: 2022-12-06 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 3fe11a89ef811..a98c5902a066f 100644 --- a/api_docs/kbn_cli_dev_mode.mdx +++ b/api_docs/kbn_cli_dev_mode.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cli-dev-mode title: "@kbn/cli-dev-mode" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cli-dev-mode plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cli-dev-mode'] --- import kbnCliDevModeObj from './kbn_cli_dev_mode.devdocs.json'; diff --git a/api_docs/kbn_coloring.mdx b/api_docs/kbn_coloring.mdx index 4bf877d6fcdb7..85def9b8eb464 100644 --- a/api_docs/kbn_coloring.mdx +++ b/api_docs/kbn_coloring.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-coloring title: "@kbn/coloring" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/coloring plugin -date: 2022-11-29 +date: 2022-12-06 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 c2bb42b1e1de7..7fc9f150d8a7e 100644 --- a/api_docs/kbn_config.mdx +++ b/api_docs/kbn_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-config title: "@kbn/config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/config plugin -date: 2022-11-29 +date: 2022-12-06 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 506c5f8055aa3..757fa174d4af6 100644 --- a/api_docs/kbn_config_mocks.mdx +++ b/api_docs/kbn_config_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-config-mocks title: "@kbn/config-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/config-mocks plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config-mocks'] --- import kbnConfigMocksObj from './kbn_config_mocks.devdocs.json'; diff --git a/api_docs/kbn_config_schema.devdocs.json b/api_docs/kbn_config_schema.devdocs.json index 6f14501525b6d..fba38fe0d44cc 100644 --- a/api_docs/kbn_config_schema.devdocs.json +++ b/api_docs/kbn_config_schema.devdocs.json @@ -463,6 +463,9 @@ "label": "rightOperand", "description": [], "signature": [ + "A | ", + "Reference", + " | ", { "pluginId": "@kbn/config-schema", "scope": "server", @@ -470,9 +473,7 @@ "section": "def-server.Type", "text": "Type" }, - " | A | ", - "Reference", - "" + "" ], "path": "packages/kbn-config-schema/src/types/conditional_type.ts", "deprecated": false, @@ -1465,7 +1466,9 @@ "ConditionalTypeValue", ", B, C>(leftOperand: ", "Reference", - ", rightOperand: ", + ", rightOperand: A | ", + "Reference", + " | ", { "pluginId": "@kbn/config-schema", "scope": "server", @@ -1473,9 +1476,7 @@ "section": "def-server.Type", "text": "Type" }, - " | A | ", - "Reference", - ", equalType: ", + ", equalType: ", { "pluginId": "@kbn/config-schema", "scope": "server", @@ -2520,7 +2521,9 @@ "ConditionalTypeValue", ", B, C>(leftOperand: ", "Reference", - ", rightOperand: ", + ", rightOperand: A | ", + "Reference", + " | ", { "pluginId": "@kbn/config-schema", "scope": "server", @@ -2528,9 +2531,7 @@ "section": "def-server.Type", "text": "Type" }, - " | A | ", - "Reference", - ", equalType: ", + ", equalType: ", { "pluginId": "@kbn/config-schema", "scope": "server", @@ -2586,6 +2587,9 @@ "label": "rightOperand", "description": [], "signature": [ + "A | ", + "Reference", + " | ", { "pluginId": "@kbn/config-schema", "scope": "server", @@ -2593,9 +2597,7 @@ "section": "def-server.Type", "text": "Type" }, - " | A | ", - "Reference", - "" + "" ], "path": "packages/kbn-config-schema/index.ts", "deprecated": false, diff --git a/api_docs/kbn_config_schema.mdx b/api_docs/kbn_config_schema.mdx index fbc878540bd18..0a63152fb2b34 100644 --- a/api_docs/kbn_config_schema.mdx +++ b/api_docs/kbn_config_schema.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-config-schema title: "@kbn/config-schema" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/config-schema plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config-schema'] --- import kbnConfigSchemaObj from './kbn_config_schema.devdocs.json'; diff --git a/api_docs/kbn_content_management_inspector.mdx b/api_docs/kbn_content_management_inspector.mdx index 2470d81f2a77e..0f53318ee7f90 100644 --- a/api_docs/kbn_content_management_inspector.mdx +++ b/api_docs/kbn_content_management_inspector.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-inspector title: "@kbn/content-management-inspector" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-inspector plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-inspector'] --- import kbnContentManagementInspectorObj from './kbn_content_management_inspector.devdocs.json'; diff --git a/api_docs/kbn_content_management_table_list.mdx b/api_docs/kbn_content_management_table_list.mdx index 59133e5c32711..0413880a5a20b 100644 --- a/api_docs/kbn_content_management_table_list.mdx +++ b/api_docs/kbn_content_management_table_list.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-table-list title: "@kbn/content-management-table-list" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-table-list plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-table-list'] --- import kbnContentManagementTableListObj from './kbn_content_management_table_list.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_browser.mdx b/api_docs/kbn_core_analytics_browser.mdx index fe17a5ee2a252..5f11d8900c77f 100644 --- a/api_docs/kbn_core_analytics_browser.mdx +++ b/api_docs/kbn_core_analytics_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-browser title: "@kbn/core-analytics-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-browser plugin -date: 2022-11-29 +date: 2022-12-06 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 393229992a841..0c89b30b55b82 100644 --- a/api_docs/kbn_core_analytics_browser_internal.mdx +++ b/api_docs/kbn_core_analytics_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-browser-internal title: "@kbn/core-analytics-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-browser-internal plugin -date: 2022-11-29 +date: 2022-12-06 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 3c082aa7c7e22..e83fcc8e3b3e5 100644 --- a/api_docs/kbn_core_analytics_browser_mocks.mdx +++ b/api_docs/kbn_core_analytics_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-browser-mocks title: "@kbn/core-analytics-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-browser-mocks plugin -date: 2022-11-29 +date: 2022-12-06 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 24fba51e25474..94d5e24bba39e 100644 --- a/api_docs/kbn_core_analytics_server.mdx +++ b/api_docs/kbn_core_analytics_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-server title: "@kbn/core-analytics-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-server plugin -date: 2022-11-29 +date: 2022-12-06 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 a472aa73c4bc0..a05929d4e2c23 100644 --- a/api_docs/kbn_core_analytics_server_internal.mdx +++ b/api_docs/kbn_core_analytics_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-server-internal title: "@kbn/core-analytics-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-server-internal plugin -date: 2022-11-29 +date: 2022-12-06 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 061f371fda13c..d6ae00d0756d5 100644 --- a/api_docs/kbn_core_analytics_server_mocks.mdx +++ b/api_docs/kbn_core_analytics_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-server-mocks title: "@kbn/core-analytics-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-server-mocks plugin -date: 2022-11-29 +date: 2022-12-06 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.devdocs.json b/api_docs/kbn_core_application_browser.devdocs.json index a71db82bf7b24..3617d74cf3736 100644 --- a/api_docs/kbn_core_application_browser.devdocs.json +++ b/api_docs/kbn_core_application_browser.devdocs.json @@ -2184,7 +2184,7 @@ "section": "def-common.AppStatus", "text": "AppStatus" }, - " | undefined; searchable?: boolean | undefined; deepLinks?: ", + " | undefined; tooltip?: string | undefined; searchable?: boolean | undefined; deepLinks?: ", { "pluginId": "@kbn/core-application-browser", "scope": "common", @@ -2200,7 +2200,7 @@ "section": "def-common.AppNavLinkStatus", "text": "AppNavLinkStatus" }, - " | undefined; defaultPath?: string | undefined; tooltip?: string | undefined; }" + " | undefined; defaultPath?: string | undefined; }" ], "path": "packages/core/application/core-application-browser/src/application.ts", "deprecated": false, diff --git a/api_docs/kbn_core_application_browser.mdx b/api_docs/kbn_core_application_browser.mdx index 68c51511f90bd..e5145430f88ce 100644 --- a/api_docs/kbn_core_application_browser.mdx +++ b/api_docs/kbn_core_application_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-browser title: "@kbn/core-application-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-browser plugin -date: 2022-11-29 +date: 2022-12-06 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 f11375333b37b..0991508cdcf47 100644 --- a/api_docs/kbn_core_application_browser_internal.mdx +++ b/api_docs/kbn_core_application_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-browser-internal title: "@kbn/core-application-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-browser-internal plugin -date: 2022-11-29 +date: 2022-12-06 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 fdb6ba6b1943d..f7a6b42eda25c 100644 --- a/api_docs/kbn_core_application_browser_mocks.mdx +++ b/api_docs/kbn_core_application_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-browser-mocks title: "@kbn/core-application-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-browser-mocks plugin -date: 2022-11-29 +date: 2022-12-06 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 0a9f06262b256..266547c987504 100644 --- a/api_docs/kbn_core_application_common.mdx +++ b/api_docs/kbn_core_application_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-common title: "@kbn/core-application-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-common plugin -date: 2022-11-29 +date: 2022-12-06 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 55460963472dc..4d1fdfd8a2a48 100644 --- a/api_docs/kbn_core_apps_browser_internal.mdx +++ b/api_docs/kbn_core_apps_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-apps-browser-internal title: "@kbn/core-apps-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-apps-browser-internal plugin -date: 2022-11-29 +date: 2022-12-06 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 3c25309abb4a9..45a42aacb49f0 100644 --- a/api_docs/kbn_core_apps_browser_mocks.mdx +++ b/api_docs/kbn_core_apps_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-apps-browser-mocks title: "@kbn/core-apps-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-apps-browser-mocks plugin -date: 2022-11-29 +date: 2022-12-06 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 a23be8969ea2d..5336232039151 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: 2022-11-29 +date: 2022-12-06 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 01a28813e711e..0819c4101f6c8 100644 --- a/api_docs/kbn_core_base_browser_mocks.mdx +++ b/api_docs/kbn_core_base_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-browser-mocks title: "@kbn/core-base-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-browser-mocks plugin -date: 2022-11-29 +date: 2022-12-06 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 64828f5f792b7..45f98461dc187 100644 --- a/api_docs/kbn_core_base_common.mdx +++ b/api_docs/kbn_core_base_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-common title: "@kbn/core-base-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-common plugin -date: 2022-11-29 +date: 2022-12-06 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 9f2a06fa3c779..a43d045650ae2 100644 --- a/api_docs/kbn_core_base_server_internal.mdx +++ b/api_docs/kbn_core_base_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-server-internal title: "@kbn/core-base-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-server-internal plugin -date: 2022-11-29 +date: 2022-12-06 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 351be6eeab306..f5afda9768202 100644 --- a/api_docs/kbn_core_base_server_mocks.mdx +++ b/api_docs/kbn_core_base_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-server-mocks title: "@kbn/core-base-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-server-mocks plugin -date: 2022-11-29 +date: 2022-12-06 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 3f632e9af2981..e889fd243af24 100644 --- a/api_docs/kbn_core_capabilities_browser_mocks.mdx +++ b/api_docs/kbn_core_capabilities_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-browser-mocks title: "@kbn/core-capabilities-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-browser-mocks plugin -date: 2022-11-29 +date: 2022-12-06 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 82a31cd8c3d59..c72d04653e0af 100644 --- a/api_docs/kbn_core_capabilities_common.mdx +++ b/api_docs/kbn_core_capabilities_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-common title: "@kbn/core-capabilities-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-common plugin -date: 2022-11-29 +date: 2022-12-06 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 9681c696f75d7..f5321874a5c44 100644 --- a/api_docs/kbn_core_capabilities_server.mdx +++ b/api_docs/kbn_core_capabilities_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-server title: "@kbn/core-capabilities-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-server plugin -date: 2022-11-29 +date: 2022-12-06 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 90c628c047a16..47a382543300f 100644 --- a/api_docs/kbn_core_capabilities_server_mocks.mdx +++ b/api_docs/kbn_core_capabilities_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-server-mocks title: "@kbn/core-capabilities-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-server-mocks plugin -date: 2022-11-29 +date: 2022-12-06 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 54b20ccb6c093..5eb2bc6d8e06f 100644 --- a/api_docs/kbn_core_chrome_browser.mdx +++ b/api_docs/kbn_core_chrome_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-chrome-browser title: "@kbn/core-chrome-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-chrome-browser plugin -date: 2022-11-29 +date: 2022-12-06 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 e712893b9e199..1017fcbf71a44 100644 --- a/api_docs/kbn_core_chrome_browser_mocks.mdx +++ b/api_docs/kbn_core_chrome_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-chrome-browser-mocks title: "@kbn/core-chrome-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-chrome-browser-mocks plugin -date: 2022-11-29 +date: 2022-12-06 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 da0a90aa42a0e..7668cb8db8e3e 100644 --- a/api_docs/kbn_core_config_server_internal.mdx +++ b/api_docs/kbn_core_config_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-config-server-internal title: "@kbn/core-config-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-config-server-internal plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-config-server-internal'] --- import kbnCoreConfigServerInternalObj from './kbn_core_config_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_browser.mdx b/api_docs/kbn_core_deprecations_browser.mdx index d6f7976d096cb..95cb1ab00d50d 100644 --- a/api_docs/kbn_core_deprecations_browser.mdx +++ b/api_docs/kbn_core_deprecations_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-browser title: "@kbn/core-deprecations-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-browser plugin -date: 2022-11-29 +date: 2022-12-06 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 b15047d95b316..8be14215cb77f 100644 --- a/api_docs/kbn_core_deprecations_browser_internal.mdx +++ b/api_docs/kbn_core_deprecations_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-browser-internal title: "@kbn/core-deprecations-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-browser-internal plugin -date: 2022-11-29 +date: 2022-12-06 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 ce98aede9de8d..d77b7e99afa22 100644 --- a/api_docs/kbn_core_deprecations_browser_mocks.mdx +++ b/api_docs/kbn_core_deprecations_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-browser-mocks title: "@kbn/core-deprecations-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-browser-mocks plugin -date: 2022-11-29 +date: 2022-12-06 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 8fba3dcf30378..a1d5b8e9656e3 100644 --- a/api_docs/kbn_core_deprecations_common.mdx +++ b/api_docs/kbn_core_deprecations_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-common title: "@kbn/core-deprecations-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-common plugin -date: 2022-11-29 +date: 2022-12-06 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 66680ddd13e9b..16d05337094ba 100644 --- a/api_docs/kbn_core_deprecations_server.mdx +++ b/api_docs/kbn_core_deprecations_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-server title: "@kbn/core-deprecations-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-server plugin -date: 2022-11-29 +date: 2022-12-06 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 40417af58d627..f9795671bf19a 100644 --- a/api_docs/kbn_core_deprecations_server_internal.mdx +++ b/api_docs/kbn_core_deprecations_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-server-internal title: "@kbn/core-deprecations-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-server-internal plugin -date: 2022-11-29 +date: 2022-12-06 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 2daae56b94215..78943917d80bc 100644 --- a/api_docs/kbn_core_deprecations_server_mocks.mdx +++ b/api_docs/kbn_core_deprecations_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-server-mocks title: "@kbn/core-deprecations-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-server-mocks plugin -date: 2022-11-29 +date: 2022-12-06 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 a672eb2548961..9b2a2dfcee9c6 100644 --- a/api_docs/kbn_core_doc_links_browser.mdx +++ b/api_docs/kbn_core_doc_links_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-browser title: "@kbn/core-doc-links-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-browser plugin -date: 2022-11-29 +date: 2022-12-06 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 6d629cbe44dc9..bf65db30c301c 100644 --- a/api_docs/kbn_core_doc_links_browser_mocks.mdx +++ b/api_docs/kbn_core_doc_links_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-browser-mocks title: "@kbn/core-doc-links-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-browser-mocks plugin -date: 2022-11-29 +date: 2022-12-06 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 fdff8719edc7d..8614904ddbfb3 100644 --- a/api_docs/kbn_core_doc_links_server.mdx +++ b/api_docs/kbn_core_doc_links_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-server title: "@kbn/core-doc-links-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-server plugin -date: 2022-11-29 +date: 2022-12-06 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 70616c059a25b..cce389eee0d61 100644 --- a/api_docs/kbn_core_doc_links_server_mocks.mdx +++ b/api_docs/kbn_core_doc_links_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-server-mocks title: "@kbn/core-doc-links-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-server-mocks plugin -date: 2022-11-29 +date: 2022-12-06 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 9d0ebf7066eca..3c479a5108b30 100644 --- a/api_docs/kbn_core_elasticsearch_client_server_internal.mdx +++ b/api_docs/kbn_core_elasticsearch_client_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-client-server-internal title: "@kbn/core-elasticsearch-client-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-client-server-internal plugin -date: 2022-11-29 +date: 2022-12-06 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 7116e7b9738f6..4ac0e5816b528 100644 --- a/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx +++ b/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-client-server-mocks title: "@kbn/core-elasticsearch-client-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-client-server-mocks plugin -date: 2022-11-29 +date: 2022-12-06 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 63ccf3820bf4c..fefb775e4820d 100644 --- a/api_docs/kbn_core_elasticsearch_server.mdx +++ b/api_docs/kbn_core_elasticsearch_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-server title: "@kbn/core-elasticsearch-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-server plugin -date: 2022-11-29 +date: 2022-12-06 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.devdocs.json b/api_docs/kbn_core_elasticsearch_server_internal.devdocs.json index e7449c52e06ce..b6dba147ae5f1 100644 --- a/api_docs/kbn_core_elasticsearch_server_internal.devdocs.json +++ b/api_docs/kbn_core_elasticsearch_server_internal.devdocs.json @@ -2941,7 +2941,7 @@ "label": "ElasticsearchConfigType", "description": [], "signature": [ - "{ readonly username?: string | undefined; readonly password?: string | undefined; readonly serviceAccountToken?: string | undefined; readonly requestTimeout: moment.Duration; readonly compression: boolean; readonly ssl: Readonly<{ key?: string | undefined; certificateAuthorities?: string | string[] | undefined; certificate?: string | undefined; keyPassphrase?: string | undefined; } & { verificationMode: \"none\" | \"full\" | \"certificate\"; keystore: Readonly<{ path?: string | undefined; password?: string | undefined; } & {}>; truststore: Readonly<{ path?: string | undefined; password?: string | undefined; } & {}>; alwaysPresentCertificate: boolean; }>; readonly healthCheck: Readonly<{} & { delay: moment.Duration; }>; readonly customHeaders: Record; readonly hosts: string | string[]; readonly sniffOnStart: boolean; readonly sniffInterval: false | moment.Duration; readonly sniffOnConnectionFault: boolean; readonly maxSockets: number; readonly maxIdleSockets: number; readonly idleSocketTimeout: moment.Duration; readonly requestHeadersWhitelist: string | string[]; readonly shardTimeout: moment.Duration; readonly pingTimeout: moment.Duration; readonly logQueries: boolean; readonly apiVersion: string; readonly ignoreVersionMismatch: boolean; readonly skipStartupConnectionCheck: boolean; }" + "{ readonly username?: string | undefined; readonly password?: string | undefined; readonly serviceAccountToken?: string | undefined; readonly requestTimeout: moment.Duration; readonly compression: boolean; readonly ssl: Readonly<{ key?: string | undefined; certificate?: string | undefined; certificateAuthorities?: string | string[] | undefined; keyPassphrase?: string | undefined; } & { verificationMode: \"none\" | \"full\" | \"certificate\"; keystore: Readonly<{ path?: string | undefined; password?: string | undefined; } & {}>; truststore: Readonly<{ path?: string | undefined; password?: string | undefined; } & {}>; alwaysPresentCertificate: boolean; }>; readonly sniffOnStart: boolean; readonly sniffInterval: false | moment.Duration; readonly sniffOnConnectionFault: boolean; readonly hosts: string | string[]; readonly maxSockets: number; readonly maxIdleSockets: number; readonly idleSocketTimeout: moment.Duration; readonly requestHeadersWhitelist: string | string[]; readonly customHeaders: Record; readonly shardTimeout: moment.Duration; readonly pingTimeout: moment.Duration; readonly logQueries: boolean; readonly apiVersion: string; readonly healthCheck: Readonly<{} & { delay: moment.Duration; }>; readonly ignoreVersionMismatch: boolean; readonly skipStartupConnectionCheck: boolean; }" ], "path": "packages/core/elasticsearch/core-elasticsearch-server-internal/src/elasticsearch_config.ts", "deprecated": false, diff --git a/api_docs/kbn_core_elasticsearch_server_internal.mdx b/api_docs/kbn_core_elasticsearch_server_internal.mdx index 508a1b4c4ab86..58198264711b2 100644 --- a/api_docs/kbn_core_elasticsearch_server_internal.mdx +++ b/api_docs/kbn_core_elasticsearch_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-server-internal title: "@kbn/core-elasticsearch-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-server-internal plugin -date: 2022-11-29 +date: 2022-12-06 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 9c8e38de9cf10..ad2679338e83d 100644 --- a/api_docs/kbn_core_elasticsearch_server_mocks.mdx +++ b/api_docs/kbn_core_elasticsearch_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-server-mocks title: "@kbn/core-elasticsearch-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-server-mocks plugin -date: 2022-11-29 +date: 2022-12-06 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 ac5a302ee9148..84b57b013c071 100644 --- a/api_docs/kbn_core_environment_server_internal.mdx +++ b/api_docs/kbn_core_environment_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-environment-server-internal title: "@kbn/core-environment-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-environment-server-internal plugin -date: 2022-11-29 +date: 2022-12-06 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 9b564da074b2d..ce531e597364f 100644 --- a/api_docs/kbn_core_environment_server_mocks.mdx +++ b/api_docs/kbn_core_environment_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-environment-server-mocks title: "@kbn/core-environment-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-environment-server-mocks plugin -date: 2022-11-29 +date: 2022-12-06 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 c6b3136179bee..bf2ab3df3b3bb 100644 --- a/api_docs/kbn_core_execution_context_browser.mdx +++ b/api_docs/kbn_core_execution_context_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-browser title: "@kbn/core-execution-context-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-browser plugin -date: 2022-11-29 +date: 2022-12-06 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 eb20f1b9f228b..73d1d16382b47 100644 --- a/api_docs/kbn_core_execution_context_browser_internal.mdx +++ b/api_docs/kbn_core_execution_context_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-browser-internal title: "@kbn/core-execution-context-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-browser-internal plugin -date: 2022-11-29 +date: 2022-12-06 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 1ca7db2408386..ab99ccbbaac38 100644 --- a/api_docs/kbn_core_execution_context_browser_mocks.mdx +++ b/api_docs/kbn_core_execution_context_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-browser-mocks title: "@kbn/core-execution-context-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-browser-mocks plugin -date: 2022-11-29 +date: 2022-12-06 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 820813b45f854..cc40714a7680b 100644 --- a/api_docs/kbn_core_execution_context_common.mdx +++ b/api_docs/kbn_core_execution_context_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-common title: "@kbn/core-execution-context-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-common plugin -date: 2022-11-29 +date: 2022-12-06 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 33bbd483eceed..d6e0440137555 100644 --- a/api_docs/kbn_core_execution_context_server.mdx +++ b/api_docs/kbn_core_execution_context_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-server title: "@kbn/core-execution-context-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-server plugin -date: 2022-11-29 +date: 2022-12-06 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 4724841ac7177..986e9be1b12e0 100644 --- a/api_docs/kbn_core_execution_context_server_internal.mdx +++ b/api_docs/kbn_core_execution_context_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-server-internal title: "@kbn/core-execution-context-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-server-internal plugin -date: 2022-11-29 +date: 2022-12-06 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 88d582430efa3..7d435faba134e 100644 --- a/api_docs/kbn_core_execution_context_server_mocks.mdx +++ b/api_docs/kbn_core_execution_context_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-server-mocks title: "@kbn/core-execution-context-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-server-mocks plugin -date: 2022-11-29 +date: 2022-12-06 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 87ac5ac0c74f1..e8ca4f852365e 100644 --- a/api_docs/kbn_core_fatal_errors_browser.mdx +++ b/api_docs/kbn_core_fatal_errors_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-fatal-errors-browser title: "@kbn/core-fatal-errors-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-fatal-errors-browser plugin -date: 2022-11-29 +date: 2022-12-06 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 29a01e65a9278..c99af5e477c49 100644 --- a/api_docs/kbn_core_fatal_errors_browser_mocks.mdx +++ b/api_docs/kbn_core_fatal_errors_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-fatal-errors-browser-mocks title: "@kbn/core-fatal-errors-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-fatal-errors-browser-mocks plugin -date: 2022-11-29 +date: 2022-12-06 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 829b277d86597..61f3b26de33e3 100644 --- a/api_docs/kbn_core_http_browser.mdx +++ b/api_docs/kbn_core_http_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-browser title: "@kbn/core-http-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-browser plugin -date: 2022-11-29 +date: 2022-12-06 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 e1da680a9a7bd..33bed741ec8c9 100644 --- a/api_docs/kbn_core_http_browser_internal.mdx +++ b/api_docs/kbn_core_http_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-browser-internal title: "@kbn/core-http-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-browser-internal plugin -date: 2022-11-29 +date: 2022-12-06 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 3be7085694343..20b34df3790ee 100644 --- a/api_docs/kbn_core_http_browser_mocks.mdx +++ b/api_docs/kbn_core_http_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-browser-mocks title: "@kbn/core-http-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-browser-mocks plugin -date: 2022-11-29 +date: 2022-12-06 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 e23f6069c7431..c231ae64a5c22 100644 --- a/api_docs/kbn_core_http_common.mdx +++ b/api_docs/kbn_core_http_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-common title: "@kbn/core-http-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-common plugin -date: 2022-11-29 +date: 2022-12-06 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 8ad1e3f19b501..eec495f106c97 100644 --- a/api_docs/kbn_core_http_context_server_mocks.mdx +++ b/api_docs/kbn_core_http_context_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-context-server-mocks title: "@kbn/core-http-context-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-context-server-mocks plugin -date: 2022-11-29 +date: 2022-12-06 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 4866ac5bdf71b..1f42dab2dd77e 100644 --- a/api_docs/kbn_core_http_request_handler_context_server.mdx +++ b/api_docs/kbn_core_http_request_handler_context_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-request-handler-context-server title: "@kbn/core-http-request-handler-context-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-request-handler-context-server plugin -date: 2022-11-29 +date: 2022-12-06 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 82b754848eba4..9280594a7952e 100644 --- a/api_docs/kbn_core_http_resources_server.mdx +++ b/api_docs/kbn_core_http_resources_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-resources-server title: "@kbn/core-http-resources-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-resources-server plugin -date: 2022-11-29 +date: 2022-12-06 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 bc6fbdf1352e5..c430f2d25a6b9 100644 --- a/api_docs/kbn_core_http_resources_server_internal.mdx +++ b/api_docs/kbn_core_http_resources_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-resources-server-internal title: "@kbn/core-http-resources-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-resources-server-internal plugin -date: 2022-11-29 +date: 2022-12-06 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 784a7016e1006..cbf061df2f53b 100644 --- a/api_docs/kbn_core_http_resources_server_mocks.mdx +++ b/api_docs/kbn_core_http_resources_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-resources-server-mocks title: "@kbn/core-http-resources-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-resources-server-mocks plugin -date: 2022-11-29 +date: 2022-12-06 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 8c5e760460422..3a3a59cc24db1 100644 --- a/api_docs/kbn_core_http_router_server_internal.mdx +++ b/api_docs/kbn_core_http_router_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-router-server-internal title: "@kbn/core-http-router-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-router-server-internal plugin -date: 2022-11-29 +date: 2022-12-06 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 2e82ec4e4349f..5bc170371eac6 100644 --- a/api_docs/kbn_core_http_router_server_mocks.mdx +++ b/api_docs/kbn_core_http_router_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-router-server-mocks title: "@kbn/core-http-router-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-router-server-mocks plugin -date: 2022-11-29 +date: 2022-12-06 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 8a5588394688e..e14d3e5f6e225 100644 --- a/api_docs/kbn_core_http_server.mdx +++ b/api_docs/kbn_core_http_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-server title: "@kbn/core-http-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-server plugin -date: 2022-11-29 +date: 2022-12-06 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.devdocs.json b/api_docs/kbn_core_http_server_internal.devdocs.json index d4c9428b8a5da..ac5218e06dbbe 100644 --- a/api_docs/kbn_core_http_server_internal.devdocs.json +++ b/api_docs/kbn_core_http_server_internal.devdocs.json @@ -843,7 +843,7 @@ "label": "HttpConfigType", "description": [], "signature": [ - "{ readonly uuid?: string | undefined; readonly basePath?: string | undefined; readonly publicBaseUrl?: string | undefined; readonly name: string; readonly host: string; readonly compression: Readonly<{ referrerWhitelist?: string[] | undefined; } & { enabled: boolean; brotli: Readonly<{} & { enabled: boolean; quality: number; }>; }>; readonly ssl: Readonly<{ key?: string | undefined; certificateAuthorities?: string | string[] | undefined; certificate?: string | undefined; keyPassphrase?: string | undefined; redirectHttpFromPort?: number | undefined; } & { enabled: boolean; keystore: Readonly<{ path?: string | undefined; password?: string | undefined; } & {}>; truststore: Readonly<{ path?: string | undefined; password?: string | undefined; } & {}>; cipherSuites: string[]; supportedProtocols: string[]; clientAuthentication: \"optional\" | \"none\" | \"required\"; }>; readonly port: number; readonly cors: Readonly<{} & { enabled: boolean; allowCredentials: boolean; allowOrigin: string[] | \"*\"[]; }>; readonly autoListen: boolean; readonly shutdownTimeout: moment.Duration; readonly securityResponseHeaders: Readonly<{} & { referrerPolicy: \"origin\" | \"no-referrer\" | \"no-referrer-when-downgrade\" | \"origin-when-cross-origin\" | \"same-origin\" | \"strict-origin\" | \"strict-origin-when-cross-origin\" | \"unsafe-url\" | null; disableEmbedding: boolean; strictTransportSecurity: string | null; xContentTypeOptions: \"nosniff\" | null; permissionsPolicy: string | null; }>; readonly customResponseHeaders: Record; readonly maxPayload: ", + "{ readonly uuid?: string | undefined; readonly basePath?: string | undefined; readonly publicBaseUrl?: string | undefined; readonly name: string; readonly host: string; readonly compression: Readonly<{ referrerWhitelist?: string[] | undefined; } & { enabled: boolean; brotli: Readonly<{} & { enabled: boolean; quality: number; }>; }>; readonly ssl: Readonly<{ key?: string | undefined; certificate?: string | undefined; certificateAuthorities?: string | string[] | undefined; keyPassphrase?: string | undefined; redirectHttpFromPort?: number | undefined; } & { enabled: boolean; keystore: Readonly<{ path?: string | undefined; password?: string | undefined; } & {}>; truststore: Readonly<{ path?: string | undefined; password?: string | undefined; } & {}>; cipherSuites: string[]; supportedProtocols: string[]; clientAuthentication: \"optional\" | \"none\" | \"required\"; }>; readonly port: number; readonly cors: Readonly<{} & { enabled: boolean; allowCredentials: boolean; allowOrigin: string[] | \"*\"[]; }>; readonly autoListen: boolean; readonly shutdownTimeout: moment.Duration; readonly securityResponseHeaders: Readonly<{} & { referrerPolicy: \"origin\" | \"no-referrer\" | \"no-referrer-when-downgrade\" | \"origin-when-cross-origin\" | \"same-origin\" | \"strict-origin\" | \"strict-origin-when-cross-origin\" | \"unsafe-url\" | null; disableEmbedding: boolean; strictTransportSecurity: string | null; xContentTypeOptions: \"nosniff\" | null; permissionsPolicy: string | null; }>; readonly customResponseHeaders: Record; readonly maxPayload: ", { "pluginId": "@kbn/config-schema", "scope": "server", diff --git a/api_docs/kbn_core_http_server_internal.mdx b/api_docs/kbn_core_http_server_internal.mdx index bb9343f22f9b0..8df81c8485cb1 100644 --- a/api_docs/kbn_core_http_server_internal.mdx +++ b/api_docs/kbn_core_http_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-server-internal title: "@kbn/core-http-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-server-internal plugin -date: 2022-11-29 +date: 2022-12-06 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 0720281186f9f..7c4f4a8d02b42 100644 --- a/api_docs/kbn_core_http_server_mocks.mdx +++ b/api_docs/kbn_core_http_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-server-mocks title: "@kbn/core-http-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-server-mocks plugin -date: 2022-11-29 +date: 2022-12-06 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 e8579476faaaf..62651a2972515 100644 --- a/api_docs/kbn_core_i18n_browser.mdx +++ b/api_docs/kbn_core_i18n_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-browser title: "@kbn/core-i18n-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-browser plugin -date: 2022-11-29 +date: 2022-12-06 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 b53db03d7ccf4..c09fc4edbe3b2 100644 --- a/api_docs/kbn_core_i18n_browser_mocks.mdx +++ b/api_docs/kbn_core_i18n_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-browser-mocks title: "@kbn/core-i18n-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-browser-mocks plugin -date: 2022-11-29 +date: 2022-12-06 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 4d6c87b0eddf6..7157f3bcf7c9e 100644 --- a/api_docs/kbn_core_i18n_server.mdx +++ b/api_docs/kbn_core_i18n_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-server title: "@kbn/core-i18n-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-server plugin -date: 2022-11-29 +date: 2022-12-06 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 55bd0ec411c0a..69a312c78dbc5 100644 --- a/api_docs/kbn_core_i18n_server_internal.mdx +++ b/api_docs/kbn_core_i18n_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-server-internal title: "@kbn/core-i18n-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-server-internal plugin -date: 2022-11-29 +date: 2022-12-06 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 1fe6479068764..cef493bcc2cdf 100644 --- a/api_docs/kbn_core_i18n_server_mocks.mdx +++ b/api_docs/kbn_core_i18n_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-server-mocks title: "@kbn/core-i18n-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-server-mocks plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-server-mocks'] --- import kbnCoreI18nServerMocksObj from './kbn_core_i18n_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_injected_metadata_browser.mdx b/api_docs/kbn_core_injected_metadata_browser.mdx index 2526ec601603c..0b6f211d95bc5 100644 --- a/api_docs/kbn_core_injected_metadata_browser.mdx +++ b/api_docs/kbn_core_injected_metadata_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-injected-metadata-browser title: "@kbn/core-injected-metadata-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-injected-metadata-browser plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-injected-metadata-browser'] --- import kbnCoreInjectedMetadataBrowserObj from './kbn_core_injected_metadata_browser.devdocs.json'; diff --git a/api_docs/kbn_core_injected_metadata_browser_mocks.mdx b/api_docs/kbn_core_injected_metadata_browser_mocks.mdx index 3ec46595d829c..4fc87e2929b50 100644 --- a/api_docs/kbn_core_injected_metadata_browser_mocks.mdx +++ b/api_docs/kbn_core_injected_metadata_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-injected-metadata-browser-mocks title: "@kbn/core-injected-metadata-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-injected-metadata-browser-mocks plugin -date: 2022-11-29 +date: 2022-12-06 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 65344c0f5c513..fa6fae1003f6d 100644 --- a/api_docs/kbn_core_integrations_browser_internal.mdx +++ b/api_docs/kbn_core_integrations_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-integrations-browser-internal title: "@kbn/core-integrations-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-integrations-browser-internal plugin -date: 2022-11-29 +date: 2022-12-06 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 594235bd3fb85..96a39d2da03ef 100644 --- a/api_docs/kbn_core_integrations_browser_mocks.mdx +++ b/api_docs/kbn_core_integrations_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-integrations-browser-mocks title: "@kbn/core-integrations-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-integrations-browser-mocks plugin -date: 2022-11-29 +date: 2022-12-06 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 cc69b8a8a8411..93533bdce2805 100644 --- a/api_docs/kbn_core_lifecycle_browser.mdx +++ b/api_docs/kbn_core_lifecycle_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-browser title: "@kbn/core-lifecycle-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-browser plugin -date: 2022-11-29 +date: 2022-12-06 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 a9b091242da93..afdc9a15c78d1 100644 --- a/api_docs/kbn_core_lifecycle_browser_mocks.mdx +++ b/api_docs/kbn_core_lifecycle_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-browser-mocks title: "@kbn/core-lifecycle-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-browser-mocks plugin -date: 2022-11-29 +date: 2022-12-06 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 17ad7b82b4516..feec70aa08cf7 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: 2022-11-29 +date: 2022-12-06 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 a08b7a9305e51..05212d195af71 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: 2022-11-29 +date: 2022-12-06 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 8f8cd5db20806..99c361512f874 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: 2022-11-29 +date: 2022-12-06 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 3f5645cb817aa..37c69e4448592 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: 2022-11-29 +date: 2022-12-06 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 4be7875c06108..f283a5d14c691 100644 --- a/api_docs/kbn_core_logging_server.mdx +++ b/api_docs/kbn_core_logging_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-server title: "@kbn/core-logging-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-server plugin -date: 2022-11-29 +date: 2022-12-06 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 10aee9c5394f6..92749a0a9851f 100644 --- a/api_docs/kbn_core_logging_server_internal.mdx +++ b/api_docs/kbn_core_logging_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-server-internal title: "@kbn/core-logging-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-server-internal plugin -date: 2022-11-29 +date: 2022-12-06 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 518dc78911f8b..8e6cb70f3758c 100644 --- a/api_docs/kbn_core_logging_server_mocks.mdx +++ b/api_docs/kbn_core_logging_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-server-mocks title: "@kbn/core-logging-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-server-mocks plugin -date: 2022-11-29 +date: 2022-12-06 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 0aabd55f4cb1b..69b47e4da2a5d 100644 --- a/api_docs/kbn_core_metrics_collectors_server_internal.mdx +++ b/api_docs/kbn_core_metrics_collectors_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-collectors-server-internal title: "@kbn/core-metrics-collectors-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-collectors-server-internal plugin -date: 2022-11-29 +date: 2022-12-06 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 72c3dbe7a2346..6b60ccd65f266 100644 --- a/api_docs/kbn_core_metrics_collectors_server_mocks.mdx +++ b/api_docs/kbn_core_metrics_collectors_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-collectors-server-mocks title: "@kbn/core-metrics-collectors-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-collectors-server-mocks plugin -date: 2022-11-29 +date: 2022-12-06 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 644aa2592a231..7b491127d8ba9 100644 --- a/api_docs/kbn_core_metrics_server.mdx +++ b/api_docs/kbn_core_metrics_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-server title: "@kbn/core-metrics-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-server plugin -date: 2022-11-29 +date: 2022-12-06 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 164e01c1c2b1a..2672ccd4642dc 100644 --- a/api_docs/kbn_core_metrics_server_internal.mdx +++ b/api_docs/kbn_core_metrics_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-server-internal title: "@kbn/core-metrics-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-server-internal plugin -date: 2022-11-29 +date: 2022-12-06 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 03608e1983a91..b9267b4bf4170 100644 --- a/api_docs/kbn_core_metrics_server_mocks.mdx +++ b/api_docs/kbn_core_metrics_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-server-mocks title: "@kbn/core-metrics-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-server-mocks plugin -date: 2022-11-29 +date: 2022-12-06 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 13a055fa3820a..527c5f5c41564 100644 --- a/api_docs/kbn_core_mount_utils_browser.mdx +++ b/api_docs/kbn_core_mount_utils_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-mount-utils-browser title: "@kbn/core-mount-utils-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-mount-utils-browser plugin -date: 2022-11-29 +date: 2022-12-06 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 16094018ee247..5169544aa6953 100644 --- a/api_docs/kbn_core_node_server.mdx +++ b/api_docs/kbn_core_node_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-node-server title: "@kbn/core-node-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-node-server plugin -date: 2022-11-29 +date: 2022-12-06 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 03d9976e4dcde..044e6f6da7e00 100644 --- a/api_docs/kbn_core_node_server_internal.mdx +++ b/api_docs/kbn_core_node_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-node-server-internal title: "@kbn/core-node-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-node-server-internal plugin -date: 2022-11-29 +date: 2022-12-06 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 c262b6a0323ac..7ea4dec41fdac 100644 --- a/api_docs/kbn_core_node_server_mocks.mdx +++ b/api_docs/kbn_core_node_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-node-server-mocks title: "@kbn/core-node-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-node-server-mocks plugin -date: 2022-11-29 +date: 2022-12-06 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 48e707e33715b..761ba08b2e4eb 100644 --- a/api_docs/kbn_core_notifications_browser.mdx +++ b/api_docs/kbn_core_notifications_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-notifications-browser title: "@kbn/core-notifications-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-notifications-browser plugin -date: 2022-11-29 +date: 2022-12-06 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 ea09b59d9328c..0d5d764a85494 100644 --- a/api_docs/kbn_core_notifications_browser_internal.mdx +++ b/api_docs/kbn_core_notifications_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-notifications-browser-internal title: "@kbn/core-notifications-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-notifications-browser-internal plugin -date: 2022-11-29 +date: 2022-12-06 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 57607e2e5e876..2a34ed909d3dc 100644 --- a/api_docs/kbn_core_notifications_browser_mocks.mdx +++ b/api_docs/kbn_core_notifications_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-notifications-browser-mocks title: "@kbn/core-notifications-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-notifications-browser-mocks plugin -date: 2022-11-29 +date: 2022-12-06 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 e00ac362fc463..23c0901aa37bf 100644 --- a/api_docs/kbn_core_overlays_browser.mdx +++ b/api_docs/kbn_core_overlays_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-overlays-browser title: "@kbn/core-overlays-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-overlays-browser plugin -date: 2022-11-29 +date: 2022-12-06 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 c3e49594faede..4fb5c82446f37 100644 --- a/api_docs/kbn_core_overlays_browser_internal.mdx +++ b/api_docs/kbn_core_overlays_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-overlays-browser-internal title: "@kbn/core-overlays-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-overlays-browser-internal plugin -date: 2022-11-29 +date: 2022-12-06 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 3805e037a2e22..7ebee6af491fe 100644 --- a/api_docs/kbn_core_overlays_browser_mocks.mdx +++ b/api_docs/kbn_core_overlays_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-overlays-browser-mocks title: "@kbn/core-overlays-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-overlays-browser-mocks plugin -date: 2022-11-29 +date: 2022-12-06 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 a036bfcfc3903..737b181e2eb03 100644 --- a/api_docs/kbn_core_plugins_browser.mdx +++ b/api_docs/kbn_core_plugins_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-browser title: "@kbn/core-plugins-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-browser plugin -date: 2022-11-29 +date: 2022-12-06 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 7e127b67d22ac..f1d7c495a6f57 100644 --- a/api_docs/kbn_core_plugins_browser_mocks.mdx +++ b/api_docs/kbn_core_plugins_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-browser-mocks title: "@kbn/core-plugins-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-browser-mocks plugin -date: 2022-11-29 +date: 2022-12-06 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_server.mdx b/api_docs/kbn_core_plugins_server.mdx index 1b9b11c0e29a2..1bdc6c9737e53 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: 2022-11-29 +date: 2022-12-06 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 30e7665c9b577..f89d1a649fce6 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: 2022-11-29 +date: 2022-12-06 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 0fce0f34ebe91..685ca3bb626e3 100644 --- a/api_docs/kbn_core_preboot_server.mdx +++ b/api_docs/kbn_core_preboot_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-preboot-server title: "@kbn/core-preboot-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-preboot-server plugin -date: 2022-11-29 +date: 2022-12-06 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 8b51e5394ef54..ab312dbcaf3b1 100644 --- a/api_docs/kbn_core_preboot_server_mocks.mdx +++ b/api_docs/kbn_core_preboot_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-preboot-server-mocks title: "@kbn/core-preboot-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-preboot-server-mocks plugin -date: 2022-11-29 +date: 2022-12-06 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 34eb00126b958..41ea98eb389cf 100644 --- a/api_docs/kbn_core_rendering_browser_mocks.mdx +++ b/api_docs/kbn_core_rendering_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-rendering-browser-mocks title: "@kbn/core-rendering-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-rendering-browser-mocks plugin -date: 2022-11-29 +date: 2022-12-06 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 263e166a00db7..7439bc59f65d7 100644 --- a/api_docs/kbn_core_rendering_server_internal.mdx +++ b/api_docs/kbn_core_rendering_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-rendering-server-internal title: "@kbn/core-rendering-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-rendering-server-internal plugin -date: 2022-11-29 +date: 2022-12-06 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 5e1fe20c15893..c51398cd2bc68 100644 --- a/api_docs/kbn_core_rendering_server_mocks.mdx +++ b/api_docs/kbn_core_rendering_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-rendering-server-mocks title: "@kbn/core-rendering-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-rendering-server-mocks plugin -date: 2022-11-29 +date: 2022-12-06 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 e8c0cbc3e7ade..85093ab0de7c1 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: 2022-11-29 +date: 2022-12-06 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 84c63c84878f0..7e2de2e82d43e 100644 --- a/api_docs/kbn_core_saved_objects_api_browser.mdx +++ b/api_docs/kbn_core_saved_objects_api_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-browser title: "@kbn/core-saved-objects-api-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-browser plugin -date: 2022-11-29 +date: 2022-12-06 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 1b93e5427a613..e121bac91a981 100644 --- a/api_docs/kbn_core_saved_objects_api_server.mdx +++ b/api_docs/kbn_core_saved_objects_api_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-server title: "@kbn/core-saved-objects-api-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-server plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-server'] --- import kbnCoreSavedObjectsApiServerObj from './kbn_core_saved_objects_api_server.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_api_server_internal.mdx b/api_docs/kbn_core_saved_objects_api_server_internal.mdx index bf85aefe2a97b..e5d9c3b6b1183 100644 --- a/api_docs/kbn_core_saved_objects_api_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_api_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-server-internal title: "@kbn/core-saved-objects-api-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-server-internal plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-server-internal'] --- import kbnCoreSavedObjectsApiServerInternalObj from './kbn_core_saved_objects_api_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_api_server_mocks.mdx b/api_docs/kbn_core_saved_objects_api_server_mocks.mdx index 8da1bb14cdefb..e89adf7825fd8 100644 --- a/api_docs/kbn_core_saved_objects_api_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_api_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-server-mocks title: "@kbn/core-saved-objects-api-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-server-mocks plugin -date: 2022-11-29 +date: 2022-12-06 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 fd896c9cb4773..c55cae140748f 100644 --- a/api_docs/kbn_core_saved_objects_base_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_base_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-base-server-internal title: "@kbn/core-saved-objects-base-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-base-server-internal plugin -date: 2022-11-29 +date: 2022-12-06 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 39e9f0b3ba4b3..266eeca5b7b17 100644 --- a/api_docs/kbn_core_saved_objects_base_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_base_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-base-server-mocks title: "@kbn/core-saved-objects-base-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-base-server-mocks plugin -date: 2022-11-29 +date: 2022-12-06 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 6bfd1dbd35118..3b7963337688c 100644 --- a/api_docs/kbn_core_saved_objects_browser.mdx +++ b/api_docs/kbn_core_saved_objects_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-browser title: "@kbn/core-saved-objects-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-browser plugin -date: 2022-11-29 +date: 2022-12-06 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 60c33e1340a51..0f6ee09219fe1 100644 --- a/api_docs/kbn_core_saved_objects_browser_internal.mdx +++ b/api_docs/kbn_core_saved_objects_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-browser-internal title: "@kbn/core-saved-objects-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-browser-internal plugin -date: 2022-11-29 +date: 2022-12-06 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 bb8651a12546b..6db3cf241e453 100644 --- a/api_docs/kbn_core_saved_objects_browser_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-browser-mocks title: "@kbn/core-saved-objects-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-browser-mocks plugin -date: 2022-11-29 +date: 2022-12-06 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 8aec13f7f4890..59d860f9e6e57 100644 --- a/api_docs/kbn_core_saved_objects_common.mdx +++ b/api_docs/kbn_core_saved_objects_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-common title: "@kbn/core-saved-objects-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-common plugin -date: 2022-11-29 +date: 2022-12-06 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 51b428e1b495f..fa63ef0e06e3e 100644 --- a/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-import-export-server-internal title: "@kbn/core-saved-objects-import-export-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-import-export-server-internal plugin -date: 2022-11-29 +date: 2022-12-06 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 cee9c70e8efcd..462cb0c15d7f0 100644 --- a/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-import-export-server-mocks title: "@kbn/core-saved-objects-import-export-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-import-export-server-mocks plugin -date: 2022-11-29 +date: 2022-12-06 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 6c54ea59468b8..8672c40d385f1 100644 --- a/api_docs/kbn_core_saved_objects_migration_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_migration_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-migration-server-internal title: "@kbn/core-saved-objects-migration-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-migration-server-internal plugin -date: 2022-11-29 +date: 2022-12-06 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 c1f44588ff352..fc2c3b5aecbc1 100644 --- a/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-migration-server-mocks title: "@kbn/core-saved-objects-migration-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-migration-server-mocks plugin -date: 2022-11-29 +date: 2022-12-06 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 5d1b42df92587..932721d1cfd43 100644 --- a/api_docs/kbn_core_saved_objects_server.mdx +++ b/api_docs/kbn_core_saved_objects_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-server title: "@kbn/core-saved-objects-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-server plugin -date: 2022-11-29 +date: 2022-12-06 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 56a384b0e4cf2..4bdf38d3cfe86 100644 --- a/api_docs/kbn_core_saved_objects_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-server-internal title: "@kbn/core-saved-objects-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-server-internal plugin -date: 2022-11-29 +date: 2022-12-06 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 351477412d8d3..c391e859f6e22 100644 --- a/api_docs/kbn_core_saved_objects_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-server-mocks title: "@kbn/core-saved-objects-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-server-mocks plugin -date: 2022-11-29 +date: 2022-12-06 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 d5800ddeb310d..c2a5e83864c37 100644 --- a/api_docs/kbn_core_saved_objects_utils_server.mdx +++ b/api_docs/kbn_core_saved_objects_utils_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-utils-server title: "@kbn/core-saved-objects-utils-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-utils-server plugin -date: 2022-11-29 +date: 2022-12-06 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 9eb7ca2690e88..13645b911006d 100644 --- a/api_docs/kbn_core_status_common.mdx +++ b/api_docs/kbn_core_status_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-common title: "@kbn/core-status-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-common plugin -date: 2022-11-29 +date: 2022-12-06 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 eff5be5a378d1..aff6802de0a30 100644 --- a/api_docs/kbn_core_status_common_internal.mdx +++ b/api_docs/kbn_core_status_common_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-common-internal title: "@kbn/core-status-common-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-common-internal plugin -date: 2022-11-29 +date: 2022-12-06 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 5005cf0a76aad..7078555ea75bf 100644 --- a/api_docs/kbn_core_status_server.mdx +++ b/api_docs/kbn_core_status_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-server title: "@kbn/core-status-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-server plugin -date: 2022-11-29 +date: 2022-12-06 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 1bdefb158e36e..2e683f68503be 100644 --- a/api_docs/kbn_core_status_server_internal.mdx +++ b/api_docs/kbn_core_status_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-server-internal title: "@kbn/core-status-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-server-internal plugin -date: 2022-11-29 +date: 2022-12-06 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 c971bcf92c55f..597a1d3f506d1 100644 --- a/api_docs/kbn_core_status_server_mocks.mdx +++ b/api_docs/kbn_core_status_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-server-mocks title: "@kbn/core-status-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-server-mocks plugin -date: 2022-11-29 +date: 2022-12-06 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 70f106f832dac..faece7243f02e 100644 --- a/api_docs/kbn_core_test_helpers_deprecations_getters.mdx +++ b/api_docs/kbn_core_test_helpers_deprecations_getters.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-deprecations-getters title: "@kbn/core-test-helpers-deprecations-getters" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-deprecations-getters plugin -date: 2022-11-29 +date: 2022-12-06 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 1d6c870e4978d..0d23068a8e239 100644 --- a/api_docs/kbn_core_test_helpers_http_setup_browser.mdx +++ b/api_docs/kbn_core_test_helpers_http_setup_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-http-setup-browser title: "@kbn/core-test-helpers-http-setup-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-http-setup-browser plugin -date: 2022-11-29 +date: 2022-12-06 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 59b0f94beee9b..407949386ac57 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: 2022-11-29 +date: 2022-12-06 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_so_type_serializer.mdx b/api_docs/kbn_core_test_helpers_so_type_serializer.mdx index 9be5c7fa89e43..af319b0b46dbf 100644 --- a/api_docs/kbn_core_test_helpers_so_type_serializer.mdx +++ b/api_docs/kbn_core_test_helpers_so_type_serializer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-so-type-serializer title: "@kbn/core-test-helpers-so-type-serializer" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-so-type-serializer plugin -date: 2022-11-29 +date: 2022-12-06 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 6a4a0d1e00efb..e13168ab66b71 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: 2022-11-29 +date: 2022-12-06 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 c4a213bf7fa7a..fe488d2b9160b 100644 --- a/api_docs/kbn_core_theme_browser.mdx +++ b/api_docs/kbn_core_theme_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-theme-browser title: "@kbn/core-theme-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-theme-browser plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-theme-browser'] --- import kbnCoreThemeBrowserObj from './kbn_core_theme_browser.devdocs.json'; diff --git a/api_docs/kbn_core_theme_browser_internal.mdx b/api_docs/kbn_core_theme_browser_internal.mdx index 049201e6c6e22..6588f3db40c35 100644 --- a/api_docs/kbn_core_theme_browser_internal.mdx +++ b/api_docs/kbn_core_theme_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-theme-browser-internal title: "@kbn/core-theme-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-theme-browser-internal plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-theme-browser-internal'] --- import kbnCoreThemeBrowserInternalObj from './kbn_core_theme_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_theme_browser_mocks.mdx b/api_docs/kbn_core_theme_browser_mocks.mdx index 6275c6086f97e..104a3882e38b0 100644 --- a/api_docs/kbn_core_theme_browser_mocks.mdx +++ b/api_docs/kbn_core_theme_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-theme-browser-mocks title: "@kbn/core-theme-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-theme-browser-mocks plugin -date: 2022-11-29 +date: 2022-12-06 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 a68501e279179..7d2f98a1fbee6 100644 --- a/api_docs/kbn_core_ui_settings_browser.mdx +++ b/api_docs/kbn_core_ui_settings_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-browser title: "@kbn/core-ui-settings-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-browser plugin -date: 2022-11-29 +date: 2022-12-06 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 896f0d573d68f..9b66c108cd033 100644 --- a/api_docs/kbn_core_ui_settings_browser_internal.mdx +++ b/api_docs/kbn_core_ui_settings_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-browser-internal title: "@kbn/core-ui-settings-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-browser-internal plugin -date: 2022-11-29 +date: 2022-12-06 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 3bf3aeccc3e75..870a165def94d 100644 --- a/api_docs/kbn_core_ui_settings_browser_mocks.mdx +++ b/api_docs/kbn_core_ui_settings_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-browser-mocks title: "@kbn/core-ui-settings-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-browser-mocks plugin -date: 2022-11-29 +date: 2022-12-06 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 21ec2fc774a65..c9f981e689d73 100644 --- a/api_docs/kbn_core_ui_settings_common.mdx +++ b/api_docs/kbn_core_ui_settings_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-common title: "@kbn/core-ui-settings-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-common plugin -date: 2022-11-29 +date: 2022-12-06 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 11523bf8d9903..4ae0594ed8497 100644 --- a/api_docs/kbn_core_ui_settings_server.mdx +++ b/api_docs/kbn_core_ui_settings_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-server title: "@kbn/core-ui-settings-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-server plugin -date: 2022-11-29 +date: 2022-12-06 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 a6a70fb8c1b4e..e917187cbd9d5 100644 --- a/api_docs/kbn_core_ui_settings_server_internal.mdx +++ b/api_docs/kbn_core_ui_settings_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-server-internal title: "@kbn/core-ui-settings-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-server-internal plugin -date: 2022-11-29 +date: 2022-12-06 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 455dd00bb5da8..bed23f998989f 100644 --- a/api_docs/kbn_core_ui_settings_server_mocks.mdx +++ b/api_docs/kbn_core_ui_settings_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-server-mocks title: "@kbn/core-ui-settings-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-server-mocks plugin -date: 2022-11-29 +date: 2022-12-06 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 ce0192fa325d0..4641db206c3e5 100644 --- a/api_docs/kbn_core_usage_data_server.mdx +++ b/api_docs/kbn_core_usage_data_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-usage-data-server title: "@kbn/core-usage-data-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-usage-data-server plugin -date: 2022-11-29 +date: 2022-12-06 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 436b930d53746..5ee595e321734 100644 --- a/api_docs/kbn_core_usage_data_server_internal.mdx +++ b/api_docs/kbn_core_usage_data_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-usage-data-server-internal title: "@kbn/core-usage-data-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-usage-data-server-internal plugin -date: 2022-11-29 +date: 2022-12-06 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 a4c593dc82755..1c8d8f92e5b30 100644 --- a/api_docs/kbn_core_usage_data_server_mocks.mdx +++ b/api_docs/kbn_core_usage_data_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-usage-data-server-mocks title: "@kbn/core-usage-data-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-usage-data-server-mocks plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-usage-data-server-mocks'] --- import kbnCoreUsageDataServerMocksObj from './kbn_core_usage_data_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_crypto.mdx b/api_docs/kbn_crypto.mdx index 33fd29b3e3158..6f8c214b8e5d8 100644 --- a/api_docs/kbn_crypto.mdx +++ b/api_docs/kbn_crypto.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-crypto title: "@kbn/crypto" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/crypto plugin -date: 2022-11-29 +date: 2022-12-06 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 ebbf4a4e02cf9..572ff6f3a8fb6 100644 --- a/api_docs/kbn_crypto_browser.mdx +++ b/api_docs/kbn_crypto_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-crypto-browser title: "@kbn/crypto-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/crypto-browser plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/crypto-browser'] --- import kbnCryptoBrowserObj from './kbn_crypto_browser.devdocs.json'; diff --git a/api_docs/kbn_datemath.mdx b/api_docs/kbn_datemath.mdx index 74f38821eebaf..d3ca2440ecfd1 100644 --- a/api_docs/kbn_datemath.mdx +++ b/api_docs/kbn_datemath.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-datemath title: "@kbn/datemath" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/datemath plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/datemath'] --- import kbnDatemathObj from './kbn_datemath.devdocs.json'; diff --git a/api_docs/kbn_dev_cli_errors.mdx b/api_docs/kbn_dev_cli_errors.mdx index 0ebaf7db4a61e..80d06db6c0381 100644 --- a/api_docs/kbn_dev_cli_errors.mdx +++ b/api_docs/kbn_dev_cli_errors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-cli-errors title: "@kbn/dev-cli-errors" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-cli-errors plugin -date: 2022-11-29 +date: 2022-12-06 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 e1b3f2140a26a..231419258159c 100644 --- a/api_docs/kbn_dev_cli_runner.mdx +++ b/api_docs/kbn_dev_cli_runner.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-cli-runner title: "@kbn/dev-cli-runner" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-cli-runner plugin -date: 2022-11-29 +date: 2022-12-06 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 158cc55984acc..3ecdd330b90f9 100644 --- a/api_docs/kbn_dev_proc_runner.mdx +++ b/api_docs/kbn_dev_proc_runner.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-proc-runner title: "@kbn/dev-proc-runner" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-proc-runner plugin -date: 2022-11-29 +date: 2022-12-06 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 785965b6fc064..0599f20d0690d 100644 --- a/api_docs/kbn_dev_utils.mdx +++ b/api_docs/kbn_dev_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-utils title: "@kbn/dev-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-utils plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-utils'] --- import kbnDevUtilsObj from './kbn_dev_utils.devdocs.json'; diff --git a/api_docs/kbn_doc_links.mdx b/api_docs/kbn_doc_links.mdx index 101b4d4173f95..36faa22dca4d7 100644 --- a/api_docs/kbn_doc_links.mdx +++ b/api_docs/kbn_doc_links.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-doc-links title: "@kbn/doc-links" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/doc-links plugin -date: 2022-11-29 +date: 2022-12-06 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 f36fe93237768..cf2f7734574bc 100644 --- a/api_docs/kbn_docs_utils.mdx +++ b/api_docs/kbn_docs_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-docs-utils title: "@kbn/docs-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/docs-utils plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/docs-utils'] --- import kbnDocsUtilsObj from './kbn_docs_utils.devdocs.json'; diff --git a/api_docs/kbn_ebt_tools.mdx b/api_docs/kbn_ebt_tools.mdx index 017d29d7565fe..eb8869751d6d6 100644 --- a/api_docs/kbn_ebt_tools.mdx +++ b/api_docs/kbn_ebt_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ebt-tools title: "@kbn/ebt-tools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ebt-tools plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ebt-tools'] --- import kbnEbtToolsObj from './kbn_ebt_tools.devdocs.json'; diff --git a/api_docs/kbn_es.mdx b/api_docs/kbn_es.mdx index e58aef6107aa2..83f5465e0e22a 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: 2022-11-29 +date: 2022-12-06 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 3fb898af289d0..9559b919787ac 100644 --- a/api_docs/kbn_es_archiver.mdx +++ b/api_docs/kbn_es_archiver.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-archiver title: "@kbn/es-archiver" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-archiver plugin -date: 2022-11-29 +date: 2022-12-06 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 efb4c03d1a8e2..bf4860207b72f 100644 --- a/api_docs/kbn_es_errors.mdx +++ b/api_docs/kbn_es_errors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-errors title: "@kbn/es-errors" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-errors plugin -date: 2022-11-29 +date: 2022-12-06 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 40048490ce6fd..c457675b1ff65 100644 --- a/api_docs/kbn_es_query.mdx +++ b/api_docs/kbn_es_query.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-query title: "@kbn/es-query" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-query plugin -date: 2022-11-29 +date: 2022-12-06 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 213429ff7dc31..a1f60fe69e4a5 100644 --- a/api_docs/kbn_es_types.mdx +++ b/api_docs/kbn_es_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-types title: "@kbn/es-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-types plugin -date: 2022-11-29 +date: 2022-12-06 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 55b92cd4be9ca..78d178b0e85db 100644 --- a/api_docs/kbn_eslint_plugin_imports.mdx +++ b/api_docs/kbn_eslint_plugin_imports.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-eslint-plugin-imports title: "@kbn/eslint-plugin-imports" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/eslint-plugin-imports plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/eslint-plugin-imports'] --- import kbnEslintPluginImportsObj from './kbn_eslint_plugin_imports.devdocs.json'; diff --git a/api_docs/kbn_field_types.mdx b/api_docs/kbn_field_types.mdx index 35d726d8cfa8e..2a0c01e78f487 100644 --- a/api_docs/kbn_field_types.mdx +++ b/api_docs/kbn_field_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-field-types title: "@kbn/field-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/field-types plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/field-types'] --- import kbnFieldTypesObj from './kbn_field_types.devdocs.json'; diff --git a/api_docs/kbn_find_used_node_modules.mdx b/api_docs/kbn_find_used_node_modules.mdx index c13cd321fdc92..0df1f66094a09 100644 --- a/api_docs/kbn_find_used_node_modules.mdx +++ b/api_docs/kbn_find_used_node_modules.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-find-used-node-modules title: "@kbn/find-used-node-modules" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/find-used-node-modules plugin -date: 2022-11-29 +date: 2022-12-06 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 ccb33916ecb86..5418d72188074 100644 --- a/api_docs/kbn_ftr_common_functional_services.mdx +++ b/api_docs/kbn_ftr_common_functional_services.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ftr-common-functional-services title: "@kbn/ftr-common-functional-services" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ftr-common-functional-services plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ftr-common-functional-services'] --- import kbnFtrCommonFunctionalServicesObj from './kbn_ftr_common_functional_services.devdocs.json'; diff --git a/api_docs/kbn_generate.mdx b/api_docs/kbn_generate.mdx index 20886184070f2..eb56f7fb40595 100644 --- a/api_docs/kbn_generate.mdx +++ b/api_docs/kbn_generate.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-generate title: "@kbn/generate" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/generate plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/generate'] --- import kbnGenerateObj from './kbn_generate.devdocs.json'; diff --git a/api_docs/kbn_get_repo_files.mdx b/api_docs/kbn_get_repo_files.mdx index 7d7e97c2b6e27..cf2a8683c5684 100644 --- a/api_docs/kbn_get_repo_files.mdx +++ b/api_docs/kbn_get_repo_files.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-get-repo-files title: "@kbn/get-repo-files" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/get-repo-files plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/get-repo-files'] --- import kbnGetRepoFilesObj from './kbn_get_repo_files.devdocs.json'; diff --git a/api_docs/kbn_guided_onboarding.devdocs.json b/api_docs/kbn_guided_onboarding.devdocs.json index 13782e7daa9e6..39521593c905b 100644 --- a/api_docs/kbn_guided_onboarding.devdocs.json +++ b/api_docs/kbn_guided_onboarding.devdocs.json @@ -310,7 +310,7 @@ "label": "status", "description": [], "signature": [ - "\"complete\" | \"in_progress\" | \"active\" | \"inactive\" | \"ready_to_complete\"" + "\"complete\" | \"in_progress\" | \"inactive\" | \"active\" | \"ready_to_complete\"" ], "path": "packages/kbn-guided-onboarding/src/types.ts", "deprecated": false, @@ -379,7 +379,7 @@ "\nAllowed states for each step in a guide:\n inactive: Step has not started\n active: Step is ready to start (i.e., the guide has been started)\n in_progress: Step has been started and is in progress\n ready_to_complete: Step can be manually completed\n complete: Step has been completed" ], "signature": [ - "\"complete\" | \"in_progress\" | \"active\" | \"inactive\" | \"ready_to_complete\"" + "\"complete\" | \"in_progress\" | \"inactive\" | \"active\" | \"ready_to_complete\"" ], "path": "packages/kbn-guided-onboarding/src/types.ts", "deprecated": false, diff --git a/api_docs/kbn_guided_onboarding.mdx b/api_docs/kbn_guided_onboarding.mdx index 2ed5ce6c97aaf..72267a4b32c50 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: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/guided-onboarding'] --- import kbnGuidedOnboardingObj from './kbn_guided_onboarding.devdocs.json'; diff --git a/api_docs/kbn_handlebars.devdocs.json b/api_docs/kbn_handlebars.devdocs.json index 440a27d24ef64..e1233a052e2cb 100644 --- a/api_docs/kbn_handlebars.devdocs.json +++ b/api_docs/kbn_handlebars.devdocs.json @@ -49,7 +49,71 @@ "initialIsOpen": false } ], - "interfaces": [], + "interfaces": [ + { + "parentPluginId": "@kbn/handlebars", + "id": "def-common.DecoratorsHash", + "type": "Interface", + "tags": [], + "label": "DecoratorsHash", + "description": [], + "path": "packages/kbn-handlebars/index.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/handlebars", + "id": "def-common.DecoratorsHash.Unnamed", + "type": "IndexSignature", + "tags": [], + "label": "[name: string]: DecoratorFunction", + "description": [], + "signature": [ + "[name: string]: ", + { + "pluginId": "@kbn/handlebars", + "scope": "common", + "docId": "kibKbnHandlebarsPluginApi", + "section": "def-common.DecoratorFunction", + "text": "DecoratorFunction" + } + ], + "path": "packages/kbn-handlebars/index.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/handlebars", + "id": "def-common.HelpersHash", + "type": "Interface", + "tags": [], + "label": "HelpersHash", + "description": [], + "path": "packages/kbn-handlebars/index.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/handlebars", + "id": "def-common.HelpersHash.Unnamed", + "type": "IndexSignature", + "tags": [], + "label": "[name: string]: HelperDelegate", + "description": [], + "signature": [ + "[name: string]: Handlebars.HelperDelegate" + ], + "path": "packages/kbn-handlebars/index.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + } + ], "enums": [], "misc": [ { @@ -69,6 +133,113 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "@kbn/handlebars", + "id": "def-common.DecoratorFunction", + "type": "Type", + "tags": [], + "label": "DecoratorFunction", + "description": [ + "\nAccording to the [decorator docs]{@link https://github.com/handlebars-lang/handlebars.js/blob/4.x/docs/decorators-api.md},\na decorator will be called with a different set of arugments than what's actually happening in the upstream code.\nSo here I assume that the docs are wrong and that the upstream code is correct. In reality, `context` is the last 4\ndocumented arguments rolled into one object." + ], + "signature": [ + "(prog: Handlebars.TemplateDelegate, props: Record, container: Container, options: any) => any" + ], + "path": "packages/kbn-handlebars/index.ts", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "@kbn/handlebars", + "id": "def-common.DecoratorFunction.$1", + "type": "Function", + "tags": [], + "label": "prog", + "description": [], + "signature": [ + "Handlebars.TemplateDelegate" + ], + "path": "packages/kbn-handlebars/index.ts", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "@kbn/handlebars", + "id": "def-common.DecoratorFunction.$1.$1", + "type": "Uncategorized", + "tags": [], + "label": "context", + "description": [], + "signature": [ + "T" + ], + "path": "node_modules/handlebars/types/index.d.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/handlebars", + "id": "def-common.DecoratorFunction.$1.$2", + "type": "Object", + "tags": [], + "label": "options", + "description": [], + "signature": [ + "Handlebars.RuntimeOptions | undefined" + ], + "path": "node_modules/handlebars/types/index.d.ts", + "deprecated": false, + "trackAdoption": false + } + ] + }, + { + "parentPluginId": "@kbn/handlebars", + "id": "def-common.DecoratorFunction.$2", + "type": "Object", + "tags": [], + "label": "props", + "description": [], + "signature": [ + "{ [x: string]: any; }" + ], + "path": "packages/kbn-handlebars/index.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/handlebars", + "id": "def-common.DecoratorFunction.$3", + "type": "Object", + "tags": [], + "label": "container", + "description": [], + "signature": [ + "Container" + ], + "path": "packages/kbn-handlebars/index.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/handlebars", + "id": "def-common.DecoratorFunction.$4", + "type": "Any", + "tags": [], + "label": "options", + "description": [], + "signature": [ + "any" + ], + "path": "packages/kbn-handlebars/index.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, { "parentPluginId": "@kbn/handlebars", "id": "def-common.ExtendedCompileOptions", @@ -96,7 +267,7 @@ "\nSupported Handlebars runtime options\n\nThis is a subset of all the runtime options supported by the upstream\nHandlebars module." ], "signature": [ - "{ data?: any; helpers?: { [name: string]: Function; } | undefined; blockParams?: any[] | undefined; }" + "{ data?: any; helpers?: { [name: string]: Function; } | undefined; blockParams?: any[] | undefined; decorators?: { [name: string]: Function; } | undefined; }" ], "path": "packages/kbn-handlebars/index.ts", "deprecated": false, diff --git a/api_docs/kbn_handlebars.mdx b/api_docs/kbn_handlebars.mdx index 8c7f66ab6bf5b..aaa32ce7c2956 100644 --- a/api_docs/kbn_handlebars.mdx +++ b/api_docs/kbn_handlebars.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-handlebars title: "@kbn/handlebars" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/handlebars plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/handlebars'] --- import kbnHandlebarsObj from './kbn_handlebars.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Owner missing] for questions regarding this plugin. | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 6 | 0 | 0 | 0 | +| 17 | 1 | 8 | 0 | ## Common @@ -31,6 +31,9 @@ Contact [Owner missing] for questions regarding this plugin. ### Functions +### Interfaces + + ### Consts, variables and types diff --git a/api_docs/kbn_hapi_mocks.mdx b/api_docs/kbn_hapi_mocks.mdx index cfb9eb2dfe3c9..6b1ff10552ff7 100644 --- a/api_docs/kbn_hapi_mocks.mdx +++ b/api_docs/kbn_hapi_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-hapi-mocks title: "@kbn/hapi-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/hapi-mocks plugin -date: 2022-11-29 +date: 2022-12-06 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 e766dc5ad88b4..3dc202feb5468 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: 2022-11-29 +date: 2022-12-06 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 835ad2ba8b768..5787c0a64b061 100644 --- a/api_docs/kbn_home_sample_data_card.mdx +++ b/api_docs/kbn_home_sample_data_card.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-home-sample-data-card title: "@kbn/home-sample-data-card" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/home-sample-data-card plugin -date: 2022-11-29 +date: 2022-12-06 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 74085300f59ba..2f48f3535cbf0 100644 --- a/api_docs/kbn_home_sample_data_tab.mdx +++ b/api_docs/kbn_home_sample_data_tab.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-home-sample-data-tab title: "@kbn/home-sample-data-tab" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/home-sample-data-tab plugin -date: 2022-11-29 +date: 2022-12-06 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 75bafcd61e726..7f601a4e6b157 100644 --- a/api_docs/kbn_i18n.mdx +++ b/api_docs/kbn_i18n.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-i18n title: "@kbn/i18n" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/i18n plugin -date: 2022-11-29 +date: 2022-12-06 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 784182a13d3c1..dac104a2e6207 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: 2022-11-29 +date: 2022-12-06 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 d6a3b9d50d94d..921b776cf6d2f 100644 --- a/api_docs/kbn_import_resolver.mdx +++ b/api_docs/kbn_import_resolver.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-import-resolver title: "@kbn/import-resolver" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/import-resolver plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/import-resolver'] --- import kbnImportResolverObj from './kbn_import_resolver.devdocs.json'; diff --git a/api_docs/kbn_interpreter.mdx b/api_docs/kbn_interpreter.mdx index 3496caf4b6273..5270da2a8f613 100644 --- a/api_docs/kbn_interpreter.mdx +++ b/api_docs/kbn_interpreter.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-interpreter title: "@kbn/interpreter" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/interpreter plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/interpreter'] --- import kbnInterpreterObj from './kbn_interpreter.devdocs.json'; diff --git a/api_docs/kbn_io_ts_utils.devdocs.json b/api_docs/kbn_io_ts_utils.devdocs.json index 4f27d88f64b54..d6bef46b1ce92 100644 --- a/api_docs/kbn_io_ts_utils.devdocs.json +++ b/api_docs/kbn_io_ts_utils.devdocs.json @@ -325,8 +325,48 @@ } ], "enums": [], - "misc": [], + "misc": [ + { + "parentPluginId": "@kbn/io-ts-utils", + "id": "def-common.IndexPatternType", + "type": "Type", + "tags": [], + "label": "IndexPatternType", + "description": [], + "signature": [ + "string & ", + "Brand", + "<", + "IndexPatternBrand", + ">" + ], + "path": "packages/kbn-io-ts-utils/src/index_pattern_rt/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + } + ], "objects": [ + { + "parentPluginId": "@kbn/io-ts-utils", + "id": "def-common.indexPatternRt", + "type": "Object", + "tags": [], + "label": "indexPatternRt", + "description": [], + "signature": [ + "BrandC", + "<", + "StringC", + ", ", + "IndexPatternBrand", + ">" + ], + "path": "packages/kbn-io-ts-utils/src/index_pattern_rt/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "@kbn/io-ts-utils", "id": "def-common.isoToEpochRt", diff --git a/api_docs/kbn_io_ts_utils.mdx b/api_docs/kbn_io_ts_utils.mdx index 361aeceb82119..172d157c6b878 100644 --- a/api_docs/kbn_io_ts_utils.mdx +++ b/api_docs/kbn_io_ts_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-io-ts-utils title: "@kbn/io-ts-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/io-ts-utils plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/io-ts-utils'] --- import kbnIoTsUtilsObj from './kbn_io_ts_utils.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Owner missing] for questions regarding this plugin. | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 20 | 0 | 20 | 2 | +| 22 | 0 | 22 | 3 | ## Common @@ -34,3 +34,6 @@ Contact [Owner missing] for questions regarding this plugin. ### Interfaces +### Consts, variables and types + + diff --git a/api_docs/kbn_jest_serializers.mdx b/api_docs/kbn_jest_serializers.mdx index 2c41250498678..31bf1187bb828 100644 --- a/api_docs/kbn_jest_serializers.mdx +++ b/api_docs/kbn_jest_serializers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-jest-serializers title: "@kbn/jest-serializers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/jest-serializers plugin -date: 2022-11-29 +date: 2022-12-06 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 ba33660565a3c..6a183876cb3df 100644 --- a/api_docs/kbn_journeys.mdx +++ b/api_docs/kbn_journeys.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-journeys title: "@kbn/journeys" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/journeys plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/journeys'] --- import kbnJourneysObj from './kbn_journeys.devdocs.json'; diff --git a/api_docs/kbn_kibana_manifest_schema.mdx b/api_docs/kbn_kibana_manifest_schema.mdx index 1f9ae9f58985f..6b281e82d195b 100644 --- a/api_docs/kbn_kibana_manifest_schema.mdx +++ b/api_docs/kbn_kibana_manifest_schema.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-kibana-manifest-schema title: "@kbn/kibana-manifest-schema" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/kibana-manifest-schema plugin -date: 2022-11-29 +date: 2022-12-06 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 ebe66c7ed539d..889cab6af3046 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: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/language-documentation-popover'] --- import kbnLanguageDocumentationPopoverObj from './kbn_language_documentation_popover.devdocs.json'; diff --git a/api_docs/kbn_logging.mdx b/api_docs/kbn_logging.mdx index d6ae9badd0f7c..03ef626fe2ec5 100644 --- a/api_docs/kbn_logging.mdx +++ b/api_docs/kbn_logging.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-logging title: "@kbn/logging" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/logging plugin -date: 2022-11-29 +date: 2022-12-06 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 81100556c3660..493c6fd536809 100644 --- a/api_docs/kbn_logging_mocks.mdx +++ b/api_docs/kbn_logging_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-logging-mocks title: "@kbn/logging-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/logging-mocks plugin -date: 2022-11-29 +date: 2022-12-06 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 7e23ae991da8c..270b052d1f45a 100644 --- a/api_docs/kbn_managed_vscode_config.mdx +++ b/api_docs/kbn_managed_vscode_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-managed-vscode-config title: "@kbn/managed-vscode-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/managed-vscode-config plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/managed-vscode-config'] --- import kbnManagedVscodeConfigObj from './kbn_managed_vscode_config.devdocs.json'; diff --git a/api_docs/kbn_mapbox_gl.mdx b/api_docs/kbn_mapbox_gl.mdx index 374a3949d8d9f..f6be64a927aa4 100644 --- a/api_docs/kbn_mapbox_gl.mdx +++ b/api_docs/kbn_mapbox_gl.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-mapbox-gl title: "@kbn/mapbox-gl" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/mapbox-gl plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/mapbox-gl'] --- import kbnMapboxGlObj from './kbn_mapbox_gl.devdocs.json'; diff --git a/api_docs/kbn_ml_agg_utils.mdx b/api_docs/kbn_ml_agg_utils.mdx index 676eb972af87a..d7288b6ddeacb 100644 --- a/api_docs/kbn_ml_agg_utils.mdx +++ b/api_docs/kbn_ml_agg_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-agg-utils title: "@kbn/ml-agg-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-agg-utils plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-agg-utils'] --- import kbnMlAggUtilsObj from './kbn_ml_agg_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_is_populated_object.mdx b/api_docs/kbn_ml_is_populated_object.mdx index 167dc8bf285a7..80af6c1ace908 100644 --- a/api_docs/kbn_ml_is_populated_object.mdx +++ b/api_docs/kbn_ml_is_populated_object.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-is-populated-object title: "@kbn/ml-is-populated-object" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-is-populated-object plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-is-populated-object'] --- import kbnMlIsPopulatedObjectObj from './kbn_ml_is_populated_object.devdocs.json'; diff --git a/api_docs/kbn_ml_string_hash.mdx b/api_docs/kbn_ml_string_hash.mdx index d7e3c9f4d05ef..bb878933973a2 100644 --- a/api_docs/kbn_ml_string_hash.mdx +++ b/api_docs/kbn_ml_string_hash.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-string-hash title: "@kbn/ml-string-hash" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-string-hash plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-string-hash'] --- import kbnMlStringHashObj from './kbn_ml_string_hash.devdocs.json'; diff --git a/api_docs/kbn_monaco.mdx b/api_docs/kbn_monaco.mdx index 66b6e5ed6b519..d684a319e2944 100644 --- a/api_docs/kbn_monaco.mdx +++ b/api_docs/kbn_monaco.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-monaco title: "@kbn/monaco" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/monaco plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/monaco'] --- import kbnMonacoObj from './kbn_monaco.devdocs.json'; diff --git a/api_docs/kbn_optimizer.mdx b/api_docs/kbn_optimizer.mdx index 05e7398788f58..fb14195a42224 100644 --- a/api_docs/kbn_optimizer.mdx +++ b/api_docs/kbn_optimizer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-optimizer title: "@kbn/optimizer" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/optimizer plugin -date: 2022-11-29 +date: 2022-12-06 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 669a437bb127e..2e7b88625fd76 100644 --- a/api_docs/kbn_optimizer_webpack_helpers.mdx +++ b/api_docs/kbn_optimizer_webpack_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-optimizer-webpack-helpers title: "@kbn/optimizer-webpack-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/optimizer-webpack-helpers plugin -date: 2022-11-29 +date: 2022-12-06 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 5bcf43db9c14c..c545b16c76e6b 100644 --- a/api_docs/kbn_osquery_io_ts_types.mdx +++ b/api_docs/kbn_osquery_io_ts_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-osquery-io-ts-types title: "@kbn/osquery-io-ts-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/osquery-io-ts-types plugin -date: 2022-11-29 +date: 2022-12-06 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_peggy.mdx b/api_docs/kbn_peggy.mdx index 284b1b9b234ec..4a87f715dd78c 100644 --- a/api_docs/kbn_peggy.mdx +++ b/api_docs/kbn_peggy.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-peggy title: "@kbn/peggy" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/peggy plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/peggy'] --- import kbnPeggyObj from './kbn_peggy.devdocs.json'; diff --git a/api_docs/kbn_performance_testing_dataset_extractor.mdx b/api_docs/kbn_performance_testing_dataset_extractor.mdx index 834210c8a409c..57dcb6021e950 100644 --- a/api_docs/kbn_performance_testing_dataset_extractor.mdx +++ b/api_docs/kbn_performance_testing_dataset_extractor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-performance-testing-dataset-extractor title: "@kbn/performance-testing-dataset-extractor" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/performance-testing-dataset-extractor plugin -date: 2022-11-29 +date: 2022-12-06 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 1186d61193732..9c796ba3c04ad 100644 --- a/api_docs/kbn_plugin_generator.mdx +++ b/api_docs/kbn_plugin_generator.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-plugin-generator title: "@kbn/plugin-generator" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/plugin-generator plugin -date: 2022-11-29 +date: 2022-12-06 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 6f234b4ea16f2..de87b3df787ec 100644 --- a/api_docs/kbn_plugin_helpers.mdx +++ b/api_docs/kbn_plugin_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-plugin-helpers title: "@kbn/plugin-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/plugin-helpers plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/plugin-helpers'] --- import kbnPluginHelpersObj from './kbn_plugin_helpers.devdocs.json'; diff --git a/api_docs/kbn_react_field.mdx b/api_docs/kbn_react_field.mdx index 55fe113496e34..8ee50b467ce60 100644 --- a/api_docs/kbn_react_field.mdx +++ b/api_docs/kbn_react_field.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-field title: "@kbn/react-field" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-field plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-field'] --- import kbnReactFieldObj from './kbn_react_field.devdocs.json'; diff --git a/api_docs/kbn_repo_source_classifier.mdx b/api_docs/kbn_repo_source_classifier.mdx index 3a42245532f6d..8ccf71cb57864 100644 --- a/api_docs/kbn_repo_source_classifier.mdx +++ b/api_docs/kbn_repo_source_classifier.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-repo-source-classifier title: "@kbn/repo-source-classifier" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/repo-source-classifier plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/repo-source-classifier'] --- import kbnRepoSourceClassifierObj from './kbn_repo_source_classifier.devdocs.json'; diff --git a/api_docs/kbn_rison.devdocs.json b/api_docs/kbn_rison.devdocs.json new file mode 100644 index 0000000000000..ccfc5d62d9b7d --- /dev/null +++ b/api_docs/kbn_rison.devdocs.json @@ -0,0 +1,248 @@ +{ + "id": "@kbn/rison", + "client": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "server": { + "classes": [], + "functions": [ + { + "parentPluginId": "@kbn/rison", + "id": "def-server.decode", + "type": "Function", + "tags": [], + "label": "decode", + "description": [ + "\nparse a rison string into a javascript structure." + ], + "signature": [ + "(rison: string) => ", + { + "pluginId": "@kbn/rison", + "scope": "server", + "docId": "kibKbnRisonPluginApi", + "section": "def-server.RisonValue", + "text": "RisonValue" + } + ], + "path": "packages/kbn-rison/kbn_rison.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/rison", + "id": "def-server.decode.$1", + "type": "string", + "tags": [], + "label": "rison", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-rison/kbn_rison.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/rison", + "id": "def-server.decodeArray", + "type": "Function", + "tags": [], + "label": "decodeArray", + "description": [ + "\nparse an a-rison string into a javascript structure.\n\nthis simply adds array markup around the string before parsing." + ], + "signature": [ + "(rison: string) => ", + { + "pluginId": "@kbn/rison", + "scope": "server", + "docId": "kibKbnRisonPluginApi", + "section": "def-server.RisonValue", + "text": "RisonValue" + }, + "[]" + ], + "path": "packages/kbn-rison/kbn_rison.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/rison", + "id": "def-server.decodeArray.$1", + "type": "string", + "tags": [], + "label": "rison", + "description": [], + "signature": [ + "string" + ], + "path": "packages/kbn-rison/kbn_rison.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/rison", + "id": "def-server.encode", + "type": "Function", + "tags": [], + "label": "encode", + "description": [ + "\nrison-encode a javascript structure" + ], + "signature": [ + "(obj: any) => string" + ], + "path": "packages/kbn-rison/kbn_rison.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/rison", + "id": "def-server.encode.$1", + "type": "Any", + "tags": [], + "label": "obj", + "description": [], + "signature": [ + "any" + ], + "path": "packages/kbn-rison/kbn_rison.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/rison", + "id": "def-server.encodeArray", + "type": "Function", + "tags": [], + "label": "encodeArray", + "description": [ + "\nrison-encode a javascript array without surrounding parens" + ], + "signature": [ + "(array: any[]) => any" + ], + "path": "packages/kbn-rison/kbn_rison.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/rison", + "id": "def-server.encodeArray.$1", + "type": "Array", + "tags": [], + "label": "array", + "description": [], + "signature": [ + "any[]" + ], + "path": "packages/kbn-rison/kbn_rison.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/rison", + "id": "def-server.encodeUnknown", + "type": "Function", + "tags": [], + "label": "encodeUnknown", + "description": [], + "signature": [ + "(obj: any) => string | undefined" + ], + "path": "packages/kbn-rison/kbn_rison.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/rison", + "id": "def-server.encodeUnknown.$1", + "type": "Any", + "tags": [], + "label": "obj", + "description": [], + "signature": [ + "any" + ], + "path": "packages/kbn-rison/kbn_rison.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + } + ], + "interfaces": [], + "enums": [], + "misc": [ + { + "parentPluginId": "@kbn/rison", + "id": "def-server.RisonValue", + "type": "Type", + "tags": [], + "label": "RisonValue", + "description": [], + "signature": [ + "string | number | boolean | ", + { + "pluginId": "@kbn/rison", + "scope": "server", + "docId": "kibKbnRisonPluginApi", + "section": "def-server.RisonValue", + "text": "RisonValue" + }, + "[] | { [key: string]: ", + { + "pluginId": "@kbn/rison", + "scope": "server", + "docId": "kibKbnRisonPluginApi", + "section": "def-server.RisonValue", + "text": "RisonValue" + }, + "; } | null" + ], + "path": "packages/kbn-rison/kbn_rison.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + } + ], + "objects": [] + }, + "common": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + } +} \ No newline at end of file diff --git a/api_docs/kbn_rison.mdx b/api_docs/kbn_rison.mdx new file mode 100644 index 0000000000000..6736b2fd24754 --- /dev/null +++ b/api_docs/kbn_rison.mdx @@ -0,0 +1,33 @@ +--- +#### +#### This document is auto-generated and is meant to be viewed inside our experimental, new docs system. +#### Reach out in #docs-engineering for more info. +#### +id: kibKbnRisonPluginApi +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: 2022-12-06 +tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rison'] +--- +import kbnRisonObj from './kbn_rison.devdocs.json'; + + + +Contact [Owner missing] for questions regarding this plugin. + +**Code health stats** + +| Public API count | Any count | Items lacking comments | Missing exports | +|-------------------|-----------|------------------------|-----------------| +| 11 | 2 | 7 | 0 | + +## Server + +### Functions + + +### Consts, variables and types + + diff --git a/api_docs/kbn_rule_data_utils.devdocs.json b/api_docs/kbn_rule_data_utils.devdocs.json index f2a733e93e056..403479f0c300a 100644 --- a/api_docs/kbn_rule_data_utils.devdocs.json +++ b/api_docs/kbn_rule_data_utils.devdocs.json @@ -1251,7 +1251,7 @@ "label": "AlertStatus", "description": [], "signature": [ - "\"recovered\" | \"active\"" + "\"active\" | \"recovered\"" ], "path": "packages/kbn-rule-data-utils/src/alerts_as_data_status.ts", "deprecated": false, diff --git a/api_docs/kbn_rule_data_utils.mdx b/api_docs/kbn_rule_data_utils.mdx index 4d40793268f20..58c892f9ea5d1 100644 --- a/api_docs/kbn_rule_data_utils.mdx +++ b/api_docs/kbn_rule_data_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-rule-data-utils title: "@kbn/rule-data-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/rule-data-utils plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rule-data-utils'] --- import kbnRuleDataUtilsObj from './kbn_rule_data_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_autocomplete.mdx b/api_docs/kbn_securitysolution_autocomplete.mdx index 3a8a3d09f6e10..2a67b8f0b2a45 100644 --- a/api_docs/kbn_securitysolution_autocomplete.mdx +++ b/api_docs/kbn_securitysolution_autocomplete.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-autocomplete title: "@kbn/securitysolution-autocomplete" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-autocomplete plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-autocomplete'] --- import kbnSecuritysolutionAutocompleteObj from './kbn_securitysolution_autocomplete.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_es_utils.mdx b/api_docs/kbn_securitysolution_es_utils.mdx index 82b4a27654598..9ddc1a20ad2b5 100644 --- a/api_docs/kbn_securitysolution_es_utils.mdx +++ b/api_docs/kbn_securitysolution_es_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-es-utils title: "@kbn/securitysolution-es-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-es-utils plugin -date: 2022-11-29 +date: 2022-12-06 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.devdocs.json b/api_docs/kbn_securitysolution_exception_list_components.devdocs.json index 7c5410f630730..ca9ebec0b58fd 100644 --- a/api_docs/kbn_securitysolution_exception_list_components.devdocs.json +++ b/api_docs/kbn_securitysolution_exception_list_components.devdocs.json @@ -309,6 +309,39 @@ ], "initialIsOpen": false }, + { + "parentPluginId": "@kbn/securitysolution-exception-list-components", + "id": "def-common.generateLinkedRulesMenuItems", + "type": "Function", + "tags": [], + "label": "generateLinkedRulesMenuItems", + "description": [], + "signature": [ + "({ dataTestSubj, linkedRules, securityLinkAnchorComponent, leftIcon, }: MenuItemLinkedRulesProps) => React.ReactElement>[] | null" + ], + "path": "packages/kbn-securitysolution-exception-list-components/src/generate_linked_rules_menu_item/index.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/securitysolution-exception-list-components", + "id": "def-common.generateLinkedRulesMenuItems.$1", + "type": "Object", + "tags": [], + "label": "{\n dataTestSubj,\n linkedRules,\n securityLinkAnchorComponent,\n leftIcon = '',\n}", + "description": [], + "signature": [ + "MenuItemLinkedRulesProps" + ], + "path": "packages/kbn-securitysolution-exception-list-components/src/generate_linked_rules_menu_item/index.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, { "parentPluginId": "@kbn/securitysolution-exception-list-components", "id": "def-common.HeaderMenu", diff --git a/api_docs/kbn_securitysolution_exception_list_components.mdx b/api_docs/kbn_securitysolution_exception_list_components.mdx index fab8bcecfc275..bf5dccc0e220b 100644 --- a/api_docs/kbn_securitysolution_exception_list_components.mdx +++ b/api_docs/kbn_securitysolution_exception_list_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-exception-list-components title: "@kbn/securitysolution-exception-list-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-exception-list-components plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-exception-list-components'] --- import kbnSecuritysolutionExceptionListComponentsObj from './kbn_securitysolution_exception_list_components.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Owner missing] for questions regarding this plugin. | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 102 | 0 | 91 | 1 | +| 104 | 0 | 93 | 1 | ## Common diff --git a/api_docs/kbn_securitysolution_hook_utils.mdx b/api_docs/kbn_securitysolution_hook_utils.mdx index a557ea1a78217..3083b3254d881 100644 --- a/api_docs/kbn_securitysolution_hook_utils.mdx +++ b/api_docs/kbn_securitysolution_hook_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-hook-utils title: "@kbn/securitysolution-hook-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-hook-utils plugin -date: 2022-11-29 +date: 2022-12-06 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 29abfc5b4e6a2..f6a76b3a11330 100644 --- a/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-alerting-types title: "@kbn/securitysolution-io-ts-alerting-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-alerting-types plugin -date: 2022-11-29 +date: 2022-12-06 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 b34154d40882d..bf51768f895cd 100644 --- a/api_docs/kbn_securitysolution_io_ts_list_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_list_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-list-types title: "@kbn/securitysolution-io-ts-list-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-list-types plugin -date: 2022-11-29 +date: 2022-12-06 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 36ea96a72f11d..b4a088e907489 100644 --- a/api_docs/kbn_securitysolution_io_ts_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-types title: "@kbn/securitysolution-io-ts-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-types plugin -date: 2022-11-29 +date: 2022-12-06 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 4082f06610d2b..5c9e710eab355 100644 --- a/api_docs/kbn_securitysolution_io_ts_utils.mdx +++ b/api_docs/kbn_securitysolution_io_ts_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-utils title: "@kbn/securitysolution-io-ts-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-utils plugin -date: 2022-11-29 +date: 2022-12-06 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 5745702411442..184aae4efbdec 100644 --- a/api_docs/kbn_securitysolution_list_api.mdx +++ b/api_docs/kbn_securitysolution_list_api.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-api title: "@kbn/securitysolution-list-api" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-api plugin -date: 2022-11-29 +date: 2022-12-06 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 49a7263eaada8..e8f2fd2f8a0f7 100644 --- a/api_docs/kbn_securitysolution_list_constants.mdx +++ b/api_docs/kbn_securitysolution_list_constants.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-constants title: "@kbn/securitysolution-list-constants" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-constants plugin -date: 2022-11-29 +date: 2022-12-06 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 62a7ac4e0ff9c..a1cf9ab583b8c 100644 --- a/api_docs/kbn_securitysolution_list_hooks.mdx +++ b/api_docs/kbn_securitysolution_list_hooks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-hooks title: "@kbn/securitysolution-list-hooks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-hooks plugin -date: 2022-11-29 +date: 2022-12-06 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 2c761d5e49a54..110857778b1fb 100644 --- a/api_docs/kbn_securitysolution_list_utils.mdx +++ b/api_docs/kbn_securitysolution_list_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-utils title: "@kbn/securitysolution-list-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-utils plugin -date: 2022-11-29 +date: 2022-12-06 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 61199116cfd33..bef2cb875a16d 100644 --- a/api_docs/kbn_securitysolution_rules.mdx +++ b/api_docs/kbn_securitysolution_rules.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-rules title: "@kbn/securitysolution-rules" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-rules plugin -date: 2022-11-29 +date: 2022-12-06 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 c6c28924e2cc1..b7a7096ffbca7 100644 --- a/api_docs/kbn_securitysolution_t_grid.mdx +++ b/api_docs/kbn_securitysolution_t_grid.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-t-grid title: "@kbn/securitysolution-t-grid" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-t-grid plugin -date: 2022-11-29 +date: 2022-12-06 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 74072f100732b..6a1e9117265c4 100644 --- a/api_docs/kbn_securitysolution_utils.mdx +++ b/api_docs/kbn_securitysolution_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-utils title: "@kbn/securitysolution-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-utils plugin -date: 2022-11-29 +date: 2022-12-06 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 1194ce9c2c7f4..e04a04c425a8f 100644 --- a/api_docs/kbn_server_http_tools.mdx +++ b/api_docs/kbn_server_http_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-server-http-tools title: "@kbn/server-http-tools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/server-http-tools plugin -date: 2022-11-29 +date: 2022-12-06 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 3e85cf1dac16a..db6669b2c2c82 100644 --- a/api_docs/kbn_server_route_repository.mdx +++ b/api_docs/kbn_server_route_repository.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-server-route-repository title: "@kbn/server-route-repository" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/server-route-repository plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/server-route-repository'] --- import kbnServerRouteRepositoryObj from './kbn_server_route_repository.devdocs.json'; diff --git a/api_docs/kbn_shared_svg.mdx b/api_docs/kbn_shared_svg.mdx index b16d100f973f5..5a952d9c12768 100644 --- a/api_docs/kbn_shared_svg.mdx +++ b/api_docs/kbn_shared_svg.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-svg title: "@kbn/shared-svg" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-svg plugin -date: 2022-11-29 +date: 2022-12-06 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 d746fdc62c8d6..975b27be5c27b 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: 2022-11-29 +date: 2022-12-06 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_avatar_user_profile_components.mdx b/api_docs/kbn_shared_ux_avatar_user_profile_components.mdx index bc91d7219c87b..d7d9bcf18c15a 100644 --- a/api_docs/kbn_shared_ux_avatar_user_profile_components.mdx +++ b/api_docs/kbn_shared_ux_avatar_user_profile_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-avatar-user-profile-components title: "@kbn/shared-ux-avatar-user-profile-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-avatar-user-profile-components plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-avatar-user-profile-components'] --- import kbnSharedUxAvatarUserProfileComponentsObj from './kbn_shared_ux_avatar_user_profile_components.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_button_exit_full_screen.mdx b/api_docs/kbn_shared_ux_button_exit_full_screen.mdx index 99bdf0dc58615..3aaeb39134631 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: 2022-11-29 +date: 2022-12-06 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_exit_full_screen_mocks.mdx b/api_docs/kbn_shared_ux_button_exit_full_screen_mocks.mdx index 063ee661ccadc..92bad13340a97 100644 --- a/api_docs/kbn_shared_ux_button_exit_full_screen_mocks.mdx +++ b/api_docs/kbn_shared_ux_button_exit_full_screen_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-button-exit-full-screen-mocks title: "@kbn/shared-ux-button-exit-full-screen-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-button-exit-full-screen-mocks plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-button-exit-full-screen-mocks'] --- import kbnSharedUxButtonExitFullScreenMocksObj from './kbn_shared_ux_button_exit_full_screen_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_button_toolbar.mdx b/api_docs/kbn_shared_ux_button_toolbar.mdx index 0ccc197da1de3..b7947a169a085 100644 --- a/api_docs/kbn_shared_ux_button_toolbar.mdx +++ b/api_docs/kbn_shared_ux_button_toolbar.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-button-toolbar title: "@kbn/shared-ux-button-toolbar" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-button-toolbar plugin -date: 2022-11-29 +date: 2022-12-06 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.devdocs.json b/api_docs/kbn_shared_ux_card_no_data.devdocs.json index 9128118a280ee..3f9b08b643f7a 100644 --- a/api_docs/kbn_shared_ux_card_no_data.devdocs.json +++ b/api_docs/kbn_shared_ux_card_no_data.devdocs.json @@ -186,7 +186,7 @@ "signature": [ "{ children?: React.ReactNode; description?: React.ReactNode; category?: string | undefined; onError?: React.ReactEventHandler | undefined; hidden?: boolean | undefined; icon?: React.ReactElement<", "EuiIconProps", - ", string | React.JSXElementConstructor> | null | undefined; id?: string | undefined; image?: string | React.ReactElement> | undefined; className?: string | undefined; title?: boolean | React.ReactChild | React.ReactFragment | React.ReactPortal | undefined; onChange?: React.FormEventHandler | undefined; onKeyDown?: React.KeyboardEventHandler | undefined; onClick?: React.MouseEventHandler | undefined; security?: string | undefined; defaultValue?: string | number | readonly string[] | undefined; lang?: string | undefined; defaultChecked?: boolean | undefined; suppressContentEditableWarning?: boolean | undefined; suppressHydrationWarning?: boolean | undefined; accessKey?: string | undefined; contentEditable?: \"inherit\" | Booleanish | undefined; contextMenu?: string | undefined; dir?: string | undefined; draggable?: Booleanish | undefined; placeholder?: string | undefined; slot?: string | undefined; spellCheck?: Booleanish | undefined; style?: React.CSSProperties | undefined; tabIndex?: number | undefined; translate?: \"no\" | \"yes\" | undefined; radioGroup?: string | undefined; role?: React.AriaRole | undefined; about?: string | undefined; datatype?: string | undefined; inlist?: any; prefix?: string | undefined; property?: string | undefined; resource?: string | undefined; typeof?: string | undefined; vocab?: string | undefined; autoCapitalize?: string | undefined; autoCorrect?: string | undefined; autoSave?: string | undefined; itemProp?: string | undefined; itemScope?: boolean | undefined; itemType?: string | undefined; itemID?: string | undefined; itemRef?: string | undefined; results?: number | undefined; unselectable?: \"on\" | \"off\" | undefined; inputMode?: \"none\" | \"email\" | \"search\" | \"text\" | \"tel\" | \"url\" | \"numeric\" | \"decimal\" | undefined; is?: string | undefined; 'aria-activedescendant'?: string | undefined; 'aria-atomic'?: Booleanish | undefined; 'aria-autocomplete'?: \"none\" | \"list\" | \"inline\" | \"both\" | undefined; 'aria-busy'?: Booleanish | undefined; 'aria-checked'?: boolean | \"mixed\" | \"false\" | \"true\" | undefined; 'aria-colcount'?: number | undefined; 'aria-colindex'?: number | undefined; 'aria-colspan'?: number | undefined; 'aria-controls'?: string | undefined; 'aria-current'?: boolean | \"date\" | \"location\" | \"time\" | \"page\" | \"false\" | \"true\" | \"step\" | undefined; 'aria-describedby'?: string | undefined; 'aria-details'?: string | undefined; 'aria-disabled'?: Booleanish | undefined; 'aria-dropeffect'?: \"none\" | \"copy\" | \"link\" | \"execute\" | \"move\" | \"popup\" | undefined; 'aria-errormessage'?: string | undefined; 'aria-expanded'?: Booleanish | undefined; 'aria-flowto'?: string | undefined; 'aria-grabbed'?: Booleanish | undefined; 'aria-haspopup'?: boolean | \"grid\" | \"menu\" | \"false\" | \"true\" | \"dialog\" | \"listbox\" | \"tree\" | undefined; 'aria-hidden'?: Booleanish | undefined; 'aria-invalid'?: boolean | \"false\" | \"true\" | \"grammar\" | \"spelling\" | undefined; 'aria-keyshortcuts'?: string | undefined; 'aria-label'?: string | undefined; 'aria-labelledby'?: string | undefined; 'aria-level'?: number | undefined; 'aria-live'?: \"off\" | \"assertive\" | \"polite\" | undefined; 'aria-modal'?: Booleanish | undefined; 'aria-multiline'?: Booleanish | undefined; 'aria-multiselectable'?: Booleanish | undefined; 'aria-orientation'?: \"horizontal\" | \"vertical\" | undefined; 'aria-owns'?: string | undefined; 'aria-placeholder'?: string | undefined; 'aria-posinset'?: number | undefined; 'aria-pressed'?: boolean | \"mixed\" | \"false\" | \"true\" | undefined; 'aria-readonly'?: Booleanish | undefined; 'aria-relevant'?: \"all\" | \"text\" | \"additions\" | \"additions removals\" | \"additions text\" | \"removals\" | \"removals additions\" | \"removals text\" | \"text additions\" | \"text removals\" | undefined; 'aria-required'?: Booleanish | undefined; 'aria-roledescription'?: string | undefined; 'aria-rowcount'?: number | undefined; 'aria-rowindex'?: number | undefined; 'aria-rowspan'?: number | undefined; 'aria-selected'?: Booleanish | undefined; 'aria-setsize'?: number | undefined; 'aria-sort'?: \"none\" | \"other\" | \"ascending\" | \"descending\" | undefined; 'aria-valuemax'?: number | undefined; 'aria-valuemin'?: number | undefined; 'aria-valuenow'?: number | undefined; 'aria-valuetext'?: string | undefined; dangerouslySetInnerHTML?: { __html: string; } | undefined; onCopy?: React.ClipboardEventHandler | undefined; onCopyCapture?: React.ClipboardEventHandler | undefined; onCut?: React.ClipboardEventHandler | undefined; onCutCapture?: React.ClipboardEventHandler | undefined; onPaste?: React.ClipboardEventHandler | undefined; onPasteCapture?: React.ClipboardEventHandler | undefined; onCompositionEnd?: React.CompositionEventHandler | undefined; onCompositionEndCapture?: React.CompositionEventHandler | undefined; onCompositionStart?: React.CompositionEventHandler | undefined; onCompositionStartCapture?: React.CompositionEventHandler | undefined; onCompositionUpdate?: React.CompositionEventHandler | undefined; onCompositionUpdateCapture?: React.CompositionEventHandler | undefined; onFocus?: React.FocusEventHandler | undefined; onFocusCapture?: React.FocusEventHandler | undefined; onBlur?: React.FocusEventHandler | undefined; onBlurCapture?: React.FocusEventHandler | undefined; onChangeCapture?: React.FormEventHandler | undefined; onBeforeInput?: React.FormEventHandler | undefined; onBeforeInputCapture?: React.FormEventHandler | undefined; onInput?: React.FormEventHandler | undefined; onInputCapture?: React.FormEventHandler | undefined; onReset?: React.FormEventHandler | undefined; onResetCapture?: React.FormEventHandler | undefined; onSubmit?: React.FormEventHandler | undefined; onSubmitCapture?: React.FormEventHandler | undefined; onInvalid?: React.FormEventHandler | undefined; onInvalidCapture?: React.FormEventHandler | undefined; onLoad?: React.ReactEventHandler | undefined; onLoadCapture?: React.ReactEventHandler | undefined; onErrorCapture?: React.ReactEventHandler | undefined; onKeyDownCapture?: React.KeyboardEventHandler | undefined; onKeyPress?: React.KeyboardEventHandler | undefined; onKeyPressCapture?: React.KeyboardEventHandler | undefined; onKeyUp?: React.KeyboardEventHandler | undefined; onKeyUpCapture?: React.KeyboardEventHandler | undefined; onAbort?: React.ReactEventHandler | undefined; onAbortCapture?: React.ReactEventHandler | undefined; onCanPlay?: React.ReactEventHandler | undefined; onCanPlayCapture?: React.ReactEventHandler | undefined; onCanPlayThrough?: React.ReactEventHandler | undefined; onCanPlayThroughCapture?: React.ReactEventHandler | undefined; onDurationChange?: React.ReactEventHandler | undefined; onDurationChangeCapture?: React.ReactEventHandler | undefined; onEmptied?: React.ReactEventHandler | undefined; onEmptiedCapture?: React.ReactEventHandler | undefined; onEncrypted?: React.ReactEventHandler | undefined; onEncryptedCapture?: React.ReactEventHandler | undefined; onEnded?: React.ReactEventHandler | undefined; onEndedCapture?: React.ReactEventHandler | undefined; onLoadedData?: React.ReactEventHandler | undefined; onLoadedDataCapture?: React.ReactEventHandler | undefined; onLoadedMetadata?: React.ReactEventHandler | undefined; onLoadedMetadataCapture?: React.ReactEventHandler | undefined; onLoadStart?: React.ReactEventHandler | undefined; onLoadStartCapture?: React.ReactEventHandler | undefined; onPause?: React.ReactEventHandler | undefined; onPauseCapture?: React.ReactEventHandler | undefined; onPlay?: React.ReactEventHandler | undefined; onPlayCapture?: React.ReactEventHandler | undefined; onPlaying?: React.ReactEventHandler | undefined; onPlayingCapture?: React.ReactEventHandler | undefined; onProgress?: React.ReactEventHandler | undefined; onProgressCapture?: React.ReactEventHandler | undefined; onRateChange?: React.ReactEventHandler | undefined; onRateChangeCapture?: React.ReactEventHandler | undefined; onSeeked?: React.ReactEventHandler | undefined; onSeekedCapture?: React.ReactEventHandler | undefined; onSeeking?: React.ReactEventHandler | undefined; onSeekingCapture?: React.ReactEventHandler | undefined; onStalled?: React.ReactEventHandler | undefined; onStalledCapture?: React.ReactEventHandler | undefined; onSuspend?: React.ReactEventHandler | undefined; onSuspendCapture?: React.ReactEventHandler | undefined; onTimeUpdate?: React.ReactEventHandler | undefined; onTimeUpdateCapture?: React.ReactEventHandler | undefined; onVolumeChange?: React.ReactEventHandler | undefined; onVolumeChangeCapture?: React.ReactEventHandler | undefined; onWaiting?: React.ReactEventHandler | undefined; onWaitingCapture?: React.ReactEventHandler | undefined; onAuxClick?: React.MouseEventHandler | undefined; onAuxClickCapture?: React.MouseEventHandler | undefined; onClickCapture?: React.MouseEventHandler | undefined; onContextMenu?: React.MouseEventHandler | undefined; onContextMenuCapture?: React.MouseEventHandler | undefined; onDoubleClick?: React.MouseEventHandler | undefined; onDoubleClickCapture?: React.MouseEventHandler | undefined; onDrag?: React.DragEventHandler | undefined; onDragCapture?: React.DragEventHandler | undefined; onDragEnd?: React.DragEventHandler | undefined; onDragEndCapture?: React.DragEventHandler | undefined; onDragEnter?: React.DragEventHandler | undefined; onDragEnterCapture?: React.DragEventHandler | undefined; onDragExit?: React.DragEventHandler | undefined; onDragExitCapture?: React.DragEventHandler | undefined; onDragLeave?: React.DragEventHandler | undefined; onDragLeaveCapture?: React.DragEventHandler | undefined; onDragOver?: React.DragEventHandler | undefined; onDragOverCapture?: React.DragEventHandler | undefined; onDragStart?: React.DragEventHandler | undefined; onDragStartCapture?: React.DragEventHandler | undefined; onDrop?: React.DragEventHandler | undefined; onDropCapture?: React.DragEventHandler | undefined; onMouseDown?: React.MouseEventHandler | undefined; onMouseDownCapture?: React.MouseEventHandler | undefined; onMouseEnter?: React.MouseEventHandler | undefined; onMouseLeave?: React.MouseEventHandler | undefined; onMouseMove?: React.MouseEventHandler | undefined; onMouseMoveCapture?: React.MouseEventHandler | undefined; onMouseOut?: React.MouseEventHandler | undefined; onMouseOutCapture?: React.MouseEventHandler | undefined; onMouseOver?: React.MouseEventHandler | undefined; onMouseOverCapture?: React.MouseEventHandler | undefined; onMouseUp?: React.MouseEventHandler | undefined; onMouseUpCapture?: React.MouseEventHandler | undefined; onSelect?: React.ReactEventHandler | undefined; onSelectCapture?: React.ReactEventHandler | undefined; onTouchCancel?: React.TouchEventHandler | undefined; onTouchCancelCapture?: React.TouchEventHandler | undefined; onTouchEnd?: React.TouchEventHandler | undefined; onTouchEndCapture?: React.TouchEventHandler | undefined; onTouchMove?: React.TouchEventHandler | undefined; onTouchMoveCapture?: React.TouchEventHandler | undefined; onTouchStart?: React.TouchEventHandler | undefined; onTouchStartCapture?: React.TouchEventHandler | undefined; onPointerDown?: React.PointerEventHandler | undefined; onPointerDownCapture?: React.PointerEventHandler | undefined; onPointerMove?: React.PointerEventHandler | undefined; onPointerMoveCapture?: React.PointerEventHandler | undefined; onPointerUp?: React.PointerEventHandler | undefined; onPointerUpCapture?: React.PointerEventHandler | undefined; onPointerCancel?: React.PointerEventHandler | undefined; onPointerCancelCapture?: React.PointerEventHandler | undefined; onPointerEnter?: React.PointerEventHandler | undefined; onPointerEnterCapture?: React.PointerEventHandler | undefined; onPointerLeave?: React.PointerEventHandler | undefined; onPointerLeaveCapture?: React.PointerEventHandler | undefined; onPointerOver?: React.PointerEventHandler | undefined; onPointerOverCapture?: React.PointerEventHandler | undefined; onPointerOut?: React.PointerEventHandler | undefined; onPointerOutCapture?: React.PointerEventHandler | undefined; onGotPointerCapture?: React.PointerEventHandler | undefined; onGotPointerCaptureCapture?: React.PointerEventHandler | undefined; onLostPointerCapture?: React.PointerEventHandler | undefined; onLostPointerCaptureCapture?: React.PointerEventHandler | undefined; onScroll?: React.UIEventHandler | undefined; onScrollCapture?: React.UIEventHandler | undefined; onWheel?: React.WheelEventHandler | undefined; onWheelCapture?: React.WheelEventHandler | undefined; onAnimationStart?: React.AnimationEventHandler | undefined; onAnimationStartCapture?: React.AnimationEventHandler | undefined; onAnimationEnd?: React.AnimationEventHandler | undefined; onAnimationEndCapture?: React.AnimationEventHandler | undefined; onAnimationIteration?: React.AnimationEventHandler | undefined; onAnimationIterationCapture?: React.AnimationEventHandler | undefined; onTransitionEnd?: React.TransitionEventHandler | undefined; onTransitionEndCapture?: React.TransitionEventHandler | undefined; 'data-test-subj'?: string | undefined; css?: ", + ", string | React.JSXElementConstructor> | null | undefined; id?: string | undefined; image?: string | React.ReactElement> | undefined; className?: string | undefined; title?: boolean | React.ReactChild | React.ReactFragment | React.ReactPortal | undefined; onChange?: React.FormEventHandler | undefined; onKeyDown?: React.KeyboardEventHandler | undefined; onClick?: React.MouseEventHandler | undefined; security?: string | undefined; defaultValue?: string | number | readonly string[] | undefined; lang?: string | undefined; defaultChecked?: boolean | undefined; suppressContentEditableWarning?: boolean | undefined; suppressHydrationWarning?: boolean | undefined; accessKey?: string | undefined; contentEditable?: \"inherit\" | Booleanish | undefined; contextMenu?: string | undefined; dir?: string | undefined; draggable?: Booleanish | undefined; placeholder?: string | undefined; slot?: string | undefined; spellCheck?: Booleanish | undefined; style?: React.CSSProperties | undefined; tabIndex?: number | undefined; translate?: \"no\" | \"yes\" | undefined; radioGroup?: string | undefined; role?: React.AriaRole | undefined; about?: string | undefined; datatype?: string | undefined; inlist?: any; prefix?: string | undefined; property?: string | undefined; resource?: string | undefined; typeof?: string | undefined; vocab?: string | undefined; autoCapitalize?: string | undefined; autoCorrect?: string | undefined; autoSave?: string | undefined; itemProp?: string | undefined; itemScope?: boolean | undefined; itemType?: string | undefined; itemID?: string | undefined; itemRef?: string | undefined; results?: number | undefined; unselectable?: \"on\" | \"off\" | undefined; inputMode?: \"none\" | \"email\" | \"search\" | \"text\" | \"url\" | \"tel\" | \"numeric\" | \"decimal\" | undefined; is?: string | undefined; 'aria-activedescendant'?: string | undefined; 'aria-atomic'?: Booleanish | undefined; 'aria-autocomplete'?: \"none\" | \"list\" | \"inline\" | \"both\" | undefined; 'aria-busy'?: Booleanish | undefined; 'aria-checked'?: boolean | \"mixed\" | \"false\" | \"true\" | undefined; 'aria-colcount'?: number | undefined; 'aria-colindex'?: number | undefined; 'aria-colspan'?: number | undefined; 'aria-controls'?: string | undefined; 'aria-current'?: boolean | \"date\" | \"location\" | \"time\" | \"page\" | \"false\" | \"true\" | \"step\" | undefined; 'aria-describedby'?: string | undefined; 'aria-details'?: string | undefined; 'aria-disabled'?: Booleanish | undefined; 'aria-dropeffect'?: \"none\" | \"copy\" | \"link\" | \"execute\" | \"move\" | \"popup\" | undefined; 'aria-errormessage'?: string | undefined; 'aria-expanded'?: Booleanish | undefined; 'aria-flowto'?: string | undefined; 'aria-grabbed'?: Booleanish | undefined; 'aria-haspopup'?: boolean | \"grid\" | \"menu\" | \"false\" | \"true\" | \"dialog\" | \"listbox\" | \"tree\" | undefined; 'aria-hidden'?: Booleanish | undefined; 'aria-invalid'?: boolean | \"false\" | \"true\" | \"grammar\" | \"spelling\" | undefined; 'aria-keyshortcuts'?: string | undefined; 'aria-label'?: string | undefined; 'aria-labelledby'?: string | undefined; 'aria-level'?: number | undefined; 'aria-live'?: \"off\" | \"assertive\" | \"polite\" | undefined; 'aria-modal'?: Booleanish | undefined; 'aria-multiline'?: Booleanish | undefined; 'aria-multiselectable'?: Booleanish | undefined; 'aria-orientation'?: \"horizontal\" | \"vertical\" | undefined; 'aria-owns'?: string | undefined; 'aria-placeholder'?: string | undefined; 'aria-posinset'?: number | undefined; 'aria-pressed'?: boolean | \"mixed\" | \"false\" | \"true\" | undefined; 'aria-readonly'?: Booleanish | undefined; 'aria-relevant'?: \"all\" | \"text\" | \"additions\" | \"additions removals\" | \"additions text\" | \"removals\" | \"removals additions\" | \"removals text\" | \"text additions\" | \"text removals\" | undefined; 'aria-required'?: Booleanish | undefined; 'aria-roledescription'?: string | undefined; 'aria-rowcount'?: number | undefined; 'aria-rowindex'?: number | undefined; 'aria-rowspan'?: number | undefined; 'aria-selected'?: Booleanish | undefined; 'aria-setsize'?: number | undefined; 'aria-sort'?: \"none\" | \"other\" | \"ascending\" | \"descending\" | undefined; 'aria-valuemax'?: number | undefined; 'aria-valuemin'?: number | undefined; 'aria-valuenow'?: number | undefined; 'aria-valuetext'?: string | undefined; dangerouslySetInnerHTML?: { __html: string; } | undefined; onCopy?: React.ClipboardEventHandler | undefined; onCopyCapture?: React.ClipboardEventHandler | undefined; onCut?: React.ClipboardEventHandler | undefined; onCutCapture?: React.ClipboardEventHandler | undefined; onPaste?: React.ClipboardEventHandler | undefined; onPasteCapture?: React.ClipboardEventHandler | undefined; onCompositionEnd?: React.CompositionEventHandler | undefined; onCompositionEndCapture?: React.CompositionEventHandler | undefined; onCompositionStart?: React.CompositionEventHandler | undefined; onCompositionStartCapture?: React.CompositionEventHandler | undefined; onCompositionUpdate?: React.CompositionEventHandler | undefined; onCompositionUpdateCapture?: React.CompositionEventHandler | undefined; onFocus?: React.FocusEventHandler | undefined; onFocusCapture?: React.FocusEventHandler | undefined; onBlur?: React.FocusEventHandler | undefined; onBlurCapture?: React.FocusEventHandler | undefined; onChangeCapture?: React.FormEventHandler | undefined; onBeforeInput?: React.FormEventHandler | undefined; onBeforeInputCapture?: React.FormEventHandler | undefined; onInput?: React.FormEventHandler | undefined; onInputCapture?: React.FormEventHandler | undefined; onReset?: React.FormEventHandler | undefined; onResetCapture?: React.FormEventHandler | undefined; onSubmit?: React.FormEventHandler | undefined; onSubmitCapture?: React.FormEventHandler | undefined; onInvalid?: React.FormEventHandler | undefined; onInvalidCapture?: React.FormEventHandler | undefined; onLoad?: React.ReactEventHandler | undefined; onLoadCapture?: React.ReactEventHandler | undefined; onErrorCapture?: React.ReactEventHandler | undefined; onKeyDownCapture?: React.KeyboardEventHandler | undefined; onKeyPress?: React.KeyboardEventHandler | undefined; onKeyPressCapture?: React.KeyboardEventHandler | undefined; onKeyUp?: React.KeyboardEventHandler | undefined; onKeyUpCapture?: React.KeyboardEventHandler | undefined; onAbort?: React.ReactEventHandler | undefined; onAbortCapture?: React.ReactEventHandler | undefined; onCanPlay?: React.ReactEventHandler | undefined; onCanPlayCapture?: React.ReactEventHandler | undefined; onCanPlayThrough?: React.ReactEventHandler | undefined; onCanPlayThroughCapture?: React.ReactEventHandler | undefined; onDurationChange?: React.ReactEventHandler | undefined; onDurationChangeCapture?: React.ReactEventHandler | undefined; onEmptied?: React.ReactEventHandler | undefined; onEmptiedCapture?: React.ReactEventHandler | undefined; onEncrypted?: React.ReactEventHandler | undefined; onEncryptedCapture?: React.ReactEventHandler | undefined; onEnded?: React.ReactEventHandler | undefined; onEndedCapture?: React.ReactEventHandler | undefined; onLoadedData?: React.ReactEventHandler | undefined; onLoadedDataCapture?: React.ReactEventHandler | undefined; onLoadedMetadata?: React.ReactEventHandler | undefined; onLoadedMetadataCapture?: React.ReactEventHandler | undefined; onLoadStart?: React.ReactEventHandler | undefined; onLoadStartCapture?: React.ReactEventHandler | undefined; onPause?: React.ReactEventHandler | undefined; onPauseCapture?: React.ReactEventHandler | undefined; onPlay?: React.ReactEventHandler | undefined; onPlayCapture?: React.ReactEventHandler | undefined; onPlaying?: React.ReactEventHandler | undefined; onPlayingCapture?: React.ReactEventHandler | undefined; onProgress?: React.ReactEventHandler | undefined; onProgressCapture?: React.ReactEventHandler | undefined; onRateChange?: React.ReactEventHandler | undefined; onRateChangeCapture?: React.ReactEventHandler | undefined; onSeeked?: React.ReactEventHandler | undefined; onSeekedCapture?: React.ReactEventHandler | undefined; onSeeking?: React.ReactEventHandler | undefined; onSeekingCapture?: React.ReactEventHandler | undefined; onStalled?: React.ReactEventHandler | undefined; onStalledCapture?: React.ReactEventHandler | undefined; onSuspend?: React.ReactEventHandler | undefined; onSuspendCapture?: React.ReactEventHandler | undefined; onTimeUpdate?: React.ReactEventHandler | undefined; onTimeUpdateCapture?: React.ReactEventHandler | undefined; onVolumeChange?: React.ReactEventHandler | undefined; onVolumeChangeCapture?: React.ReactEventHandler | undefined; onWaiting?: React.ReactEventHandler | undefined; onWaitingCapture?: React.ReactEventHandler | undefined; onAuxClick?: React.MouseEventHandler | undefined; onAuxClickCapture?: React.MouseEventHandler | undefined; onClickCapture?: React.MouseEventHandler | undefined; onContextMenu?: React.MouseEventHandler | undefined; onContextMenuCapture?: React.MouseEventHandler | undefined; onDoubleClick?: React.MouseEventHandler | undefined; onDoubleClickCapture?: React.MouseEventHandler | undefined; onDrag?: React.DragEventHandler | undefined; onDragCapture?: React.DragEventHandler | undefined; onDragEnd?: React.DragEventHandler | undefined; onDragEndCapture?: React.DragEventHandler | undefined; onDragEnter?: React.DragEventHandler | undefined; onDragEnterCapture?: React.DragEventHandler | undefined; onDragExit?: React.DragEventHandler | undefined; onDragExitCapture?: React.DragEventHandler | undefined; onDragLeave?: React.DragEventHandler | undefined; onDragLeaveCapture?: React.DragEventHandler | undefined; onDragOver?: React.DragEventHandler | undefined; onDragOverCapture?: React.DragEventHandler | undefined; onDragStart?: React.DragEventHandler | undefined; onDragStartCapture?: React.DragEventHandler | undefined; onDrop?: React.DragEventHandler | undefined; onDropCapture?: React.DragEventHandler | undefined; onMouseDown?: React.MouseEventHandler | undefined; onMouseDownCapture?: React.MouseEventHandler | undefined; onMouseEnter?: React.MouseEventHandler | undefined; onMouseLeave?: React.MouseEventHandler | undefined; onMouseMove?: React.MouseEventHandler | undefined; onMouseMoveCapture?: React.MouseEventHandler | undefined; onMouseOut?: React.MouseEventHandler | undefined; onMouseOutCapture?: React.MouseEventHandler | undefined; onMouseOver?: React.MouseEventHandler | undefined; onMouseOverCapture?: React.MouseEventHandler | undefined; onMouseUp?: React.MouseEventHandler | undefined; onMouseUpCapture?: React.MouseEventHandler | undefined; onSelect?: React.ReactEventHandler | undefined; onSelectCapture?: React.ReactEventHandler | undefined; onTouchCancel?: React.TouchEventHandler | undefined; onTouchCancelCapture?: React.TouchEventHandler | undefined; onTouchEnd?: React.TouchEventHandler | undefined; onTouchEndCapture?: React.TouchEventHandler | undefined; onTouchMove?: React.TouchEventHandler | undefined; onTouchMoveCapture?: React.TouchEventHandler | undefined; onTouchStart?: React.TouchEventHandler | undefined; onTouchStartCapture?: React.TouchEventHandler | undefined; onPointerDown?: React.PointerEventHandler | undefined; onPointerDownCapture?: React.PointerEventHandler | undefined; onPointerMove?: React.PointerEventHandler | undefined; onPointerMoveCapture?: React.PointerEventHandler | undefined; onPointerUp?: React.PointerEventHandler | undefined; onPointerUpCapture?: React.PointerEventHandler | undefined; onPointerCancel?: React.PointerEventHandler | undefined; onPointerCancelCapture?: React.PointerEventHandler | undefined; onPointerEnter?: React.PointerEventHandler | undefined; onPointerEnterCapture?: React.PointerEventHandler | undefined; onPointerLeave?: React.PointerEventHandler | undefined; onPointerLeaveCapture?: React.PointerEventHandler | undefined; onPointerOver?: React.PointerEventHandler | undefined; onPointerOverCapture?: React.PointerEventHandler | undefined; onPointerOut?: React.PointerEventHandler | undefined; onPointerOutCapture?: React.PointerEventHandler | undefined; onGotPointerCapture?: React.PointerEventHandler | undefined; onGotPointerCaptureCapture?: React.PointerEventHandler | undefined; onLostPointerCapture?: React.PointerEventHandler | undefined; onLostPointerCaptureCapture?: React.PointerEventHandler | undefined; onScroll?: React.UIEventHandler | undefined; onScrollCapture?: React.UIEventHandler | undefined; onWheel?: React.WheelEventHandler | undefined; onWheelCapture?: React.WheelEventHandler | undefined; onAnimationStart?: React.AnimationEventHandler | undefined; onAnimationStartCapture?: React.AnimationEventHandler | undefined; onAnimationEnd?: React.AnimationEventHandler | undefined; onAnimationEndCapture?: React.AnimationEventHandler | undefined; onAnimationIteration?: React.AnimationEventHandler | undefined; onAnimationIterationCapture?: React.AnimationEventHandler | undefined; onTransitionEnd?: React.TransitionEventHandler | undefined; onTransitionEndCapture?: React.TransitionEventHandler | undefined; 'data-test-subj'?: string | undefined; css?: ", "Interpolation", "<", "Theme", @@ -204,7 +204,7 @@ "ToolTipPositions", " | undefined; anchorProps?: (", "CommonProps", - " & React.HTMLAttributes) | undefined; title?: string | undefined; color?: \"subdued\" | \"accent\" | \"hollow\" | undefined; size?: \"m\" | \"s\" | undefined; } & ", + " & React.HTMLAttributes) | undefined; title?: string | undefined; color?: \"subdued\" | \"accent\" | \"hollow\" | undefined; size?: \"m\" | \"s\" | undefined; alignment?: \"middle\" | \"baseline\" | undefined; } & ", "DisambiguateSet", " & LabelAsString) | (", "CommonProps", @@ -220,7 +220,7 @@ "ToolTipPositions", " | undefined; anchorProps?: (", "CommonProps", - " & React.HTMLAttributes) | undefined; title?: string | undefined; color?: \"subdued\" | \"accent\" | \"hollow\" | undefined; size?: \"m\" | \"s\" | undefined; } & ", + " & React.HTMLAttributes) | undefined; title?: string | undefined; color?: \"subdued\" | \"accent\" | \"hollow\" | undefined; size?: \"m\" | \"s\" | undefined; alignment?: \"middle\" | \"baseline\" | undefined; } & ", "DisambiguateSet", " & ", "DisambiguateSet", @@ -240,7 +240,7 @@ "ToolTipPositions", " | undefined; anchorProps?: (", "CommonProps", - " & React.HTMLAttributes) | undefined; title?: string | undefined; color?: \"subdued\" | \"accent\" | \"hollow\" | undefined; size?: \"m\" | \"s\" | undefined; } & ", + " & React.HTMLAttributes) | undefined; title?: string | undefined; color?: \"subdued\" | \"accent\" | \"hollow\" | undefined; size?: \"m\" | \"s\" | undefined; alignment?: \"middle\" | \"baseline\" | undefined; } & ", "DisambiguateSet", " & LabelAsString) | (", "CommonProps", @@ -258,7 +258,7 @@ "ToolTipPositions", " | undefined; anchorProps?: (", "CommonProps", - " & React.HTMLAttributes) | undefined; title?: string | undefined; color?: \"subdued\" | \"accent\" | \"hollow\" | undefined; size?: \"m\" | \"s\" | undefined; } & ", + " & React.HTMLAttributes) | undefined; title?: string | undefined; color?: \"subdued\" | \"accent\" | \"hollow\" | undefined; size?: \"m\" | \"s\" | undefined; alignment?: \"middle\" | \"baseline\" | undefined; } & ", "DisambiguateSet", " & ", "DisambiguateSet", @@ -278,7 +278,7 @@ "ToolTipPositions", " | undefined; anchorProps?: (", "CommonProps", - " & React.HTMLAttributes) | undefined; title?: string | undefined; color?: \"subdued\" | \"accent\" | \"hollow\" | undefined; size?: \"m\" | \"s\" | undefined; } & ", + " & React.HTMLAttributes) | undefined; title?: string | undefined; color?: \"subdued\" | \"accent\" | \"hollow\" | undefined; size?: \"m\" | \"s\" | undefined; alignment?: \"middle\" | \"baseline\" | undefined; } & ", "DisambiguateSet", " & ", "DisambiguateSet", @@ -298,7 +298,7 @@ "ToolTipPositions", " | undefined; anchorProps?: (", "CommonProps", - " & React.HTMLAttributes) | undefined; title?: string | undefined; color?: \"subdued\" | \"accent\" | \"hollow\" | undefined; size?: \"m\" | \"s\" | undefined; } & ", + " & React.HTMLAttributes) | undefined; title?: string | undefined; color?: \"subdued\" | \"accent\" | \"hollow\" | undefined; size?: \"m\" | \"s\" | undefined; alignment?: \"middle\" | \"baseline\" | undefined; } & ", "DisambiguateSet", " & LabelAsString) | (", "CommonProps", @@ -316,7 +316,7 @@ "ToolTipPositions", " | undefined; anchorProps?: (", "CommonProps", - " & React.HTMLAttributes) | undefined; title?: string | undefined; color?: \"subdued\" | \"accent\" | \"hollow\" | undefined; size?: \"m\" | \"s\" | undefined; } & ", + " & React.HTMLAttributes) | undefined; title?: string | undefined; color?: \"subdued\" | \"accent\" | \"hollow\" | undefined; size?: \"m\" | \"s\" | undefined; alignment?: \"middle\" | \"baseline\" | undefined; } & ", "DisambiguateSet", " & ", "DisambiguateSet", @@ -336,7 +336,7 @@ "ToolTipPositions", " | undefined; anchorProps?: (", "CommonProps", - " & React.HTMLAttributes) | undefined; title?: string | undefined; color?: \"subdued\" | \"accent\" | \"hollow\" | undefined; size?: \"m\" | \"s\" | undefined; } & ", + " & React.HTMLAttributes) | undefined; title?: string | undefined; color?: \"subdued\" | \"accent\" | \"hollow\" | undefined; size?: \"m\" | \"s\" | undefined; alignment?: \"middle\" | \"baseline\" | undefined; } & ", "DisambiguateSet", " & ", "DisambiguateSet", diff --git a/api_docs/kbn_shared_ux_card_no_data.mdx b/api_docs/kbn_shared_ux_card_no_data.mdx index a3ebf65905949..70f22a645a033 100644 --- a/api_docs/kbn_shared_ux_card_no_data.mdx +++ b/api_docs/kbn_shared_ux_card_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-card-no-data title: "@kbn/shared-ux-card-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-card-no-data plugin -date: 2022-11-29 +date: 2022-12-06 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 4de73720db58e..3e77af0a80a2a 100644 --- a/api_docs/kbn_shared_ux_card_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_card_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-card-no-data-mocks title: "@kbn/shared-ux-card-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-card-no-data-mocks plugin -date: 2022-11-29 +date: 2022-12-06 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_file_context.devdocs.json b/api_docs/kbn_shared_ux_file_context.devdocs.json new file mode 100644 index 0000000000000..02025b778807c --- /dev/null +++ b/api_docs/kbn_shared_ux_file_context.devdocs.json @@ -0,0 +1,117 @@ +{ + "id": "@kbn/shared-ux-file-context", + "client": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "server": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "common": { + "classes": [], + "functions": [ + { + "parentPluginId": "@kbn/shared-ux-file-context", + "id": "def-common.FilesContext", + "type": "Function", + "tags": [], + "label": "FilesContext", + "description": [], + "signature": [ + "({ client, children }: React.PropsWithChildren) => JSX.Element" + ], + "path": "packages/shared-ux/file/context/src/index.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/shared-ux-file-context", + "id": "def-common.FilesContext.$1", + "type": "CompoundType", + "tags": [], + "label": "{ client, children }", + "description": [], + "signature": [ + "React.PropsWithChildren" + ], + "path": "packages/shared-ux/file/context/src/index.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/shared-ux-file-context", + "id": "def-common.useFilesContext", + "type": "Function", + "tags": [], + "label": "useFilesContext", + "description": [], + "signature": [ + "() => ", + { + "pluginId": "@kbn/shared-ux-file-context", + "scope": "common", + "docId": "kibKbnSharedUxFileContextPluginApi", + "section": "def-common.FilesContextValue", + "text": "FilesContextValue" + } + ], + "path": "packages/shared-ux/file/context/src/index.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [], + "initialIsOpen": false + } + ], + "interfaces": [ + { + "parentPluginId": "@kbn/shared-ux-file-context", + "id": "def-common.FilesContextValue", + "type": "Interface", + "tags": [], + "label": "FilesContextValue", + "description": [], + "path": "packages/shared-ux/file/context/src/index.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/shared-ux-file-context", + "id": "def-common.FilesContextValue.client", + "type": "Object", + "tags": [], + "label": "client", + "description": [ + "\nA files client that will be used process uploads." + ], + "signature": [ + "BaseFilesClient", + "" + ], + "path": "packages/shared-ux/file/context/src/index.tsx", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + } + ], + "enums": [], + "misc": [], + "objects": [] + } +} \ No newline at end of file diff --git a/api_docs/kbn_shared_ux_file_context.mdx b/api_docs/kbn_shared_ux_file_context.mdx new file mode 100644 index 0000000000000..e9602d0f013ca --- /dev/null +++ b/api_docs/kbn_shared_ux_file_context.mdx @@ -0,0 +1,33 @@ +--- +#### +#### This document is auto-generated and is meant to be viewed inside our experimental, new docs system. +#### Reach out in #docs-engineering for more info. +#### +id: kibKbnSharedUxFileContextPluginApi +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: 2022-12-06 +tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-context'] +--- +import kbnSharedUxFileContextObj from './kbn_shared_ux_file_context.devdocs.json'; + + + +Contact [Owner missing] for questions regarding this plugin. + +**Code health stats** + +| Public API count | Any count | Items lacking comments | Missing exports | +|-------------------|-----------|------------------------|-----------------| +| 5 | 0 | 4 | 0 | + +## Common + +### Functions + + +### Interfaces + + diff --git a/api_docs/kbn_shared_ux_file_image.devdocs.json b/api_docs/kbn_shared_ux_file_image.devdocs.json index b1d29de390143..5d3350f6cf444 100644 --- a/api_docs/kbn_shared_ux_file_image.devdocs.json +++ b/api_docs/kbn_shared_ux_file_image.devdocs.json @@ -82,7 +82,9 @@ "label": "Props", "description": [], "signature": [ - "{ meta?: any; } & ", + "{ meta?: ", + "FileImageMetadata", + " | undefined; } & ", "EuiImageProps" ], "path": "packages/shared-ux/file/image/impl/src/image.tsx", diff --git a/api_docs/kbn_shared_ux_file_image.mdx b/api_docs/kbn_shared_ux_file_image.mdx index 74e18d3c3edec..5f23b2f93f934 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: 2022-11-29 +date: 2022-12-06 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 975f46888cc8f..efb441df915b6 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: 2022-11-29 +date: 2022-12-06 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.devdocs.json b/api_docs/kbn_shared_ux_file_mocks.devdocs.json new file mode 100644 index 0000000000000..67aaba2cc7ed1 --- /dev/null +++ b/api_docs/kbn_shared_ux_file_mocks.devdocs.json @@ -0,0 +1,55 @@ +{ + "id": "@kbn/shared-ux-file-mocks", + "client": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "server": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "common": { + "classes": [], + "functions": [ + { + "parentPluginId": "@kbn/shared-ux-file-mocks", + "id": "def-common.createMockFilesClient", + "type": "Function", + "tags": [], + "label": "createMockFilesClient", + "description": [], + "signature": [ + "() => ", + { + "pluginId": "@kbn/utility-types-jest", + "scope": "server", + "docId": "kibKbnUtilityTypesJestPluginApi", + "section": "def-server.DeeplyMockedKeys", + "text": "DeeplyMockedKeys" + }, + "<", + "BaseFilesClient", + ">" + ], + "path": "packages/shared-ux/file/mocks/index.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [], + "initialIsOpen": false + } + ], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + } +} \ No newline at end of file diff --git a/api_docs/kbn_shared_ux_file_mocks.mdx b/api_docs/kbn_shared_ux_file_mocks.mdx new file mode 100644 index 0000000000000..e857d341cedae --- /dev/null +++ b/api_docs/kbn_shared_ux_file_mocks.mdx @@ -0,0 +1,30 @@ +--- +#### +#### This document is auto-generated and is meant to be viewed inside our experimental, new docs system. +#### Reach out in #docs-engineering for more info. +#### +id: kibKbnSharedUxFileMocksPluginApi +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: 2022-12-06 +tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-mocks'] +--- +import kbnSharedUxFileMocksObj from './kbn_shared_ux_file_mocks.devdocs.json'; + + + +Contact [Owner missing] for questions regarding this plugin. + +**Code health stats** + +| Public API count | Any count | Items lacking comments | Missing exports | +|-------------------|-----------|------------------------|-----------------| +| 1 | 0 | 1 | 0 | + +## Common + +### Functions + + diff --git a/api_docs/kbn_shared_ux_file_util.devdocs.json b/api_docs/kbn_shared_ux_file_util.devdocs.json index c14e553be0947..c471a74aeec8e 100644 --- a/api_docs/kbn_shared_ux_file_util.devdocs.json +++ b/api_docs/kbn_shared_ux_file_util.devdocs.json @@ -143,7 +143,9 @@ "\nExtract image metadata, assumes that file or blob as an image!" ], "signature": [ - "(file: Blob | File) => Promise" + "(file: Blob | File) => Promise<", + "FileImageMetadata", + " | undefined>" ], "path": "packages/shared-ux/file/util/src/image_metadata.ts", "deprecated": false, @@ -212,6 +214,42 @@ ], "returnComment": [], "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/shared-ux-file-util", + "id": "def-common.useBehaviorSubject", + "type": "Function", + "tags": [], + "label": "useBehaviorSubject", + "description": [], + "signature": [ + "(o$: ", + "BehaviorSubject", + ") => T" + ], + "path": "packages/shared-ux/file/util/src/use_behavior_subject.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/shared-ux-file-util", + "id": "def-common.useBehaviorSubject.$1", + "type": "Object", + "tags": [], + "label": "o$", + "description": [], + "signature": [ + "BehaviorSubject", + "" + ], + "path": "packages/shared-ux/file/util/src/use_behavior_subject.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false } ], "interfaces": [], @@ -225,7 +263,9 @@ "label": "ImageMetadataFactory", "description": [], "signature": [ - "(file: Blob | File) => Promise" + "(file: Blob | File) => Promise<", + "FileImageMetadata", + " | undefined>" ], "path": "packages/shared-ux/file/util/src/image_metadata.ts", "deprecated": false, diff --git a/api_docs/kbn_shared_ux_file_util.mdx b/api_docs/kbn_shared_ux_file_util.mdx index c95cc9b4dded6..430f2cc900a82 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: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-util'] --- import kbnSharedUxFileUtilObj from './kbn_shared_ux_file_util.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Owner missing] for questions regarding this plugin. | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 15 | 0 | 13 | 0 | +| 17 | 0 | 15 | 0 | ## Common diff --git a/api_docs/kbn_shared_ux_link_redirect_app.mdx b/api_docs/kbn_shared_ux_link_redirect_app.mdx index 92d443c8dfe0d..e2854a67bfab8 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: 2022-11-29 +date: 2022-12-06 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 13919bdd9c954..644155759d1c7 100644 --- a/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx +++ b/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-link-redirect-app-mocks title: "@kbn/shared-ux-link-redirect-app-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-link-redirect-app-mocks plugin -date: 2022-11-29 +date: 2022-12-06 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 3168673711040..ec169705ca905 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: 2022-11-29 +date: 2022-12-06 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.devdocs.json b/api_docs/kbn_shared_ux_markdown_mocks.devdocs.json index 0f5ffb13f1421..addc3f7f83a31 100644 --- a/api_docs/kbn_shared_ux_markdown_mocks.devdocs.json +++ b/api_docs/kbn_shared_ux_markdown_mocks.devdocs.json @@ -433,7 +433,7 @@ "label": "getServices", "description": [], "signature": [ - "() => { children?: React.ReactNode; value?: string | undefined; onError?: React.ReactEventHandler | undefined; hidden?: boolean | undefined; color?: string | undefined; id?: string | undefined; className?: string | undefined; title?: string | undefined; onChange?: ((value: string) => void) | undefined; onKeyDown?: React.KeyboardEventHandler | undefined; onClick?: React.MouseEventHandler | undefined; security?: string | undefined; defaultValue?: string | number | readonly string[] | undefined; lang?: string | undefined; defaultChecked?: boolean | undefined; suppressContentEditableWarning?: boolean | undefined; suppressHydrationWarning?: boolean | undefined; accessKey?: string | undefined; contentEditable?: \"inherit\" | Booleanish | undefined; contextMenu?: string | undefined; dir?: string | undefined; draggable?: Booleanish | undefined; placeholder?: string | undefined; slot?: string | undefined; spellCheck?: Booleanish | undefined; style?: React.CSSProperties | undefined; tabIndex?: number | undefined; translate?: \"no\" | \"yes\" | undefined; radioGroup?: string | undefined; role?: React.AriaRole | undefined; about?: string | undefined; datatype?: string | undefined; inlist?: any; prefix?: string | undefined; property?: string | undefined; resource?: string | undefined; typeof?: string | undefined; vocab?: string | undefined; autoCapitalize?: string | undefined; autoCorrect?: string | undefined; autoSave?: string | undefined; itemProp?: string | undefined; itemScope?: boolean | undefined; itemType?: string | undefined; itemID?: string | undefined; itemRef?: string | undefined; results?: number | undefined; unselectable?: \"on\" | \"off\" | undefined; inputMode?: \"none\" | \"email\" | \"search\" | \"text\" | \"tel\" | \"url\" | \"numeric\" | \"decimal\" | undefined; is?: string | undefined; 'aria-activedescendant'?: string | undefined; 'aria-atomic'?: Booleanish | undefined; 'aria-autocomplete'?: \"none\" | \"list\" | \"inline\" | \"both\" | undefined; 'aria-busy'?: Booleanish | undefined; 'aria-checked'?: boolean | \"mixed\" | \"false\" | \"true\" | undefined; 'aria-colcount'?: number | undefined; 'aria-colindex'?: number | undefined; 'aria-colspan'?: number | undefined; 'aria-controls'?: string | undefined; 'aria-current'?: boolean | \"date\" | \"location\" | \"time\" | \"page\" | \"false\" | \"true\" | \"step\" | undefined; 'aria-describedby'?: string | undefined; 'aria-details'?: string | undefined; 'aria-disabled'?: Booleanish | undefined; 'aria-dropeffect'?: \"none\" | \"copy\" | \"link\" | \"execute\" | \"move\" | \"popup\" | undefined; 'aria-errormessage'?: string | undefined; 'aria-expanded'?: Booleanish | undefined; 'aria-flowto'?: string | undefined; 'aria-grabbed'?: Booleanish | undefined; 'aria-haspopup'?: boolean | \"grid\" | \"menu\" | \"false\" | \"true\" | \"dialog\" | \"listbox\" | \"tree\" | undefined; 'aria-hidden'?: Booleanish | undefined; 'aria-invalid'?: boolean | \"false\" | \"true\" | \"grammar\" | \"spelling\" | undefined; 'aria-keyshortcuts'?: string | undefined; 'aria-label'?: string | undefined; 'aria-labelledby'?: string | undefined; 'aria-level'?: number | undefined; 'aria-live'?: \"off\" | \"assertive\" | \"polite\" | undefined; 'aria-modal'?: Booleanish | undefined; 'aria-multiline'?: Booleanish | undefined; 'aria-multiselectable'?: Booleanish | undefined; 'aria-orientation'?: \"horizontal\" | \"vertical\" | undefined; 'aria-owns'?: string | undefined; 'aria-placeholder'?: string | undefined; 'aria-posinset'?: number | undefined; 'aria-pressed'?: boolean | \"mixed\" | \"false\" | \"true\" | undefined; 'aria-readonly'?: Booleanish | undefined; 'aria-relevant'?: \"all\" | \"text\" | \"additions\" | \"additions removals\" | \"additions text\" | \"removals\" | \"removals additions\" | \"removals text\" | \"text additions\" | \"text removals\" | undefined; 'aria-required'?: Booleanish | undefined; 'aria-roledescription'?: string | undefined; 'aria-rowcount'?: number | undefined; 'aria-rowindex'?: number | undefined; 'aria-rowspan'?: number | undefined; 'aria-selected'?: Booleanish | undefined; 'aria-setsize'?: number | undefined; 'aria-sort'?: \"none\" | \"other\" | \"ascending\" | \"descending\" | undefined; 'aria-valuemax'?: number | undefined; 'aria-valuemin'?: number | undefined; 'aria-valuenow'?: number | undefined; 'aria-valuetext'?: string | undefined; dangerouslySetInnerHTML?: { __html: string; } | undefined; onCopy?: React.ClipboardEventHandler | undefined; onCopyCapture?: React.ClipboardEventHandler | undefined; onCut?: React.ClipboardEventHandler | undefined; onCutCapture?: React.ClipboardEventHandler | undefined; onPaste?: React.ClipboardEventHandler | undefined; onPasteCapture?: React.ClipboardEventHandler | undefined; onCompositionEnd?: React.CompositionEventHandler | undefined; onCompositionEndCapture?: React.CompositionEventHandler | undefined; onCompositionStart?: React.CompositionEventHandler | undefined; onCompositionStartCapture?: React.CompositionEventHandler | undefined; onCompositionUpdate?: React.CompositionEventHandler | undefined; onCompositionUpdateCapture?: React.CompositionEventHandler | undefined; onFocus?: React.FocusEventHandler | undefined; onFocusCapture?: React.FocusEventHandler | undefined; onBlur?: React.FocusEventHandler | undefined; onBlurCapture?: React.FocusEventHandler | undefined; onChangeCapture?: React.FormEventHandler | undefined; onBeforeInput?: React.FormEventHandler | undefined; onBeforeInputCapture?: React.FormEventHandler | undefined; onInput?: React.FormEventHandler | undefined; onInputCapture?: React.FormEventHandler | undefined; onReset?: React.FormEventHandler | undefined; onResetCapture?: React.FormEventHandler | undefined; onSubmit?: React.FormEventHandler | undefined; onSubmitCapture?: React.FormEventHandler | undefined; onInvalid?: React.FormEventHandler | undefined; onInvalidCapture?: React.FormEventHandler | undefined; onLoad?: React.ReactEventHandler | undefined; onLoadCapture?: React.ReactEventHandler | undefined; onErrorCapture?: React.ReactEventHandler | undefined; onKeyDownCapture?: React.KeyboardEventHandler | undefined; onKeyPress?: React.KeyboardEventHandler | undefined; onKeyPressCapture?: React.KeyboardEventHandler | undefined; onKeyUp?: React.KeyboardEventHandler | undefined; onKeyUpCapture?: React.KeyboardEventHandler | undefined; onAbort?: React.ReactEventHandler | undefined; onAbortCapture?: React.ReactEventHandler | undefined; onCanPlay?: React.ReactEventHandler | undefined; onCanPlayCapture?: React.ReactEventHandler | undefined; onCanPlayThrough?: React.ReactEventHandler | undefined; onCanPlayThroughCapture?: React.ReactEventHandler | undefined; onDurationChange?: React.ReactEventHandler | undefined; onDurationChangeCapture?: React.ReactEventHandler | undefined; onEmptied?: React.ReactEventHandler | undefined; onEmptiedCapture?: React.ReactEventHandler | undefined; onEncrypted?: React.ReactEventHandler | undefined; onEncryptedCapture?: React.ReactEventHandler | undefined; onEnded?: React.ReactEventHandler | undefined; onEndedCapture?: React.ReactEventHandler | undefined; onLoadedData?: React.ReactEventHandler | undefined; onLoadedDataCapture?: React.ReactEventHandler | undefined; onLoadedMetadata?: React.ReactEventHandler | undefined; onLoadedMetadataCapture?: React.ReactEventHandler | undefined; onLoadStart?: React.ReactEventHandler | undefined; onLoadStartCapture?: React.ReactEventHandler | undefined; onPause?: React.ReactEventHandler | undefined; onPauseCapture?: React.ReactEventHandler | undefined; onPlay?: React.ReactEventHandler | undefined; onPlayCapture?: React.ReactEventHandler | undefined; onPlaying?: React.ReactEventHandler | undefined; onPlayingCapture?: React.ReactEventHandler | undefined; onProgress?: React.ReactEventHandler | undefined; onProgressCapture?: React.ReactEventHandler | undefined; onRateChange?: React.ReactEventHandler | undefined; onRateChangeCapture?: React.ReactEventHandler | undefined; onSeeked?: React.ReactEventHandler | undefined; onSeekedCapture?: React.ReactEventHandler | undefined; onSeeking?: React.ReactEventHandler | undefined; onSeekingCapture?: React.ReactEventHandler | undefined; onStalled?: React.ReactEventHandler | undefined; onStalledCapture?: React.ReactEventHandler | undefined; onSuspend?: React.ReactEventHandler | undefined; onSuspendCapture?: React.ReactEventHandler | undefined; onTimeUpdate?: React.ReactEventHandler | undefined; onTimeUpdateCapture?: React.ReactEventHandler | undefined; onVolumeChange?: React.ReactEventHandler | undefined; onVolumeChangeCapture?: React.ReactEventHandler | undefined; onWaiting?: React.ReactEventHandler | undefined; onWaitingCapture?: React.ReactEventHandler | undefined; onAuxClick?: React.MouseEventHandler | undefined; onAuxClickCapture?: React.MouseEventHandler | undefined; onClickCapture?: React.MouseEventHandler | undefined; onContextMenu?: React.MouseEventHandler | undefined; onContextMenuCapture?: React.MouseEventHandler | undefined; onDoubleClick?: React.MouseEventHandler | undefined; onDoubleClickCapture?: React.MouseEventHandler | undefined; onDrag?: React.DragEventHandler | undefined; onDragCapture?: React.DragEventHandler | undefined; onDragEnd?: React.DragEventHandler | undefined; onDragEndCapture?: React.DragEventHandler | undefined; onDragEnter?: React.DragEventHandler | undefined; onDragEnterCapture?: React.DragEventHandler | undefined; onDragExit?: React.DragEventHandler | undefined; onDragExitCapture?: React.DragEventHandler | undefined; onDragLeave?: React.DragEventHandler | undefined; onDragLeaveCapture?: React.DragEventHandler | undefined; onDragOver?: React.DragEventHandler | undefined; onDragOverCapture?: React.DragEventHandler | undefined; onDragStart?: React.DragEventHandler | undefined; onDragStartCapture?: React.DragEventHandler | undefined; onDrop?: React.DragEventHandler | undefined; onDropCapture?: React.DragEventHandler | undefined; onMouseDown?: React.MouseEventHandler | undefined; onMouseDownCapture?: React.MouseEventHandler | undefined; onMouseEnter?: React.MouseEventHandler | undefined; onMouseLeave?: React.MouseEventHandler | undefined; onMouseMove?: React.MouseEventHandler | undefined; onMouseMoveCapture?: React.MouseEventHandler | undefined; onMouseOut?: React.MouseEventHandler | undefined; onMouseOutCapture?: React.MouseEventHandler | undefined; onMouseOver?: React.MouseEventHandler | undefined; onMouseOverCapture?: React.MouseEventHandler | undefined; onMouseUp?: React.MouseEventHandler | undefined; onMouseUpCapture?: React.MouseEventHandler | undefined; onSelect?: React.ReactEventHandler | undefined; onSelectCapture?: React.ReactEventHandler | undefined; onTouchCancel?: React.TouchEventHandler | undefined; onTouchCancelCapture?: React.TouchEventHandler | undefined; onTouchEnd?: React.TouchEventHandler | undefined; onTouchEndCapture?: React.TouchEventHandler | undefined; onTouchMove?: React.TouchEventHandler | undefined; onTouchMoveCapture?: React.TouchEventHandler | undefined; onTouchStart?: React.TouchEventHandler | undefined; onTouchStartCapture?: React.TouchEventHandler | undefined; onPointerDown?: React.PointerEventHandler | undefined; onPointerDownCapture?: React.PointerEventHandler | undefined; onPointerMove?: React.PointerEventHandler | undefined; onPointerMoveCapture?: React.PointerEventHandler | undefined; onPointerUp?: React.PointerEventHandler | undefined; onPointerUpCapture?: React.PointerEventHandler | undefined; onPointerCancel?: React.PointerEventHandler | undefined; onPointerCancelCapture?: React.PointerEventHandler | undefined; onPointerEnter?: React.PointerEventHandler | undefined; onPointerEnterCapture?: React.PointerEventHandler | undefined; onPointerLeave?: React.PointerEventHandler | undefined; onPointerLeaveCapture?: React.PointerEventHandler | undefined; onPointerOver?: React.PointerEventHandler | undefined; onPointerOverCapture?: React.PointerEventHandler | undefined; onPointerOut?: React.PointerEventHandler | undefined; onPointerOutCapture?: React.PointerEventHandler | undefined; onGotPointerCapture?: React.PointerEventHandler | undefined; onGotPointerCaptureCapture?: React.PointerEventHandler | undefined; onLostPointerCapture?: React.PointerEventHandler | undefined; onLostPointerCaptureCapture?: React.PointerEventHandler | undefined; onScroll?: React.UIEventHandler | undefined; onScrollCapture?: React.UIEventHandler | undefined; onWheel?: React.WheelEventHandler | undefined; onWheelCapture?: React.WheelEventHandler | undefined; onAnimationStart?: React.AnimationEventHandler | undefined; onAnimationStartCapture?: React.AnimationEventHandler | undefined; onAnimationEnd?: React.AnimationEventHandler | undefined; onAnimationEndCapture?: React.AnimationEventHandler | undefined; onAnimationIteration?: React.AnimationEventHandler | undefined; onAnimationIterationCapture?: React.AnimationEventHandler | undefined; onTransitionEnd?: React.TransitionEventHandler | undefined; onTransitionEndCapture?: React.TransitionEventHandler | undefined; 'data-test-subj'?: string | undefined; css?: ", + "() => { children?: React.ReactNode; value?: string | undefined; onError?: React.ReactEventHandler | undefined; hidden?: boolean | undefined; color?: string | undefined; id?: string | undefined; className?: string | undefined; title?: string | undefined; onChange?: ((value: string) => void) | undefined; onKeyDown?: React.KeyboardEventHandler | undefined; onClick?: React.MouseEventHandler | undefined; security?: string | undefined; defaultValue?: string | number | readonly string[] | undefined; lang?: string | undefined; defaultChecked?: boolean | undefined; suppressContentEditableWarning?: boolean | undefined; suppressHydrationWarning?: boolean | undefined; accessKey?: string | undefined; contentEditable?: \"inherit\" | Booleanish | undefined; contextMenu?: string | undefined; dir?: string | undefined; draggable?: Booleanish | undefined; placeholder?: string | undefined; slot?: string | undefined; spellCheck?: Booleanish | undefined; style?: React.CSSProperties | undefined; tabIndex?: number | undefined; translate?: \"no\" | \"yes\" | undefined; radioGroup?: string | undefined; role?: React.AriaRole | undefined; about?: string | undefined; datatype?: string | undefined; inlist?: any; prefix?: string | undefined; property?: string | undefined; resource?: string | undefined; typeof?: string | undefined; vocab?: string | undefined; autoCapitalize?: string | undefined; autoCorrect?: string | undefined; autoSave?: string | undefined; itemProp?: string | undefined; itemScope?: boolean | undefined; itemType?: string | undefined; itemID?: string | undefined; itemRef?: string | undefined; results?: number | undefined; unselectable?: \"on\" | \"off\" | undefined; inputMode?: \"none\" | \"email\" | \"search\" | \"text\" | \"url\" | \"tel\" | \"numeric\" | \"decimal\" | undefined; is?: string | undefined; 'aria-activedescendant'?: string | undefined; 'aria-atomic'?: Booleanish | undefined; 'aria-autocomplete'?: \"none\" | \"list\" | \"inline\" | \"both\" | undefined; 'aria-busy'?: Booleanish | undefined; 'aria-checked'?: boolean | \"mixed\" | \"false\" | \"true\" | undefined; 'aria-colcount'?: number | undefined; 'aria-colindex'?: number | undefined; 'aria-colspan'?: number | undefined; 'aria-controls'?: string | undefined; 'aria-current'?: boolean | \"date\" | \"location\" | \"time\" | \"page\" | \"false\" | \"true\" | \"step\" | undefined; 'aria-describedby'?: string | undefined; 'aria-details'?: string | undefined; 'aria-disabled'?: Booleanish | undefined; 'aria-dropeffect'?: \"none\" | \"copy\" | \"link\" | \"execute\" | \"move\" | \"popup\" | undefined; 'aria-errormessage'?: string | undefined; 'aria-expanded'?: Booleanish | undefined; 'aria-flowto'?: string | undefined; 'aria-grabbed'?: Booleanish | undefined; 'aria-haspopup'?: boolean | \"grid\" | \"menu\" | \"false\" | \"true\" | \"dialog\" | \"listbox\" | \"tree\" | undefined; 'aria-hidden'?: Booleanish | undefined; 'aria-invalid'?: boolean | \"false\" | \"true\" | \"grammar\" | \"spelling\" | undefined; 'aria-keyshortcuts'?: string | undefined; 'aria-label'?: string | undefined; 'aria-labelledby'?: string | undefined; 'aria-level'?: number | undefined; 'aria-live'?: \"off\" | \"assertive\" | \"polite\" | undefined; 'aria-modal'?: Booleanish | undefined; 'aria-multiline'?: Booleanish | undefined; 'aria-multiselectable'?: Booleanish | undefined; 'aria-orientation'?: \"horizontal\" | \"vertical\" | undefined; 'aria-owns'?: string | undefined; 'aria-placeholder'?: string | undefined; 'aria-posinset'?: number | undefined; 'aria-pressed'?: boolean | \"mixed\" | \"false\" | \"true\" | undefined; 'aria-readonly'?: Booleanish | undefined; 'aria-relevant'?: \"all\" | \"text\" | \"additions\" | \"additions removals\" | \"additions text\" | \"removals\" | \"removals additions\" | \"removals text\" | \"text additions\" | \"text removals\" | undefined; 'aria-required'?: Booleanish | undefined; 'aria-roledescription'?: string | undefined; 'aria-rowcount'?: number | undefined; 'aria-rowindex'?: number | undefined; 'aria-rowspan'?: number | undefined; 'aria-selected'?: Booleanish | undefined; 'aria-setsize'?: number | undefined; 'aria-sort'?: \"none\" | \"other\" | \"ascending\" | \"descending\" | undefined; 'aria-valuemax'?: number | undefined; 'aria-valuemin'?: number | undefined; 'aria-valuenow'?: number | undefined; 'aria-valuetext'?: string | undefined; dangerouslySetInnerHTML?: { __html: string; } | undefined; onCopy?: React.ClipboardEventHandler | undefined; onCopyCapture?: React.ClipboardEventHandler | undefined; onCut?: React.ClipboardEventHandler | undefined; onCutCapture?: React.ClipboardEventHandler | undefined; onPaste?: React.ClipboardEventHandler | undefined; onPasteCapture?: React.ClipboardEventHandler | undefined; onCompositionEnd?: React.CompositionEventHandler | undefined; onCompositionEndCapture?: React.CompositionEventHandler | undefined; onCompositionStart?: React.CompositionEventHandler | undefined; onCompositionStartCapture?: React.CompositionEventHandler | undefined; onCompositionUpdate?: React.CompositionEventHandler | undefined; onCompositionUpdateCapture?: React.CompositionEventHandler | undefined; onFocus?: React.FocusEventHandler | undefined; onFocusCapture?: React.FocusEventHandler | undefined; onBlur?: React.FocusEventHandler | undefined; onBlurCapture?: React.FocusEventHandler | undefined; onChangeCapture?: React.FormEventHandler | undefined; onBeforeInput?: React.FormEventHandler | undefined; onBeforeInputCapture?: React.FormEventHandler | undefined; onInput?: React.FormEventHandler | undefined; onInputCapture?: React.FormEventHandler | undefined; onReset?: React.FormEventHandler | undefined; onResetCapture?: React.FormEventHandler | undefined; onSubmit?: React.FormEventHandler | undefined; onSubmitCapture?: React.FormEventHandler | undefined; onInvalid?: React.FormEventHandler | undefined; onInvalidCapture?: React.FormEventHandler | undefined; onLoad?: React.ReactEventHandler | undefined; onLoadCapture?: React.ReactEventHandler | undefined; onErrorCapture?: React.ReactEventHandler | undefined; onKeyDownCapture?: React.KeyboardEventHandler | undefined; onKeyPress?: React.KeyboardEventHandler | undefined; onKeyPressCapture?: React.KeyboardEventHandler | undefined; onKeyUp?: React.KeyboardEventHandler | undefined; onKeyUpCapture?: React.KeyboardEventHandler | undefined; onAbort?: React.ReactEventHandler | undefined; onAbortCapture?: React.ReactEventHandler | undefined; onCanPlay?: React.ReactEventHandler | undefined; onCanPlayCapture?: React.ReactEventHandler | undefined; onCanPlayThrough?: React.ReactEventHandler | undefined; onCanPlayThroughCapture?: React.ReactEventHandler | undefined; onDurationChange?: React.ReactEventHandler | undefined; onDurationChangeCapture?: React.ReactEventHandler | undefined; onEmptied?: React.ReactEventHandler | undefined; onEmptiedCapture?: React.ReactEventHandler | undefined; onEncrypted?: React.ReactEventHandler | undefined; onEncryptedCapture?: React.ReactEventHandler | undefined; onEnded?: React.ReactEventHandler | undefined; onEndedCapture?: React.ReactEventHandler | undefined; onLoadedData?: React.ReactEventHandler | undefined; onLoadedDataCapture?: React.ReactEventHandler | undefined; onLoadedMetadata?: React.ReactEventHandler | undefined; onLoadedMetadataCapture?: React.ReactEventHandler | undefined; onLoadStart?: React.ReactEventHandler | undefined; onLoadStartCapture?: React.ReactEventHandler | undefined; onPause?: React.ReactEventHandler | undefined; onPauseCapture?: React.ReactEventHandler | undefined; onPlay?: React.ReactEventHandler | undefined; onPlayCapture?: React.ReactEventHandler | undefined; onPlaying?: React.ReactEventHandler | undefined; onPlayingCapture?: React.ReactEventHandler | undefined; onProgress?: React.ReactEventHandler | undefined; onProgressCapture?: React.ReactEventHandler | undefined; onRateChange?: React.ReactEventHandler | undefined; onRateChangeCapture?: React.ReactEventHandler | undefined; onSeeked?: React.ReactEventHandler | undefined; onSeekedCapture?: React.ReactEventHandler | undefined; onSeeking?: React.ReactEventHandler | undefined; onSeekingCapture?: React.ReactEventHandler | undefined; onStalled?: React.ReactEventHandler | undefined; onStalledCapture?: React.ReactEventHandler | undefined; onSuspend?: React.ReactEventHandler | undefined; onSuspendCapture?: React.ReactEventHandler | undefined; onTimeUpdate?: React.ReactEventHandler | undefined; onTimeUpdateCapture?: React.ReactEventHandler | undefined; onVolumeChange?: React.ReactEventHandler | undefined; onVolumeChangeCapture?: React.ReactEventHandler | undefined; onWaiting?: React.ReactEventHandler | undefined; onWaitingCapture?: React.ReactEventHandler | undefined; onAuxClick?: React.MouseEventHandler | undefined; onAuxClickCapture?: React.MouseEventHandler | undefined; onClickCapture?: React.MouseEventHandler | undefined; onContextMenu?: React.MouseEventHandler | undefined; onContextMenuCapture?: React.MouseEventHandler | undefined; onDoubleClick?: React.MouseEventHandler | undefined; onDoubleClickCapture?: React.MouseEventHandler | undefined; onDrag?: React.DragEventHandler | undefined; onDragCapture?: React.DragEventHandler | undefined; onDragEnd?: React.DragEventHandler | undefined; onDragEndCapture?: React.DragEventHandler | undefined; onDragEnter?: React.DragEventHandler | undefined; onDragEnterCapture?: React.DragEventHandler | undefined; onDragExit?: React.DragEventHandler | undefined; onDragExitCapture?: React.DragEventHandler | undefined; onDragLeave?: React.DragEventHandler | undefined; onDragLeaveCapture?: React.DragEventHandler | undefined; onDragOver?: React.DragEventHandler | undefined; onDragOverCapture?: React.DragEventHandler | undefined; onDragStart?: React.DragEventHandler | undefined; onDragStartCapture?: React.DragEventHandler | undefined; onDrop?: React.DragEventHandler | undefined; onDropCapture?: React.DragEventHandler | undefined; onMouseDown?: React.MouseEventHandler | undefined; onMouseDownCapture?: React.MouseEventHandler | undefined; onMouseEnter?: React.MouseEventHandler | undefined; onMouseLeave?: React.MouseEventHandler | undefined; onMouseMove?: React.MouseEventHandler | undefined; onMouseMoveCapture?: React.MouseEventHandler | undefined; onMouseOut?: React.MouseEventHandler | undefined; onMouseOutCapture?: React.MouseEventHandler | undefined; onMouseOver?: React.MouseEventHandler | undefined; onMouseOverCapture?: React.MouseEventHandler | undefined; onMouseUp?: React.MouseEventHandler | undefined; onMouseUpCapture?: React.MouseEventHandler | undefined; onSelect?: React.ReactEventHandler | undefined; onSelectCapture?: React.ReactEventHandler | undefined; onTouchCancel?: React.TouchEventHandler | undefined; onTouchCancelCapture?: React.TouchEventHandler | undefined; onTouchEnd?: React.TouchEventHandler | undefined; onTouchEndCapture?: React.TouchEventHandler | undefined; onTouchMove?: React.TouchEventHandler | undefined; onTouchMoveCapture?: React.TouchEventHandler | undefined; onTouchStart?: React.TouchEventHandler | undefined; onTouchStartCapture?: React.TouchEventHandler | undefined; onPointerDown?: React.PointerEventHandler | undefined; onPointerDownCapture?: React.PointerEventHandler | undefined; onPointerMove?: React.PointerEventHandler | undefined; onPointerMoveCapture?: React.PointerEventHandler | undefined; onPointerUp?: React.PointerEventHandler | undefined; onPointerUpCapture?: React.PointerEventHandler | undefined; onPointerCancel?: React.PointerEventHandler | undefined; onPointerCancelCapture?: React.PointerEventHandler | undefined; onPointerEnter?: React.PointerEventHandler | undefined; onPointerEnterCapture?: React.PointerEventHandler | undefined; onPointerLeave?: React.PointerEventHandler | undefined; onPointerLeaveCapture?: React.PointerEventHandler | undefined; onPointerOver?: React.PointerEventHandler | undefined; onPointerOverCapture?: React.PointerEventHandler | undefined; onPointerOut?: React.PointerEventHandler | undefined; onPointerOutCapture?: React.PointerEventHandler | undefined; onGotPointerCapture?: React.PointerEventHandler | undefined; onGotPointerCaptureCapture?: React.PointerEventHandler | undefined; onLostPointerCapture?: React.PointerEventHandler | undefined; onLostPointerCaptureCapture?: React.PointerEventHandler | undefined; onScroll?: React.UIEventHandler | undefined; onScrollCapture?: React.UIEventHandler | undefined; onWheel?: React.WheelEventHandler | undefined; onWheelCapture?: React.WheelEventHandler | undefined; onAnimationStart?: React.AnimationEventHandler | undefined; onAnimationStartCapture?: React.AnimationEventHandler | undefined; onAnimationEnd?: React.AnimationEventHandler | undefined; onAnimationEndCapture?: React.AnimationEventHandler | undefined; onAnimationIteration?: React.AnimationEventHandler | undefined; onAnimationIterationCapture?: React.AnimationEventHandler | undefined; onTransitionEnd?: React.TransitionEventHandler | undefined; onTransitionEndCapture?: React.TransitionEventHandler | undefined; 'data-test-subj'?: string | undefined; css?: ", "Interpolation", "<", "Theme", diff --git a/api_docs/kbn_shared_ux_markdown_mocks.mdx b/api_docs/kbn_shared_ux_markdown_mocks.mdx index 1425270011f6a..51be49cf40b2c 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: 2022-11-29 +date: 2022-12-06 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 dd2f7858a4a31..855b42b2d5a66 100644 --- a/api_docs/kbn_shared_ux_page_analytics_no_data.mdx +++ b/api_docs/kbn_shared_ux_page_analytics_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-analytics-no-data title: "@kbn/shared-ux-page-analytics-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-analytics-no-data plugin -date: 2022-11-29 +date: 2022-12-06 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 794dac8166565..49ec03b16234b 100644 --- a/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-analytics-no-data-mocks title: "@kbn/shared-ux-page-analytics-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-analytics-no-data-mocks plugin -date: 2022-11-29 +date: 2022-12-06 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 d4b03592d2965..5d3658dee5d49 100644 --- a/api_docs/kbn_shared_ux_page_kibana_no_data.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-no-data title: "@kbn/shared-ux-page-kibana-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-no-data plugin -date: 2022-11-29 +date: 2022-12-06 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 5077603fb1ec4..41d50fc164b8e 100644 --- a/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-no-data-mocks title: "@kbn/shared-ux-page-kibana-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-no-data-mocks plugin -date: 2022-11-29 +date: 2022-12-06 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.devdocs.json b/api_docs/kbn_shared_ux_page_kibana_template.devdocs.json index 42d13b89e4e8d..f3487bed459d8 100644 --- a/api_docs/kbn_shared_ux_page_kibana_template.devdocs.json +++ b/api_docs/kbn_shared_ux_page_kibana_template.devdocs.json @@ -181,7 +181,7 @@ "_EuiPageOuterProps", " & Omit<", "_EuiPageInnerProps", - "<\"main\">, \"border\"> & ", + "<\"main\">, \"border\" | \"component\"> & ", "_EuiPageRestrictWidth", " & ", "_EuiPageBottomBorder", @@ -189,7 +189,9 @@ "Property", ".MinHeight | undefined; offset?: number | undefined; mainProps?: (", "CommonProps", - " & React.HTMLAttributes) | undefined; } & { isEmptyState?: boolean | undefined; solutionNav?: ", + " & React.HTMLAttributes) | undefined; component?: ", + "ComponentTypes", + " | undefined; } & { isEmptyState?: boolean | undefined; solutionNav?: ", { "pluginId": "@kbn/shared-ux-page-solution-nav", "scope": "common", diff --git a/api_docs/kbn_shared_ux_page_kibana_template.mdx b/api_docs/kbn_shared_ux_page_kibana_template.mdx index c0fefbca48880..1cfb3c821f08c 100644 --- a/api_docs/kbn_shared_ux_page_kibana_template.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_template.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-template title: "@kbn/shared-ux-page-kibana-template" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-template plugin -date: 2022-11-29 +date: 2022-12-06 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 4678a350d64ac..895228de33167 100644 --- a/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-template-mocks title: "@kbn/shared-ux-page-kibana-template-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-template-mocks plugin -date: 2022-11-29 +date: 2022-12-06 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 2d7ea6ba9ac95..b8a0f2f427199 100644 --- a/api_docs/kbn_shared_ux_page_no_data.mdx +++ b/api_docs/kbn_shared_ux_page_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data title: "@kbn/shared-ux-page-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data plugin -date: 2022-11-29 +date: 2022-12-06 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.devdocs.json b/api_docs/kbn_shared_ux_page_no_data_config.devdocs.json index 07e83e6991e88..73e12b09b9d23 100644 --- a/api_docs/kbn_shared_ux_page_no_data_config.devdocs.json +++ b/api_docs/kbn_shared_ux_page_no_data_config.devdocs.json @@ -144,7 +144,7 @@ "_EuiPageOuterProps", " & Omit<", "_EuiPageInnerProps", - "<\"main\">, \"border\"> & ", + "<\"main\">, \"border\" | \"component\"> & ", "_EuiPageRestrictWidth", " & ", "_EuiPageBottomBorder", @@ -152,7 +152,9 @@ "Property", ".MinHeight | undefined; offset?: number | undefined; mainProps?: (", "CommonProps", - " & React.HTMLAttributes) | undefined; } & { noDataConfig?: ", + " & React.HTMLAttributes) | undefined; component?: ", + "ComponentTypes", + " | undefined; } & { noDataConfig?: ", "NoDataPageProps", " | undefined; pageSideBar?: React.ReactNode; pageSideBarProps?: ", "EuiPageSidebarProps", @@ -222,7 +224,7 @@ "_EuiPageOuterProps", " & Omit<", "_EuiPageInnerProps", - "<\"main\">, \"border\"> & ", + "<\"main\">, \"border\" | \"component\"> & ", "_EuiPageRestrictWidth", " & ", "_EuiPageBottomBorder", @@ -230,7 +232,9 @@ "Property", ".MinHeight | undefined; offset?: number | undefined; mainProps?: (", "CommonProps", - " & React.HTMLAttributes) | undefined; } & { noDataConfig?: ", + " & React.HTMLAttributes) | undefined; component?: ", + "ComponentTypes", + " | undefined; } & { noDataConfig?: ", "NoDataPageProps", " | undefined; pageSideBar?: React.ReactNode; pageSideBarProps?: ", "EuiPageSidebarProps", 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 822e523d7b0f3..a99824e974139 100644 --- a/api_docs/kbn_shared_ux_page_no_data_config.mdx +++ b/api_docs/kbn_shared_ux_page_no_data_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data-config title: "@kbn/shared-ux-page-no-data-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data-config plugin -date: 2022-11-29 +date: 2022-12-06 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 5dfa992a99914..b4a093c4eef94 100644 --- a/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data-config-mocks title: "@kbn/shared-ux-page-no-data-config-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data-config-mocks plugin -date: 2022-11-29 +date: 2022-12-06 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 e4d11e95b46f8..c1dcdb87f1cf8 100644 --- a/api_docs/kbn_shared_ux_page_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data-mocks title: "@kbn/shared-ux-page-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data-mocks plugin -date: 2022-11-29 +date: 2022-12-06 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 590ef342fd8aa..5c7191ae761db 100644 --- a/api_docs/kbn_shared_ux_page_solution_nav.mdx +++ b/api_docs/kbn_shared_ux_page_solution_nav.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-solution-nav title: "@kbn/shared-ux-page-solution-nav" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-solution-nav plugin -date: 2022-11-29 +date: 2022-12-06 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 2ef602d05cec3..7a1fdec933db4 100644 --- a/api_docs/kbn_shared_ux_prompt_no_data_views.mdx +++ b/api_docs/kbn_shared_ux_prompt_no_data_views.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-prompt-no-data-views title: "@kbn/shared-ux-prompt-no-data-views" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-prompt-no-data-views plugin -date: 2022-11-29 +date: 2022-12-06 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 b19ae2bdbcd84..f05ddc5cf3d3a 100644 --- a/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx +++ b/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-prompt-no-data-views-mocks title: "@kbn/shared-ux-prompt-no-data-views-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-prompt-no-data-views-mocks plugin -date: 2022-11-29 +date: 2022-12-06 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.devdocs.json b/api_docs/kbn_shared_ux_prompt_not_found.devdocs.json new file mode 100644 index 0000000000000..99a5e86068dfb --- /dev/null +++ b/api_docs/kbn_shared_ux_prompt_not_found.devdocs.json @@ -0,0 +1,63 @@ +{ + "id": "@kbn/shared-ux-prompt-not-found", + "client": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "server": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "common": { + "classes": [], + "functions": [ + { + "parentPluginId": "@kbn/shared-ux-prompt-not-found", + "id": "def-common.NotFoundPrompt", + "type": "Function", + "tags": [], + "label": "NotFoundPrompt", + "description": [ + "\nPredefined `EuiEmptyPrompt` for 404 pages." + ], + "signature": [ + "({ actions }: NotFoundProps) => JSX.Element" + ], + "path": "packages/shared-ux/prompt/not_found/src/not_found_prompt.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/shared-ux-prompt-not-found", + "id": "def-common.NotFoundPrompt.$1", + "type": "Object", + "tags": [], + "label": "{ actions }", + "description": [], + "signature": [ + "NotFoundProps" + ], + "path": "packages/shared-ux/prompt/not_found/src/not_found_prompt.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + } + ], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + } +} \ No newline at end of file diff --git a/api_docs/kbn_shared_ux_prompt_not_found.mdx b/api_docs/kbn_shared_ux_prompt_not_found.mdx new file mode 100644 index 0000000000000..76be341384b9f --- /dev/null +++ b/api_docs/kbn_shared_ux_prompt_not_found.mdx @@ -0,0 +1,30 @@ +--- +#### +#### This document is auto-generated and is meant to be viewed inside our experimental, new docs system. +#### Reach out in #docs-engineering for more info. +#### +id: kibKbnSharedUxPromptNotFoundPluginApi +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: 2022-12-06 +tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-prompt-not-found'] +--- +import kbnSharedUxPromptNotFoundObj from './kbn_shared_ux_prompt_not_found.devdocs.json'; + + + +Contact [Owner missing] for questions regarding this plugin. + +**Code health stats** + +| Public API count | Any count | Items lacking comments | Missing exports | +|-------------------|-----------|------------------------|-----------------| +| 2 | 0 | 1 | 0 | + +## Common + +### Functions + + diff --git a/api_docs/kbn_shared_ux_router.mdx b/api_docs/kbn_shared_ux_router.mdx index dc58fe24cafb5..8e2b4ab96a3c1 100644 --- a/api_docs/kbn_shared_ux_router.mdx +++ b/api_docs/kbn_shared_ux_router.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-router title: "@kbn/shared-ux-router" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-router plugin -date: 2022-11-29 +date: 2022-12-06 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 4f1c592a6c2f6..b7123b3a3cd72 100644 --- a/api_docs/kbn_shared_ux_router_mocks.mdx +++ b/api_docs/kbn_shared_ux_router_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-router-mocks title: "@kbn/shared-ux-router-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-router-mocks plugin -date: 2022-11-29 +date: 2022-12-06 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 fa722929a0ff5..55125706f1495 100644 --- a/api_docs/kbn_shared_ux_storybook_config.mdx +++ b/api_docs/kbn_shared_ux_storybook_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-storybook-config title: "@kbn/shared-ux-storybook-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-storybook-config plugin -date: 2022-11-29 +date: 2022-12-06 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 10e93dc48a604..ab0da30ffe19e 100644 --- a/api_docs/kbn_shared_ux_storybook_mock.mdx +++ b/api_docs/kbn_shared_ux_storybook_mock.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-storybook-mock title: "@kbn/shared-ux-storybook-mock" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-storybook-mock plugin -date: 2022-11-29 +date: 2022-12-06 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 22fe75a110f06..095cd3b29e241 100644 --- a/api_docs/kbn_shared_ux_utility.mdx +++ b/api_docs/kbn_shared_ux_utility.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-utility title: "@kbn/shared-ux-utility" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-utility plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-utility'] --- import kbnSharedUxUtilityObj from './kbn_shared_ux_utility.devdocs.json'; diff --git a/api_docs/kbn_some_dev_log.mdx b/api_docs/kbn_some_dev_log.mdx index 2f785f6e4120c..a7540897610d3 100644 --- a/api_docs/kbn_some_dev_log.mdx +++ b/api_docs/kbn_some_dev_log.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-some-dev-log title: "@kbn/some-dev-log" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/some-dev-log plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/some-dev-log'] --- import kbnSomeDevLogObj from './kbn_some_dev_log.devdocs.json'; diff --git a/api_docs/kbn_sort_package_json.mdx b/api_docs/kbn_sort_package_json.mdx index f181ea0955933..e2ed020d653fc 100644 --- a/api_docs/kbn_sort_package_json.mdx +++ b/api_docs/kbn_sort_package_json.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-sort-package-json title: "@kbn/sort-package-json" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/sort-package-json plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/sort-package-json'] --- import kbnSortPackageJsonObj from './kbn_sort_package_json.devdocs.json'; diff --git a/api_docs/kbn_std.mdx b/api_docs/kbn_std.mdx index e1a11d35567af..0493f6cf49de1 100644 --- a/api_docs/kbn_std.mdx +++ b/api_docs/kbn_std.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-std title: "@kbn/std" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/std plugin -date: 2022-11-29 +date: 2022-12-06 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 1ead98a7bd9b0..bbd7d580bc8ed 100644 --- a/api_docs/kbn_stdio_dev_helpers.mdx +++ b/api_docs/kbn_stdio_dev_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-stdio-dev-helpers title: "@kbn/stdio-dev-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/stdio-dev-helpers plugin -date: 2022-11-29 +date: 2022-12-06 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 f05ee9e722132..3f50aa6eb4492 100644 --- a/api_docs/kbn_storybook.mdx +++ b/api_docs/kbn_storybook.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-storybook title: "@kbn/storybook" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/storybook plugin -date: 2022-11-29 +date: 2022-12-06 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 3bfb4c56292d1..24b0aa2b2ac0b 100644 --- a/api_docs/kbn_telemetry_tools.mdx +++ b/api_docs/kbn_telemetry_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-telemetry-tools title: "@kbn/telemetry-tools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/telemetry-tools plugin -date: 2022-11-29 +date: 2022-12-06 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 30e124fe853fc..9b444b117757a 100644 --- a/api_docs/kbn_test.mdx +++ b/api_docs/kbn_test.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-test title: "@kbn/test" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/test plugin -date: 2022-11-29 +date: 2022-12-06 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 ba02155f2d0b7..4fb251e15c4a1 100644 --- a/api_docs/kbn_test_jest_helpers.mdx +++ b/api_docs/kbn_test_jest_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-test-jest-helpers title: "@kbn/test-jest-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/test-jest-helpers plugin -date: 2022-11-29 +date: 2022-12-06 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 5bb27cb029dd6..5fd856539bbe7 100644 --- a/api_docs/kbn_test_subj_selector.mdx +++ b/api_docs/kbn_test_subj_selector.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-test-subj-selector title: "@kbn/test-subj-selector" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/test-subj-selector plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test-subj-selector'] --- import kbnTestSubjSelectorObj from './kbn_test_subj_selector.devdocs.json'; diff --git a/api_docs/kbn_tooling_log.mdx b/api_docs/kbn_tooling_log.mdx index 5b20a143323a2..7cad7bea538cb 100644 --- a/api_docs/kbn_tooling_log.mdx +++ b/api_docs/kbn_tooling_log.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-tooling-log title: "@kbn/tooling-log" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/tooling-log plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/tooling-log'] --- import kbnToolingLogObj from './kbn_tooling_log.devdocs.json'; diff --git a/api_docs/kbn_type_summarizer.mdx b/api_docs/kbn_type_summarizer.mdx index fff5773985129..dd3c6057d0e52 100644 --- a/api_docs/kbn_type_summarizer.mdx +++ b/api_docs/kbn_type_summarizer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-type-summarizer title: "@kbn/type-summarizer" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/type-summarizer plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/type-summarizer'] --- import kbnTypeSummarizerObj from './kbn_type_summarizer.devdocs.json'; diff --git a/api_docs/kbn_type_summarizer_core.mdx b/api_docs/kbn_type_summarizer_core.mdx index 871708564dac7..79d2d7563d148 100644 --- a/api_docs/kbn_type_summarizer_core.mdx +++ b/api_docs/kbn_type_summarizer_core.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-type-summarizer-core title: "@kbn/type-summarizer-core" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/type-summarizer-core plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/type-summarizer-core'] --- import kbnTypeSummarizerCoreObj from './kbn_type_summarizer_core.devdocs.json'; diff --git a/api_docs/kbn_typed_react_router_config.mdx b/api_docs/kbn_typed_react_router_config.mdx index 09af3e077de20..3950e617fc4a8 100644 --- a/api_docs/kbn_typed_react_router_config.mdx +++ b/api_docs/kbn_typed_react_router_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-typed-react-router-config title: "@kbn/typed-react-router-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/typed-react-router-config plugin -date: 2022-11-29 +date: 2022-12-06 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_shared_deps_src.devdocs.json b/api_docs/kbn_ui_shared_deps_src.devdocs.json index 95594baac9f58..d2f3014cbaeae 100644 --- a/api_docs/kbn_ui_shared_deps_src.devdocs.json +++ b/api_docs/kbn_ui_shared_deps_src.devdocs.json @@ -474,10 +474,10 @@ }, { "parentPluginId": "@kbn/ui-shared-deps-src", - "id": "def-server.externals.risonnode", + "id": "def-server.externals.kbnrison", "type": "string", "tags": [], - "label": "'rison-node'", + "label": "'@kbn/rison'", "description": [], "path": "packages/kbn-ui-shared-deps-src/src/definitions.js", "deprecated": false, diff --git a/api_docs/kbn_ui_shared_deps_src.mdx b/api_docs/kbn_ui_shared_deps_src.mdx index fe1806ff41f53..2b91876286436 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: 2022-11-29 +date: 2022-12-06 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 3daa216f02aee..db31d2c7eeb7b 100644 --- a/api_docs/kbn_ui_theme.mdx +++ b/api_docs/kbn_ui_theme.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ui-theme title: "@kbn/ui-theme" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ui-theme plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ui-theme'] --- import kbnUiThemeObj from './kbn_ui_theme.devdocs.json'; diff --git a/api_docs/kbn_user_profile_components.mdx b/api_docs/kbn_user_profile_components.mdx index 3ebe1ab25ca42..1ac8cf70546aa 100644 --- a/api_docs/kbn_user_profile_components.mdx +++ b/api_docs/kbn_user_profile_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-user-profile-components title: "@kbn/user-profile-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/user-profile-components plugin -date: 2022-11-29 +date: 2022-12-06 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 bdbf90c72f5a7..58195dbec63f8 100644 --- a/api_docs/kbn_utility_types.mdx +++ b/api_docs/kbn_utility_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-utility-types title: "@kbn/utility-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/utility-types plugin -date: 2022-11-29 +date: 2022-12-06 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 fb9e18bc10013..ed62483f69f94 100644 --- a/api_docs/kbn_utility_types_jest.mdx +++ b/api_docs/kbn_utility_types_jest.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-utility-types-jest title: "@kbn/utility-types-jest" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/utility-types-jest plugin -date: 2022-11-29 +date: 2022-12-06 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 7b1e0b558a0f7..c495abb76eedb 100644 --- a/api_docs/kbn_utils.mdx +++ b/api_docs/kbn_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-utils title: "@kbn/utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/utils plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utils'] --- import kbnUtilsObj from './kbn_utils.devdocs.json'; diff --git a/api_docs/kbn_yarn_lock_validator.mdx b/api_docs/kbn_yarn_lock_validator.mdx index 768b4d89b56f8..a0a3f2d6cbcb4 100644 --- a/api_docs/kbn_yarn_lock_validator.mdx +++ b/api_docs/kbn_yarn_lock_validator.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-yarn-lock-validator title: "@kbn/yarn-lock-validator" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/yarn-lock-validator plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/yarn-lock-validator'] --- import kbnYarnLockValidatorObj from './kbn_yarn_lock_validator.devdocs.json'; diff --git a/api_docs/kibana_overview.mdx b/api_docs/kibana_overview.mdx index f5c860c829e08..18b98ee83d16a 100644 --- a/api_docs/kibana_overview.mdx +++ b/api_docs/kibana_overview.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kibanaOverview title: "kibanaOverview" image: https://source.unsplash.com/400x175/?github description: API docs for the kibanaOverview plugin -date: 2022-11-29 +date: 2022-12-06 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 665dc86ca8b81..6b5f8816ff972 100644 --- a/api_docs/kibana_react.mdx +++ b/api_docs/kibana_react.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kibanaReact title: "kibanaReact" image: https://source.unsplash.com/400x175/?github description: API docs for the kibanaReact plugin -date: 2022-11-29 +date: 2022-12-06 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 2355f311b876e..4a273553298a6 100644 --- a/api_docs/kibana_utils.mdx +++ b/api_docs/kibana_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kibanaUtils title: "kibanaUtils" image: https://source.unsplash.com/400x175/?github description: API docs for the kibanaUtils plugin -date: 2022-11-29 +date: 2022-12-06 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 2964e5cc3d5c7..dc3fbbf30d5af 100644 --- a/api_docs/kubernetes_security.mdx +++ b/api_docs/kubernetes_security.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kubernetesSecurity title: "kubernetesSecurity" image: https://source.unsplash.com/400x175/?github description: API docs for the kubernetesSecurity plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kubernetesSecurity'] --- import kubernetesSecurityObj from './kubernetes_security.devdocs.json'; diff --git a/api_docs/lens.devdocs.json b/api_docs/lens.devdocs.json index 95bd3b3bc9e6c..4762dc2ec8807 100644 --- a/api_docs/lens.devdocs.json +++ b/api_docs/lens.devdocs.json @@ -742,22 +742,6 @@ "trackAdoption": false, "children": [], "returnComment": [] - }, - { - "parentPluginId": "lens", - "id": "def-public.Embeddable.getChartInfo", - "type": "Function", - "tags": [], - "label": "getChartInfo", - "description": [], - "signature": [ - "() => Readonly" - ], - "path": "x-pack/plugins/lens/public/embeddable/embeddable.tsx", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [] } ], "initialIsOpen": false @@ -1136,6 +1120,81 @@ ], "initialIsOpen": false }, + { + "parentPluginId": "lens", + "id": "def-public.ChartInfo", + "type": "Interface", + "tags": [], + "label": "ChartInfo", + "description": [], + "path": "x-pack/plugins/lens/public/chart_info_api.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "lens", + "id": "def-public.ChartInfo.layers", + "type": "Array", + "tags": [], + "label": "layers", + "description": [], + "signature": [ + "ChartLayerDescriptor", + "[]" + ], + "path": "x-pack/plugins/lens/public/chart_info_api.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "lens", + "id": "def-public.ChartInfo.visualizationType", + "type": "string", + "tags": [], + "label": "visualizationType", + "description": [], + "path": "x-pack/plugins/lens/public/chart_info_api.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "lens", + "id": "def-public.ChartInfo.filters", + "type": "Array", + "tags": [], + "label": "filters", + "description": [], + "signature": [ + { + "pluginId": "@kbn/es-query", + "scope": "common", + "docId": "kibKbnEsQueryPluginApi", + "section": "def-common.Filter", + "text": "Filter" + }, + "[]" + ], + "path": "x-pack/plugins/lens/public/chart_info_api.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "lens", + "id": "def-public.ChartInfo.query", + "type": "Object", + "tags": [], + "label": "query", + "description": [], + "signature": [ + "{ query: string | { [key: string]: any; }; language: string; }" + ], + "path": "x-pack/plugins/lens/public/chart_info_api.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, { "parentPluginId": "lens", "id": "def-public.DataLayerArgs", @@ -3258,6 +3317,8 @@ "section": "def-public.FormulaPublicApi", "text": "FormulaPublicApi" }, + "; chartInfo: ", + "ChartInfoApi", "; }>" ], "path": "x-pack/plugins/lens/public/plugin.ts", @@ -3826,6 +3887,20 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "lens", + "id": "def-public.SharedPieLayerState.colorsByDimension", + "type": "Object", + "tags": [], + "label": "colorsByDimension", + "description": [], + "signature": [ + "Record | undefined" + ], + "path": "x-pack/plugins/lens/common/types.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "lens", "id": "def-public.SharedPieLayerState.collapseFns", @@ -6036,6 +6111,43 @@ ], "returnComment": [] }, + { + "parentPluginId": "lens", + "id": "def-public.Visualization.hasLayerSettings", + "type": "Function", + "tags": [], + "label": "hasLayerSettings", + "description": [ + "\nAllows the visualization to announce whether or not it has any settings to show" + ], + "signature": [ + "((props: ", + "VisualizationConfigProps", + ") => boolean) | undefined" + ], + "path": "x-pack/plugins/lens/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "lens", + "id": "def-public.Visualization.hasLayerSettings.$1", + "type": "Object", + "tags": [], + "label": "props", + "description": [], + "signature": [ + "VisualizationConfigProps", + "" + ], + "path": "x-pack/plugins/lens/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, { "parentPluginId": "lens", "id": "def-public.Visualization.renderLayerSettings", @@ -12073,6 +12185,20 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "lens", + "id": "def-common.SharedPieLayerState.colorsByDimension", + "type": "Object", + "tags": [], + "label": "colorsByDimension", + "description": [], + "signature": [ + "Record | undefined" + ], + "path": "x-pack/plugins/lens/common/types.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "lens", "id": "def-common.SharedPieLayerState.collapseFns", diff --git a/api_docs/lens.mdx b/api_docs/lens.mdx index 072a74b03ed83..ac739e788c61e 100644 --- a/api_docs/lens.mdx +++ b/api_docs/lens.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/lens title: "lens" image: https://source.unsplash.com/400x175/?github description: API docs for the lens plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'lens'] --- import lensObj from './lens.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Vis Editors](https://github.com/orgs/elastic/teams/kibana-visualization | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 685 | 0 | 590 | 48 | +| 693 | 0 | 597 | 50 | ## Client diff --git a/api_docs/license_api_guard.mdx b/api_docs/license_api_guard.mdx index ab1f43b8f4c53..099b953cf7274 100644 --- a/api_docs/license_api_guard.mdx +++ b/api_docs/license_api_guard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/licenseApiGuard title: "licenseApiGuard" image: https://source.unsplash.com/400x175/?github description: API docs for the licenseApiGuard plugin -date: 2022-11-29 +date: 2022-12-06 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 e17d666d41fa7..a4a5fbaa4924d 100644 --- a/api_docs/license_management.mdx +++ b/api_docs/license_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/licenseManagement title: "licenseManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the licenseManagement plugin -date: 2022-11-29 +date: 2022-12-06 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 addaf047bc9ed..3be720e7fca50 100644 --- a/api_docs/licensing.mdx +++ b/api_docs/licensing.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/licensing title: "licensing" image: https://source.unsplash.com/400x175/?github description: API docs for the licensing plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licensing'] --- import licensingObj from './licensing.devdocs.json'; diff --git a/api_docs/lists.mdx b/api_docs/lists.mdx index 5682d52d715da..e3962d6ab632c 100644 --- a/api_docs/lists.mdx +++ b/api_docs/lists.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/lists title: "lists" image: https://source.unsplash.com/400x175/?github description: API docs for the lists plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'lists'] --- import listsObj from './lists.devdocs.json'; diff --git a/api_docs/management.mdx b/api_docs/management.mdx index 9d86ea41e0838..374a530ff8309 100644 --- a/api_docs/management.mdx +++ b/api_docs/management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/management title: "management" image: https://source.unsplash.com/400x175/?github description: API docs for the management plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'management'] --- import managementObj from './management.devdocs.json'; diff --git a/api_docs/maps.devdocs.json b/api_docs/maps.devdocs.json index 11393b4a0aebd..8c3435ae4277a 100644 --- a/api_docs/maps.devdocs.json +++ b/api_docs/maps.devdocs.json @@ -4383,6 +4383,18 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "maps", + "id": "def-common.LABEL_POSITIONS", + "type": "Enum", + "tags": [], + "label": "LABEL_POSITIONS", + "description": [], + "path": "x-pack/plugins/maps/common/constants.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "maps", "id": "def-common.LAYER_TYPE", diff --git a/api_docs/maps.mdx b/api_docs/maps.mdx index 0b664142f6227..64b959f6bbf39 100644 --- a/api_docs/maps.mdx +++ b/api_docs/maps.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/maps title: "maps" image: https://source.unsplash.com/400x175/?github description: API docs for the maps plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'maps'] --- import mapsObj from './maps.devdocs.json'; @@ -21,7 +21,7 @@ Contact [GIS](https://github.com/orgs/elastic/teams/kibana-gis) for questions re | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 266 | 0 | 265 | 26 | +| 267 | 0 | 266 | 26 | ## Client diff --git a/api_docs/maps_ems.mdx b/api_docs/maps_ems.mdx index 012c739baaa13..c91506cb927e1 100644 --- a/api_docs/maps_ems.mdx +++ b/api_docs/maps_ems.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/mapsEms title: "mapsEms" image: https://source.unsplash.com/400x175/?github description: API docs for the mapsEms plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'mapsEms'] --- import mapsEmsObj from './maps_ems.devdocs.json'; diff --git a/api_docs/ml.mdx b/api_docs/ml.mdx index ad29d012503d9..3fb8911bcc351 100644 --- a/api_docs/ml.mdx +++ b/api_docs/ml.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ml title: "ml" image: https://source.unsplash.com/400x175/?github description: API docs for the ml plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ml'] --- import mlObj from './ml.devdocs.json'; diff --git a/api_docs/monitoring.mdx b/api_docs/monitoring.mdx index bacd76dff7a92..079c9e8160afc 100644 --- a/api_docs/monitoring.mdx +++ b/api_docs/monitoring.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/monitoring title: "monitoring" image: https://source.unsplash.com/400x175/?github description: API docs for the monitoring plugin -date: 2022-11-29 +date: 2022-12-06 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 41dc108bee254..8d768b4f7450e 100644 --- a/api_docs/monitoring_collection.mdx +++ b/api_docs/monitoring_collection.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/monitoringCollection title: "monitoringCollection" image: https://source.unsplash.com/400x175/?github description: API docs for the monitoringCollection plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'monitoringCollection'] --- import monitoringCollectionObj from './monitoring_collection.devdocs.json'; diff --git a/api_docs/navigation.devdocs.json b/api_docs/navigation.devdocs.json index f47ee2496eaea..7e70a907f5608 100644 --- a/api_docs/navigation.devdocs.json +++ b/api_docs/navigation.devdocs.json @@ -440,7 +440,7 @@ "ToolTipPositions", " | undefined; anchorProps?: (", "CommonProps", - " & React.HTMLAttributes) | undefined; title?: string | undefined; color?: \"subdued\" | \"accent\" | \"hollow\" | undefined; size?: \"m\" | \"s\" | undefined; } & ", + " & React.HTMLAttributes) | undefined; title?: string | undefined; color?: \"subdued\" | \"accent\" | \"hollow\" | undefined; size?: \"m\" | \"s\" | undefined; alignment?: \"middle\" | \"baseline\" | undefined; } & ", "DisambiguateSet", " & LabelAsString) | (", "CommonProps", @@ -456,7 +456,7 @@ "ToolTipPositions", " | undefined; anchorProps?: (", "CommonProps", - " & React.HTMLAttributes) | undefined; title?: string | undefined; color?: \"subdued\" | \"accent\" | \"hollow\" | undefined; size?: \"m\" | \"s\" | undefined; } & ", + " & React.HTMLAttributes) | undefined; title?: string | undefined; color?: \"subdued\" | \"accent\" | \"hollow\" | undefined; size?: \"m\" | \"s\" | undefined; alignment?: \"middle\" | \"baseline\" | undefined; } & ", "DisambiguateSet", " & ", "DisambiguateSet", @@ -476,7 +476,7 @@ "ToolTipPositions", " | undefined; anchorProps?: (", "CommonProps", - " & React.HTMLAttributes) | undefined; title?: string | undefined; color?: \"subdued\" | \"accent\" | \"hollow\" | undefined; size?: \"m\" | \"s\" | undefined; } & ", + " & React.HTMLAttributes) | undefined; title?: string | undefined; color?: \"subdued\" | \"accent\" | \"hollow\" | undefined; size?: \"m\" | \"s\" | undefined; alignment?: \"middle\" | \"baseline\" | undefined; } & ", "DisambiguateSet", " & LabelAsString) | (", "CommonProps", @@ -494,7 +494,7 @@ "ToolTipPositions", " | undefined; anchorProps?: (", "CommonProps", - " & React.HTMLAttributes) | undefined; title?: string | undefined; color?: \"subdued\" | \"accent\" | \"hollow\" | undefined; size?: \"m\" | \"s\" | undefined; } & ", + " & React.HTMLAttributes) | undefined; title?: string | undefined; color?: \"subdued\" | \"accent\" | \"hollow\" | undefined; size?: \"m\" | \"s\" | undefined; alignment?: \"middle\" | \"baseline\" | undefined; } & ", "DisambiguateSet", " & ", "DisambiguateSet", @@ -514,7 +514,7 @@ "ToolTipPositions", " | undefined; anchorProps?: (", "CommonProps", - " & React.HTMLAttributes) | undefined; title?: string | undefined; color?: \"subdued\" | \"accent\" | \"hollow\" | undefined; size?: \"m\" | \"s\" | undefined; } & ", + " & React.HTMLAttributes) | undefined; title?: string | undefined; color?: \"subdued\" | \"accent\" | \"hollow\" | undefined; size?: \"m\" | \"s\" | undefined; alignment?: \"middle\" | \"baseline\" | undefined; } & ", "DisambiguateSet", " & ", "DisambiguateSet", @@ -534,7 +534,7 @@ "ToolTipPositions", " | undefined; anchorProps?: (", "CommonProps", - " & React.HTMLAttributes) | undefined; title?: string | undefined; color?: \"subdued\" | \"accent\" | \"hollow\" | undefined; size?: \"m\" | \"s\" | undefined; } & ", + " & React.HTMLAttributes) | undefined; title?: string | undefined; color?: \"subdued\" | \"accent\" | \"hollow\" | undefined; size?: \"m\" | \"s\" | undefined; alignment?: \"middle\" | \"baseline\" | undefined; } & ", "DisambiguateSet", " & LabelAsString) | (", "CommonProps", @@ -552,7 +552,7 @@ "ToolTipPositions", " | undefined; anchorProps?: (", "CommonProps", - " & React.HTMLAttributes) | undefined; title?: string | undefined; color?: \"subdued\" | \"accent\" | \"hollow\" | undefined; size?: \"m\" | \"s\" | undefined; } & ", + " & React.HTMLAttributes) | undefined; title?: string | undefined; color?: \"subdued\" | \"accent\" | \"hollow\" | undefined; size?: \"m\" | \"s\" | undefined; alignment?: \"middle\" | \"baseline\" | undefined; } & ", "DisambiguateSet", " & ", "DisambiguateSet", @@ -572,7 +572,7 @@ "ToolTipPositions", " | undefined; anchorProps?: (", "CommonProps", - " & React.HTMLAttributes) | undefined; title?: string | undefined; color?: \"subdued\" | \"accent\" | \"hollow\" | undefined; size?: \"m\" | \"s\" | undefined; } & ", + " & React.HTMLAttributes) | undefined; title?: string | undefined; color?: \"subdued\" | \"accent\" | \"hollow\" | undefined; size?: \"m\" | \"s\" | undefined; alignment?: \"middle\" | \"baseline\" | undefined; } & ", "DisambiguateSet", " & ", "DisambiguateSet", diff --git a/api_docs/navigation.mdx b/api_docs/navigation.mdx index f9ad1fa550094..b707bba302189 100644 --- a/api_docs/navigation.mdx +++ b/api_docs/navigation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/navigation title: "navigation" image: https://source.unsplash.com/400x175/?github description: API docs for the navigation plugin -date: 2022-11-29 +date: 2022-12-06 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 709aba413a92d..4d680a6dcea18 100644 --- a/api_docs/newsfeed.mdx +++ b/api_docs/newsfeed.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/newsfeed title: "newsfeed" image: https://source.unsplash.com/400x175/?github description: API docs for the newsfeed plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'newsfeed'] --- import newsfeedObj from './newsfeed.devdocs.json'; diff --git a/api_docs/notifications.mdx b/api_docs/notifications.mdx index bf2f0f11faa8f..5f8c939fcde4e 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: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'notifications'] --- import notificationsObj from './notifications.devdocs.json'; diff --git a/api_docs/observability.devdocs.json b/api_docs/observability.devdocs.json index f2c2af16ead20..d53c00260d05c 100644 --- a/api_docs/observability.devdocs.json +++ b/api_docs/observability.devdocs.json @@ -720,7 +720,7 @@ "signature": [ "React.ExoticComponent[] | undefined; isInApp?: boolean | undefined; observabilityRuleTypeRegistry: { register: (type: ", + "<{}> | undefined; alerts?: Record[] | undefined; isInApp?: boolean | undefined; observabilityRuleTypeRegistry: { register: (type: ", { "pluginId": "observability", "scope": "public", @@ -4495,6 +4495,138 @@ ], "initialIsOpen": false }, + { + "parentPluginId": "observability", + "id": "def-public.SLO", + "type": "Interface", + "tags": [], + "label": "SLO", + "description": [], + "path": "x-pack/plugins/observability/public/typings/slo/index.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "observability", + "id": "def-public.SLO.id", + "type": "string", + "tags": [], + "label": "id", + "description": [], + "path": "x-pack/plugins/observability/public/typings/slo/index.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "observability", + "id": "def-public.SLO.name", + "type": "string", + "tags": [], + "label": "name", + "description": [], + "path": "x-pack/plugins/observability/public/typings/slo/index.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "observability", + "id": "def-public.SLO.objective", + "type": "Object", + "tags": [], + "label": "objective", + "description": [], + "signature": [ + "{ target: number; }" + ], + "path": "x-pack/plugins/observability/public/typings/slo/index.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "observability", + "id": "def-public.SLO.summary", + "type": "Object", + "tags": [], + "label": "summary", + "description": [], + "signature": [ + "{ sliValue: number; errorBudget: { remaining: number; }; }" + ], + "path": "x-pack/plugins/observability/public/typings/slo/index.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "observability", + "id": "def-public.SLOList", + "type": "Interface", + "tags": [], + "label": "SLOList", + "description": [], + "path": "x-pack/plugins/observability/public/typings/slo/index.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "observability", + "id": "def-public.SLOList.results", + "type": "Array", + "tags": [], + "label": "results", + "description": [], + "signature": [ + { + "pluginId": "observability", + "scope": "public", + "docId": "kibObservabilityPluginApi", + "section": "def-public.SLO", + "text": "SLO" + }, + "[]" + ], + "path": "x-pack/plugins/observability/public/typings/slo/index.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "observability", + "id": "def-public.SLOList.page", + "type": "number", + "tags": [], + "label": "page", + "description": [], + "path": "x-pack/plugins/observability/public/typings/slo/index.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "observability", + "id": "def-public.SLOList.perPage", + "type": "number", + "tags": [], + "label": "perPage", + "description": [], + "path": "x-pack/plugins/observability/public/typings/slo/index.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "observability", + "id": "def-public.SLOList.total", + "type": "number", + "tags": [], + "label": "total", + "description": [], + "path": "x-pack/plugins/observability/public/typings/slo/index.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, { "parentPluginId": "observability", "id": "def-public.Stat", @@ -5607,6 +5739,31 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "observability", + "id": "def-public.Subset", + "type": "Type", + "tags": [], + "label": "Subset", + "description": [ + "\nAllow partial of nested object" + ], + "signature": [ + "{ [attr in keyof K]?: (K[attr] extends object ? ", + { + "pluginId": "observability", + "scope": "public", + "docId": "kibObservabilityPluginApi", + "section": "def-public.Subset", + "text": "Subset" + }, + " : K[attr]) | undefined; }" + ], + "path": "x-pack/plugins/observability/public/typings/utils.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "observability", "id": "def-public.TERMS_COLUMN", @@ -7935,7 +8092,7 @@ "section": "def-server.ObservabilityRouteHandlerResources", "text": "ObservabilityRouteHandlerResources" }, - ", { page: number; per_page: number; total: number; results: { id: string; name: string; description: string; indicator: { type: \"sli.apm.transaction_duration\"; params: { environment: string; service: string; transaction_type: string; transaction_name: string; 'threshold.us': number; }; } | { type: \"sli.apm.transaction_error_rate\"; params: { environment: string; service: string; transaction_type: string; transaction_name: string; } & { good_status_codes?: (\"2xx\" | \"3xx\" | \"4xx\" | \"5xx\")[] | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; query_filter: string; numerator: string; denominator: string; }; }; time_window: { duration: string; is_rolling: boolean; } | { duration: string; calendar: { start_time: string; }; }; budgeting_method: string; objective: { target: number; } & { timeslice_target?: number | undefined; timeslice_window?: string | undefined; }; summary: { sli_value: number; error_budget: { initial: number; consumed: number; remaining: number; is_estimated: boolean; }; }; revision: number; created_at: string; updated_at: string; }[]; }, ", + ", { page: number; per_page: number; total: number; results: { id: string; name: string; description: string; indicator: { type: \"sli.apm.transaction_duration\"; params: { environment: string; service: string; transaction_type: string; transaction_name: string; 'threshold.us': number; }; } | { type: \"sli.apm.transaction_error_rate\"; params: { environment: string; service: string; transaction_type: string; transaction_name: string; } & { good_status_codes?: (\"2xx\" | \"3xx\" | \"4xx\" | \"5xx\")[] | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; filter: string; good: string; total: string; }; }; time_window: { duration: string; is_rolling: boolean; } | { duration: string; calendar: { start_time: string; }; }; budgeting_method: string; objective: { target: number; } & { timeslice_target?: number | undefined; timeslice_window?: string | undefined; }; summary: { sli_value: number; error_budget: { initial: number; consumed: number; remaining: number; is_estimated: boolean; }; }; settings: { timestamp_field: string; sync_delay: string; frequency: string; }; revision: number; created_at: string; updated_at: string; }[]; }, ", { "pluginId": "observability", "scope": "server", @@ -7995,7 +8152,7 @@ "section": "def-server.ObservabilityRouteHandlerResources", "text": "ObservabilityRouteHandlerResources" }, - ", { id: string; name: string; description: string; indicator: { type: \"sli.apm.transaction_duration\"; params: { environment: string; service: string; transaction_type: string; transaction_name: string; 'threshold.us': number; }; } | { type: \"sli.apm.transaction_error_rate\"; params: { environment: string; service: string; transaction_type: string; transaction_name: string; } & { good_status_codes?: (\"2xx\" | \"3xx\" | \"4xx\" | \"5xx\")[] | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; query_filter: string; numerator: string; denominator: string; }; }; time_window: { duration: string; is_rolling: boolean; } | { duration: string; calendar: { start_time: string; }; }; budgeting_method: string; objective: { target: number; } & { timeslice_target?: number | undefined; timeslice_window?: string | undefined; }; summary: { sli_value: number; error_budget: { initial: number; consumed: number; remaining: number; is_estimated: boolean; }; }; revision: number; created_at: string; updated_at: string; }, ", + ", { id: string; name: string; description: string; indicator: { type: \"sli.apm.transaction_duration\"; params: { environment: string; service: string; transaction_type: string; transaction_name: string; 'threshold.us': number; }; } | { type: \"sli.apm.transaction_error_rate\"; params: { environment: string; service: string; transaction_type: string; transaction_name: string; } & { good_status_codes?: (\"2xx\" | \"3xx\" | \"4xx\" | \"5xx\")[] | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; filter: string; good: string; total: string; }; }; time_window: { duration: string; is_rolling: boolean; } | { duration: string; calendar: { start_time: string; }; }; budgeting_method: string; objective: { target: number; } & { timeslice_target?: number | undefined; timeslice_window?: string | undefined; }; settings: { timestamp_field: string; sync_delay: string; frequency: string; }; summary: { sli_value: number; error_budget: { initial: number; consumed: number; remaining: number; is_estimated: boolean; }; }; revision: number; created_at: string; updated_at: string; }, ", { "pluginId": "observability", "scope": "server", @@ -8111,11 +8268,11 @@ "TypeC", "<{ index: ", "StringC", - "; query_filter: ", + "; filter: ", "StringC", - "; numerator: ", + "; good: ", "StringC", - "; denominator: ", + "; total: ", "StringC", "; }>; }>]>; time_window: ", "UnionC", @@ -8157,7 +8314,19 @@ "Type", "<", "Duration", - ", string, unknown>; }>]>; }>; }>, ", + ", string, unknown>; }>]>; settings: ", + "TypeC", + "<{ timestamp_field: ", + "StringC", + "; sync_delay: ", + "Type", + "<", + "Duration", + ", string, unknown>; frequency: ", + "Type", + "<", + "Duration", + ", string, unknown>; }>; }>; }>, ", { "pluginId": "observability", "scope": "server", @@ -8165,7 +8334,7 @@ "section": "def-server.ObservabilityRouteHandlerResources", "text": "ObservabilityRouteHandlerResources" }, - ", { id: string; name: string; description: string; indicator: { type: \"sli.apm.transaction_duration\"; params: { environment: string; service: string; transaction_type: string; transaction_name: string; 'threshold.us': number; }; } | { type: \"sli.apm.transaction_error_rate\"; params: { environment: string; service: string; transaction_type: string; transaction_name: string; } & { good_status_codes?: (\"2xx\" | \"3xx\" | \"4xx\" | \"5xx\")[] | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; query_filter: string; numerator: string; denominator: string; }; }; time_window: { duration: string; is_rolling: boolean; } | { duration: string; calendar: { start_time: string; }; }; budgeting_method: string; objective: { target: number; } & { timeslice_target?: number | undefined; timeslice_window?: string | undefined; }; created_at: string; updated_at: string; }, ", + ", { id: string; name: string; description: string; indicator: { type: \"sli.apm.transaction_duration\"; params: { environment: string; service: string; transaction_type: string; transaction_name: string; 'threshold.us': number; }; } | { type: \"sli.apm.transaction_error_rate\"; params: { environment: string; service: string; transaction_type: string; transaction_name: string; } & { good_status_codes?: (\"2xx\" | \"3xx\" | \"4xx\" | \"5xx\")[] | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; filter: string; good: string; total: string; }; }; time_window: { duration: string; is_rolling: boolean; } | { duration: string; calendar: { start_time: string; }; }; budgeting_method: string; objective: { target: number; } & { timeslice_target?: number | undefined; timeslice_window?: string | undefined; }; settings: { timestamp_field: string; sync_delay: string; frequency: string; }; created_at: string; updated_at: string; }, ", { "pluginId": "observability", "scope": "server", @@ -8184,6 +8353,8 @@ "<\"POST /api/observability/slos\", ", "TypeC", "<{ body: ", + "IntersectionC", + "<[", "TypeC", "<{ name: ", "StringC", @@ -8277,11 +8448,11 @@ "TypeC", "<{ index: ", "StringC", - "; query_filter: ", + "; filter: ", "StringC", - "; numerator: ", + "; good: ", "StringC", - "; denominator: ", + "; total: ", "StringC", "; }>; }>]>; time_window: ", "UnionC", @@ -8323,7 +8494,21 @@ "Type", "<", "Duration", - ", string, unknown>; }>]>; }>; }>, ", + ", string, unknown>; }>]>; }>, ", + "PartialC", + "<{ settings: ", + "PartialC", + "<{ timestamp_field: ", + "StringC", + "; sync_delay: ", + "Type", + "<", + "Duration", + ", string, unknown>; frequency: ", + "Type", + "<", + "Duration", + ", string, unknown>; }>; }>]>; }>, ", { "pluginId": "observability", "scope": "server", @@ -8439,7 +8624,7 @@ "section": "def-server.ObservabilityRouteHandlerResources", "text": "ObservabilityRouteHandlerResources" }, - ", { page: number; per_page: number; total: number; results: { id: string; name: string; description: string; indicator: { type: \"sli.apm.transaction_duration\"; params: { environment: string; service: string; transaction_type: string; transaction_name: string; 'threshold.us': number; }; } | { type: \"sli.apm.transaction_error_rate\"; params: { environment: string; service: string; transaction_type: string; transaction_name: string; } & { good_status_codes?: (\"2xx\" | \"3xx\" | \"4xx\" | \"5xx\")[] | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; query_filter: string; numerator: string; denominator: string; }; }; time_window: { duration: string; is_rolling: boolean; } | { duration: string; calendar: { start_time: string; }; }; budgeting_method: string; objective: { target: number; } & { timeslice_target?: number | undefined; timeslice_window?: string | undefined; }; summary: { sli_value: number; error_budget: { initial: number; consumed: number; remaining: number; is_estimated: boolean; }; }; revision: number; created_at: string; updated_at: string; }[]; }, ", + ", { page: number; per_page: number; total: number; results: { id: string; name: string; description: string; indicator: { type: \"sli.apm.transaction_duration\"; params: { environment: string; service: string; transaction_type: string; transaction_name: string; 'threshold.us': number; }; } | { type: \"sli.apm.transaction_error_rate\"; params: { environment: string; service: string; transaction_type: string; transaction_name: string; } & { good_status_codes?: (\"2xx\" | \"3xx\" | \"4xx\" | \"5xx\")[] | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; filter: string; good: string; total: string; }; }; time_window: { duration: string; is_rolling: boolean; } | { duration: string; calendar: { start_time: string; }; }; budgeting_method: string; objective: { target: number; } & { timeslice_target?: number | undefined; timeslice_window?: string | undefined; }; summary: { sli_value: number; error_budget: { initial: number; consumed: number; remaining: number; is_estimated: boolean; }; }; settings: { timestamp_field: string; sync_delay: string; frequency: string; }; revision: number; created_at: string; updated_at: string; }[]; }, ", { "pluginId": "observability", "scope": "server", @@ -8499,7 +8684,7 @@ "section": "def-server.ObservabilityRouteHandlerResources", "text": "ObservabilityRouteHandlerResources" }, - ", { id: string; name: string; description: string; indicator: { type: \"sli.apm.transaction_duration\"; params: { environment: string; service: string; transaction_type: string; transaction_name: string; 'threshold.us': number; }; } | { type: \"sli.apm.transaction_error_rate\"; params: { environment: string; service: string; transaction_type: string; transaction_name: string; } & { good_status_codes?: (\"2xx\" | \"3xx\" | \"4xx\" | \"5xx\")[] | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; query_filter: string; numerator: string; denominator: string; }; }; time_window: { duration: string; is_rolling: boolean; } | { duration: string; calendar: { start_time: string; }; }; budgeting_method: string; objective: { target: number; } & { timeslice_target?: number | undefined; timeslice_window?: string | undefined; }; summary: { sli_value: number; error_budget: { initial: number; consumed: number; remaining: number; is_estimated: boolean; }; }; revision: number; created_at: string; updated_at: string; }, ", + ", { id: string; name: string; description: string; indicator: { type: \"sli.apm.transaction_duration\"; params: { environment: string; service: string; transaction_type: string; transaction_name: string; 'threshold.us': number; }; } | { type: \"sli.apm.transaction_error_rate\"; params: { environment: string; service: string; transaction_type: string; transaction_name: string; } & { good_status_codes?: (\"2xx\" | \"3xx\" | \"4xx\" | \"5xx\")[] | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; filter: string; good: string; total: string; }; }; time_window: { duration: string; is_rolling: boolean; } | { duration: string; calendar: { start_time: string; }; }; budgeting_method: string; objective: { target: number; } & { timeslice_target?: number | undefined; timeslice_window?: string | undefined; }; settings: { timestamp_field: string; sync_delay: string; frequency: string; }; summary: { sli_value: number; error_budget: { initial: number; consumed: number; remaining: number; is_estimated: boolean; }; }; revision: number; created_at: string; updated_at: string; }, ", { "pluginId": "observability", "scope": "server", @@ -8615,11 +8800,11 @@ "TypeC", "<{ index: ", "StringC", - "; query_filter: ", + "; filter: ", "StringC", - "; numerator: ", + "; good: ", "StringC", - "; denominator: ", + "; total: ", "StringC", "; }>; }>]>; time_window: ", "UnionC", @@ -8661,7 +8846,19 @@ "Type", "<", "Duration", - ", string, unknown>; }>]>; }>; }>, ", + ", string, unknown>; }>]>; settings: ", + "TypeC", + "<{ timestamp_field: ", + "StringC", + "; sync_delay: ", + "Type", + "<", + "Duration", + ", string, unknown>; frequency: ", + "Type", + "<", + "Duration", + ", string, unknown>; }>; }>; }>, ", { "pluginId": "observability", "scope": "server", @@ -8669,7 +8866,7 @@ "section": "def-server.ObservabilityRouteHandlerResources", "text": "ObservabilityRouteHandlerResources" }, - ", { id: string; name: string; description: string; indicator: { type: \"sli.apm.transaction_duration\"; params: { environment: string; service: string; transaction_type: string; transaction_name: string; 'threshold.us': number; }; } | { type: \"sli.apm.transaction_error_rate\"; params: { environment: string; service: string; transaction_type: string; transaction_name: string; } & { good_status_codes?: (\"2xx\" | \"3xx\" | \"4xx\" | \"5xx\")[] | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; query_filter: string; numerator: string; denominator: string; }; }; time_window: { duration: string; is_rolling: boolean; } | { duration: string; calendar: { start_time: string; }; }; budgeting_method: string; objective: { target: number; } & { timeslice_target?: number | undefined; timeslice_window?: string | undefined; }; created_at: string; updated_at: string; }, ", + ", { id: string; name: string; description: string; indicator: { type: \"sli.apm.transaction_duration\"; params: { environment: string; service: string; transaction_type: string; transaction_name: string; 'threshold.us': number; }; } | { type: \"sli.apm.transaction_error_rate\"; params: { environment: string; service: string; transaction_type: string; transaction_name: string; } & { good_status_codes?: (\"2xx\" | \"3xx\" | \"4xx\" | \"5xx\")[] | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; filter: string; good: string; total: string; }; }; time_window: { duration: string; is_rolling: boolean; } | { duration: string; calendar: { start_time: string; }; }; budgeting_method: string; objective: { target: number; } & { timeslice_target?: number | undefined; timeslice_window?: string | undefined; }; settings: { timestamp_field: string; sync_delay: string; frequency: string; }; created_at: string; updated_at: string; }, ", { "pluginId": "observability", "scope": "server", @@ -8688,6 +8885,8 @@ "<\"POST /api/observability/slos\", ", "TypeC", "<{ body: ", + "IntersectionC", + "<[", "TypeC", "<{ name: ", "StringC", @@ -8781,11 +8980,11 @@ "TypeC", "<{ index: ", "StringC", - "; query_filter: ", + "; filter: ", "StringC", - "; numerator: ", + "; good: ", "StringC", - "; denominator: ", + "; total: ", "StringC", "; }>; }>]>; time_window: ", "UnionC", @@ -8827,7 +9026,21 @@ "Type", "<", "Duration", - ", string, unknown>; }>]>; }>; }>, ", + ", string, unknown>; }>]>; }>, ", + "PartialC", + "<{ settings: ", + "PartialC", + "<{ timestamp_field: ", + "StringC", + "; sync_delay: ", + "Type", + "<", + "Duration", + ", string, unknown>; frequency: ", + "Type", + "<", + "Duration", + ", string, unknown>; }>; }>]>; }>, ", { "pluginId": "observability", "scope": "server", @@ -9642,124 +9855,6 @@ } ] }, - { - "parentPluginId": "observability", - "id": "def-server.uiSettings.enableServiceMetrics", - "type": "Object", - "tags": [], - "label": "[enableServiceMetrics]", - "description": [], - "path": "x-pack/plugins/observability/server/ui_settings.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "observability", - "id": "def-server.uiSettings.enableServiceMetrics.category", - "type": "Array", - "tags": [], - "label": "category", - "description": [], - "signature": [ - "string[]" - ], - "path": "x-pack/plugins/observability/server/ui_settings.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "observability", - "id": "def-server.uiSettings.enableServiceMetrics.name", - "type": "Any", - "tags": [], - "label": "name", - "description": [], - "signature": [ - "any" - ], - "path": "x-pack/plugins/observability/server/ui_settings.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "observability", - "id": "def-server.uiSettings.enableServiceMetrics.value", - "type": "boolean", - "tags": [], - "label": "value", - "description": [], - "signature": [ - "false" - ], - "path": "x-pack/plugins/observability/server/ui_settings.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "observability", - "id": "def-server.uiSettings.enableServiceMetrics.description", - "type": "Any", - "tags": [], - "label": "description", - "description": [], - "signature": [ - "any" - ], - "path": "x-pack/plugins/observability/server/ui_settings.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "observability", - "id": "def-server.uiSettings.enableServiceMetrics.schema", - "type": "Object", - "tags": [], - "label": "schema", - "description": [], - "signature": [ - { - "pluginId": "@kbn/config-schema", - "scope": "server", - "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-server.Type", - "text": "Type" - }, - "" - ], - "path": "x-pack/plugins/observability/server/ui_settings.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "observability", - "id": "def-server.uiSettings.enableServiceMetrics.requiresPageReload", - "type": "boolean", - "tags": [], - "label": "requiresPageReload", - "description": [], - "signature": [ - "true" - ], - "path": "x-pack/plugins/observability/server/ui_settings.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "observability", - "id": "def-server.uiSettings.enableServiceMetrics.showInLabs", - "type": "boolean", - "tags": [], - "label": "showInLabs", - "description": [], - "signature": [ - "true" - ], - "path": "x-pack/plugins/observability/server/ui_settings.ts", - "deprecated": false, - "trackAdoption": false - } - ] - }, { "parentPluginId": "observability", "id": "def-server.uiSettings.apmServiceInventoryOptimizedSorting", @@ -10193,7 +10288,7 @@ "label": "value", "description": [], "signature": [ - "false" + "true" ], "path": "x-pack/plugins/observability/server/ui_settings.ts", "deprecated": false, @@ -10235,7 +10330,7 @@ "label": "showInLabs", "description": [], "signature": [ - "true" + "false" ], "path": "x-pack/plugins/observability/server/ui_settings.ts", "deprecated": false, @@ -11609,21 +11704,6 @@ "trackAdoption": false, "initialIsOpen": false }, - { - "parentPluginId": "observability", - "id": "def-common.enableServiceMetrics", - "type": "string", - "tags": [], - "label": "enableServiceMetrics", - "description": [], - "signature": [ - "\"observability:apmEnableServiceMetrics\"" - ], - "path": "x-pack/plugins/observability/common/ui_settings_keys.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - }, { "parentPluginId": "observability", "id": "def-common.maxSuggestions", diff --git a/api_docs/observability.mdx b/api_docs/observability.mdx index 097c446cdfa53..25f52f331133e 100644 --- a/api_docs/observability.mdx +++ b/api_docs/observability.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observability title: "observability" image: https://source.unsplash.com/400x175/?github description: API docs for the observability plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observability'] --- import observabilityObj from './observability.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Observability UI](https://github.com/orgs/elastic/teams/observability-u | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 569 | 42 | 566 | 31 | +| 571 | 40 | 567 | 31 | ## Client diff --git a/api_docs/osquery.mdx b/api_docs/osquery.mdx index 465f09cdb2249..0666c62f78f5d 100644 --- a/api_docs/osquery.mdx +++ b/api_docs/osquery.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/osquery title: "osquery" image: https://source.unsplash.com/400x175/?github description: API docs for the osquery plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'osquery'] --- import osqueryObj from './osquery.devdocs.json'; diff --git a/api_docs/plugin_directory.mdx b/api_docs/plugin_directory.mdx index 0e3f87851d36d..7dcaa3a357e84 100644 --- a/api_docs/plugin_directory.mdx +++ b/api_docs/plugin_directory.mdx @@ -7,7 +7,7 @@ id: kibDevDocsPluginDirectory slug: /kibana-dev-docs/api-meta/plugin-api-directory title: Directory description: Directory of public APIs available through plugins or packages. -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -15,13 +15,13 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | Count | Plugins or Packages with a
public API | Number of teams | |--------------|----------|------------------------| -| 520 | 435 | 40 | +| 527 | 439 | 40 | ### Public API health stats | API Count | Any Count | Missing comments | Missing exports | |--------------|----------|-----------------|--------| -| 33770 | 518 | 23484 | 1136 | +| 33860 | 520 | 23578 | 1149 | ## Plugin Directory @@ -45,7 +45,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | cloudLinks | [Kibana Core](https://github.com/orgs/elastic/teams/@kibana-core) | Adds the links to the Elastic Cloud console | 0 | 0 | 0 | 0 | | | [Cloud Security Posture](https://github.com/orgs/elastic/teams/cloud-posture-security) | The cloud security posture plugin | 17 | 0 | 2 | 2 | | | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 13 | 0 | 13 | 1 | -| | [Kibana Presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | The Controls Plugin contains embeddable components intended to create a simple query interface for end users, and a powerful editing suite that allows dashboard authors to build controls | 245 | 0 | 236 | 9 | +| | [Kibana Presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | The Controls Plugin contains embeddable components intended to create a simple query interface for end users, and a powerful editing suite that allows dashboard authors to build controls | 267 | 0 | 258 | 10 | | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 2796 | 17 | 1007 | 0 | | crossClusterReplication | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 0 | 0 | 0 | 0 | | customBranding | [global-experience](https://github.com/orgs/elastic/teams/kibana-global-experience) | Enables customization of Kibana | 0 | 0 | 0 | 0 | @@ -59,7 +59,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Data services are useful for searching and querying data from Elasticsearch. Helpful utilities include: a re-usable react query bar, KQL autocomplete, async search, Data Views (Index Patterns) and field formatters. | 1021 | 0 | 227 | 2 | | | [Machine Learning UI](https://github.com/orgs/elastic/teams/ml-ui) | The Data Visualizer tools help you understand your data, by analyzing the metrics and fields in a log file or an existing Elasticsearch index. | 28 | 3 | 24 | 1 | | | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 10 | 0 | 8 | 2 | -| | [Data Discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | This plugin contains the Discover application and the saved search embeddable. | 98 | 0 | 81 | 4 | +| | [Data Discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | This plugin contains the Discover application and the saved search embeddable. | 100 | 0 | 82 | 4 | | | [Data Discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | - | 37 | 0 | 35 | 2 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Adds embeddables service to Kibana | 510 | 6 | 410 | 4 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Extends embeddable plugin with more functionality | 14 | 0 | 14 | 0 | @@ -75,7 +75,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-visualizations) | Adds a `metric` renderer and function to the expression plugin. The renderer will display the `legacy metric` chart. | 51 | 0 | 51 | 2 | | | [Kibana Presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Adds 'metric' function and renderer to expressions | 32 | 0 | 27 | 0 | | | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-visualizations) | Adds a `metric` renderer and function to the expression plugin. The renderer will display the `metric` chart. | 63 | 0 | 63 | 2 | -| | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-visualizations) | Expression Partition Visualization plugin adds a `partitionVis` renderer and `pieVis`, `mosaicVis`, `treemapVis`, `waffleVis` functions to the expression plugin. The renderer will display the `pie`, `waffle`, `treemap` and `mosaic` charts. | 71 | 0 | 71 | 2 | +| | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-visualizations) | Expression Partition Visualization plugin adds a `partitionVis` renderer and `pieVis`, `mosaicVis`, `treemapVis`, `waffleVis` functions to the expression plugin. The renderer will display the `pie`, `waffle`, `treemap` and `mosaic` charts. | 72 | 0 | 72 | 2 | | | [Kibana Presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Adds 'repeatImage' function and renderer to expressions | 32 | 0 | 32 | 0 | | | [Kibana Presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Adds 'revealImage' function and renderer to expressions | 14 | 0 | 14 | 3 | | | [Kibana Presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Adds 'shape' function and renderer to expressions | 148 | 0 | 146 | 0 | @@ -85,15 +85,15 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 227 | 0 | 96 | 2 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Index pattern fields and ambiguous values formatters | 288 | 26 | 249 | 3 | | | [Machine Learning UI](https://github.com/orgs/elastic/teams/ml-ui) | The file upload plugin contains components and services for uploading a file, analyzing its data, and then importing the data into an Elasticsearch index. Supported file types include CSV, TSV, newline-delimited JSON and GeoJSON. | 62 | 0 | 62 | 2 | -| | [@elastic/kibana-app-services](https://github.com/orgs/elastic/teams/team:AppServicesUx) | File upload, download, sharing, and serving over HTTP implementation in Kibana. | 287 | 0 | 50 | 3 | +| | [@elastic/kibana-app-services](https://github.com/orgs/elastic/teams/team:AppServicesUx) | File upload, download, sharing, and serving over HTTP implementation in Kibana. | 252 | 1 | 45 | 5 | | | [@elastic/kibana-global-experience](https://github.com/orgs/elastic/teams/@elastic/kibana-global-experience) | Simple UI for managing files in Kibana | 2 | 1 | 2 | 0 | -| | [Fleet](https://github.com/orgs/elastic/teams/fleet) | - | 1025 | 3 | 920 | 19 | +| | [Fleet](https://github.com/orgs/elastic/teams/fleet) | - | 1027 | 3 | 922 | 19 | | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 68 | 0 | 14 | 5 | | globalSearchBar | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 0 | 0 | 0 | 0 | | globalSearchProviders | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 0 | 0 | 0 | 0 | | graph | [Data Discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | - | 0 | 0 | 0 | 0 | | grokdebugger | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 0 | 0 | 0 | 0 | -| | [Journey Onboarding](https://github.com/orgs/elastic/teams/platform-onboarding) | Guided onboarding framework | 43 | 0 | 43 | 3 | +| | [Journey Onboarding](https://github.com/orgs/elastic/teams/platform-onboarding) | Guided onboarding framework | 76 | 0 | 75 | 0 | | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 143 | 0 | 104 | 0 | | | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 4 | 0 | 4 | 0 | | | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 177 | 0 | 172 | 3 | @@ -107,14 +107,14 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | kibanaUsageCollection | [Kibana Telemetry](https://github.com/orgs/elastic/teams/kibana-telemetry) | - | 0 | 0 | 0 | 0 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | - | 624 | 3 | 424 | 8 | | | [Security Team](https://github.com/orgs/elastic/teams/security-team) | - | 3 | 0 | 3 | 1 | -| | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-visualizations) | Visualization editor allowing to quickly and easily configure compelling visualizations to use on dashboards and canvas workpads. Exposes components to embed visualizations and link into the Lens editor from within other apps in Kibana. | 685 | 0 | 590 | 48 | +| | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-visualizations) | Visualization editor allowing to quickly and easily configure compelling visualizations to use on dashboards and canvas workpads. Exposes components to embed visualizations and link into the Lens editor from within other apps in Kibana. | 693 | 0 | 597 | 50 | | | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 8 | 0 | 8 | 0 | | | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 3 | 0 | 3 | 0 | | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 117 | 0 | 42 | 10 | | | [Security detections response](https://github.com/orgs/elastic/teams/security-detections-response) | - | 206 | 0 | 93 | 51 | | logstash | [Logstash](https://github.com/orgs/elastic/teams/logstash) | - | 0 | 0 | 0 | 0 | | | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-visualizations) | - | 41 | 0 | 41 | 6 | -| | [GIS](https://github.com/orgs/elastic/teams/kibana-gis) | - | 266 | 0 | 265 | 26 | +| | [GIS](https://github.com/orgs/elastic/teams/kibana-gis) | - | 267 | 0 | 266 | 26 | | | [GIS](https://github.com/orgs/elastic/teams/kibana-gis) | - | 67 | 0 | 67 | 0 | | | [Machine Learning UI](https://github.com/orgs/elastic/teams/ml-ui) | This plugin provides access to the machine learning features provided by Elastic. | 254 | 9 | 78 | 40 | | | [Stack Monitoring](https://github.com/orgs/elastic/teams/stack-monitoring-ui) | - | 15 | 3 | 13 | 1 | @@ -122,7 +122,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | - | 34 | 0 | 34 | 2 | | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 17 | 0 | 17 | 0 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | - | 2 | 0 | 2 | 1 | -| | [Observability UI](https://github.com/orgs/elastic/teams/observability-ui) | - | 569 | 42 | 566 | 31 | +| | [Observability UI](https://github.com/orgs/elastic/teams/observability-ui) | - | 571 | 40 | 567 | 31 | | | [Security asset management](https://github.com/orgs/elastic/teams/security-asset-management) | - | 21 | 0 | 21 | 5 | | painlessLab | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 0 | 0 | 0 | 0 | | | [Kibana Presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | The Presentation Utility Plugin is a set of common, shared components and toolkits for solutions within the Presentation space, (e.g. Dashboards, Canvas). | 227 | 7 | 171 | 12 | @@ -137,7 +137,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 130 | 0 | 117 | 0 | | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 79 | 0 | 73 | 3 | | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 98 | 0 | 50 | 1 | -| | [Data Discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | This plugin contains the definition and helper methods around saved searches, used by discover and visualizations. | 44 | 0 | 44 | 1 | +| | [Data Discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | This plugin contains the definition and helper methods around saved searches, used by discover and visualizations. | 45 | 0 | 45 | 1 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | - | 32 | 0 | 13 | 0 | | | [Kibana Reporting Services](https://github.com/orgs/elastic/teams/kibana-reporting-services) | Kibana Screenshotting Plugin | 27 | 0 | 8 | 4 | | searchprofiler | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 0 | 0 | 0 | 0 | @@ -155,15 +155,15 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [Kibana Telemetry](https://github.com/orgs/elastic/teams/kibana-telemetry) | - | 31 | 0 | 26 | 6 | | | [Kibana Telemetry](https://github.com/orgs/elastic/teams/kibana-telemetry) | - | 1 | 0 | 1 | 0 | | | [Kibana Telemetry](https://github.com/orgs/elastic/teams/kibana-telemetry) | - | 11 | 0 | 10 | 0 | -| | [Protections Experience Team](https://github.com/orgs/elastic/teams/protections-experience) | Elastic threat intelligence helps you see if you are open to or have been subject to current or historical known threats | 26 | 0 | 8 | 3 | +| | [Protections Experience Team](https://github.com/orgs/elastic/teams/protections-experience) | Elastic threat intelligence helps you see if you are open to or have been subject to current or historical known threats | 34 | 0 | 14 | 3 | | | [Security solution](https://github.com/orgs/elastic/teams/security-solution) | - | 462 | 1 | 350 | 33 | | | [Machine Learning UI](https://github.com/orgs/elastic/teams/ml-ui) | This plugin provides access to the transforms features provided by Elastic. Transforms enable you to convert existing Elasticsearch indices into summarized indices, which provide opportunities for new insights and analytics. | 4 | 0 | 4 | 1 | | translations | [Kibana Localization](https://github.com/orgs/elastic/teams/kibana-localization) | - | 0 | 0 | 0 | 0 | -| | [Response Ops](https://github.com/orgs/elastic/teams/response-ops) | - | 531 | 11 | 502 | 51 | +| | [Response Ops](https://github.com/orgs/elastic/teams/response-ops) | - | 532 | 11 | 503 | 51 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Adds UI Actions service to Kibana | 133 | 2 | 92 | 11 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Extends UI Actions plugin with more functionality | 206 | 0 | 142 | 9 | -| | [Data Discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | Contains functionality for the field list which can be integrated into apps | 203 | 0 | 192 | 7 | -| | [Data Discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | The `unifiedHistogram` plugin provides UI components to create a layout including a resizable histogram and a main display. | 56 | 0 | 29 | 0 | +| | [Data Discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | Contains functionality for the field list which can be integrated into apps | 215 | 0 | 203 | 7 | +| | [Data Discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | The `unifiedHistogram` plugin provides UI components to create a layout including a resizable histogram and a main display. | 52 | 0 | 15 | 0 | | | [Visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | Contains all the key functionality of Kibana's unified search experience.Contains all the key functionality of Kibana's unified search experience. | 134 | 2 | 106 | 18 | | upgradeAssistant | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 0 | 0 | 0 | 0 | | urlDrilldown | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Adds drilldown implementations to Kibana | 0 | 0 | 0 | 0 | @@ -388,7 +388,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [Owner missing] | - | 1 | 0 | 0 | 0 | | | [Owner missing] | - | 3 | 0 | 0 | 0 | | | [Owner missing] | - | 23 | 0 | 21 | 1 | -| | [Owner missing] | - | 6 | 0 | 0 | 0 | +| | [Owner missing] | - | 17 | 1 | 8 | 0 | | | [Owner missing] | - | 3 | 0 | 3 | 0 | | | Kibana Core | - | 1 | 0 | 1 | 0 | | | [Owner missing] | - | 32 | 0 | 22 | 0 | @@ -397,7 +397,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | Kibana Core | - | 61 | 0 | 1 | 0 | | | [Owner missing] | - | 43 | 0 | 36 | 0 | | | Visualizations | - | 52 | 12 | 41 | 0 | -| | [Owner missing] | - | 20 | 0 | 20 | 2 | +| | [Owner missing] | - | 22 | 0 | 22 | 3 | | | [Owner missing] | - | 13 | 0 | 13 | 0 | | | [Owner missing] | - | 64 | 0 | 59 | 5 | | | [Owner missing] | - | 96 | 0 | 95 | 0 | @@ -419,10 +419,11 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [Owner missing] | Just some helpers for kibana plugin devs. | 1 | 0 | 1 | 0 | | | [Owner missing] | - | 21 | 0 | 10 | 0 | | | [Owner missing] | - | 6 | 0 | 6 | 1 | +| | [Owner missing] | - | 11 | 2 | 7 | 0 | | | [Owner missing] | - | 96 | 0 | 93 | 0 | | | [Owner missing] | Security Solution auto complete | 56 | 1 | 41 | 1 | | | [Owner missing] | security solution elastic search utilities to use across plugins such lists, security_solution, cases, etc... | 67 | 0 | 61 | 1 | -| | [Owner missing] | - | 102 | 0 | 91 | 1 | +| | [Owner missing] | - | 104 | 0 | 93 | 1 | | | [Owner missing] | Security Solution utilities for React hooks | 15 | 0 | 7 | 0 | | | [Owner missing] | io ts utilities and types to be shared with plugins from the security solution project | 138 | 0 | 119 | 0 | | | [Owner missing] | io ts utilities and types to be shared with plugins from the security solution project | 511 | 1 | 498 | 0 | @@ -445,9 +446,11 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [Owner missing] | - | 25 | 0 | 8 | 0 | | | [Owner missing] | - | 10 | 0 | 4 | 0 | | | [Owner missing] | - | 32 | 0 | 28 | 0 | +| | [Owner missing] | - | 5 | 0 | 4 | 0 | | | [Owner missing] | - | 3 | 0 | 2 | 0 | | | [Owner missing] | - | 2 | 0 | 2 | 0 | -| | [Owner missing] | - | 15 | 0 | 13 | 0 | +| | [Owner missing] | - | 1 | 0 | 1 | 0 | +| | [Owner missing] | - | 17 | 0 | 15 | 0 | | | [Owner missing] | - | 17 | 0 | 9 | 0 | | | [Owner missing] | - | 10 | 0 | 9 | 0 | | | [Owner missing] | - | 2 | 0 | 2 | 1 | @@ -465,6 +468,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [Owner missing] | - | 5 | 0 | 3 | 0 | | | [Owner missing] | - | 25 | 0 | 10 | 0 | | | [Owner missing] | - | 17 | 0 | 16 | 0 | +| | [Owner missing] | - | 2 | 0 | 1 | 0 | | | [Owner missing] | - | 2 | 0 | 1 | 0 | | | [Owner missing] | - | 1 | 0 | 1 | 0 | | | [Owner missing] | - | 2 | 0 | 0 | 0 | diff --git a/api_docs/presentation_util.mdx b/api_docs/presentation_util.mdx index 992c2f38ef4d5..85f6485348562 100644 --- a/api_docs/presentation_util.mdx +++ b/api_docs/presentation_util.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/presentationUtil title: "presentationUtil" image: https://source.unsplash.com/400x175/?github description: API docs for the presentationUtil plugin -date: 2022-11-29 +date: 2022-12-06 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 1e782ffe89123..af66d2ac52e8d 100644 --- a/api_docs/profiling.mdx +++ b/api_docs/profiling.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/profiling title: "profiling" image: https://source.unsplash.com/400x175/?github description: API docs for the profiling plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'profiling'] --- import profilingObj from './profiling.devdocs.json'; diff --git a/api_docs/remote_clusters.mdx b/api_docs/remote_clusters.mdx index ceb8af40ebf2b..b09b8bec09e5e 100644 --- a/api_docs/remote_clusters.mdx +++ b/api_docs/remote_clusters.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/remoteClusters title: "remoteClusters" image: https://source.unsplash.com/400x175/?github description: API docs for the remoteClusters plugin -date: 2022-11-29 +date: 2022-12-06 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 41073417142c6..d121c901fd081 100644 --- a/api_docs/reporting.mdx +++ b/api_docs/reporting.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/reporting title: "reporting" image: https://source.unsplash.com/400x175/?github description: API docs for the reporting plugin -date: 2022-11-29 +date: 2022-12-06 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 910acecc27fe3..810a2537f3cf3 100644 --- a/api_docs/rollup.mdx +++ b/api_docs/rollup.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/rollup title: "rollup" image: https://source.unsplash.com/400x175/?github description: API docs for the rollup plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'rollup'] --- import rollupObj from './rollup.devdocs.json'; diff --git a/api_docs/rule_registry.devdocs.json b/api_docs/rule_registry.devdocs.json index ad2e887fe4838..94a78d49d29a0 100644 --- a/api_docs/rule_registry.devdocs.json +++ b/api_docs/rule_registry.devdocs.json @@ -4520,7 +4520,7 @@ "label": "ParsedTechnicalFields", "description": [], "signature": [ - "{ readonly '@timestamp': string; readonly \"kibana.alert.rule.rule_type_id\": string; readonly \"kibana.alert.rule.consumer\": string; readonly \"kibana.alert.rule.producer\": string; readonly \"kibana.space_ids\": string[]; readonly \"kibana.alert.uuid\": string; readonly \"kibana.alert.instance.id\": string; readonly \"kibana.alert.status\": string; readonly \"kibana.alert.rule.category\": string; readonly \"kibana.alert.rule.uuid\": string; readonly \"kibana.alert.rule.name\": string; readonly tags?: string[] | undefined; readonly 'event.action'?: string | undefined; readonly \"kibana.alert.rule.execution.uuid\"?: string | undefined; readonly \"kibana.alert.rule.parameters\"?: { [key: string]: unknown; } | undefined; readonly \"kibana.alert.start\"?: string | undefined; readonly \"kibana.alert.time_range\"?: unknown; readonly \"kibana.alert.end\"?: string | undefined; readonly \"kibana.alert.duration.us\"?: number | undefined; readonly \"kibana.alert.severity\"?: string | undefined; readonly \"kibana.alert.flapping\"?: number | boolean | undefined; readonly \"kibana.version\"?: string | undefined; readonly \"ecs.version\"?: string | undefined; readonly \"kibana.alert.risk_score\"?: number | undefined; readonly \"kibana.alert.workflow_status\"?: string | undefined; readonly \"kibana.alert.workflow_user\"?: string | undefined; readonly \"kibana.alert.workflow_reason\"?: string | undefined; readonly \"kibana.alert.system_status\"?: string | undefined; readonly \"kibana.alert.action_group\"?: string | undefined; readonly \"kibana.alert.reason\"?: string | undefined; readonly \"kibana.alert.rule.author\"?: string | undefined; readonly \"kibana.alert.rule.created_at\"?: string | undefined; readonly \"kibana.alert.rule.created_by\"?: string | undefined; readonly \"kibana.alert.rule.description\"?: string | undefined; readonly \"kibana.alert.rule.enabled\"?: string | undefined; readonly \"kibana.alert.rule.from\"?: string | undefined; readonly \"kibana.alert.rule.interval\"?: string | undefined; readonly \"kibana.alert.rule.license\"?: string | undefined; readonly \"kibana.alert.rule.note\"?: string | undefined; readonly \"kibana.alert.rule.references\"?: string[] | undefined; readonly \"kibana.alert.rule.rule_id\"?: string | undefined; readonly \"kibana.alert.rule.rule_name_override\"?: string | undefined; readonly \"kibana.alert.rule.tags\"?: string[] | undefined; readonly \"kibana.alert.rule.to\"?: string | undefined; readonly \"kibana.alert.rule.type\"?: string | undefined; readonly \"kibana.alert.rule.updated_at\"?: string | undefined; readonly \"kibana.alert.rule.updated_by\"?: string | undefined; readonly \"kibana.alert.rule.version\"?: string | undefined; readonly \"kibana.alert.suppression.terms.field\"?: string[] | undefined; readonly \"kibana.alert.suppression.terms.value\"?: string[] | undefined; readonly \"kibana.alert.suppression.start\"?: string | undefined; readonly \"kibana.alert.suppression.end\"?: string | undefined; readonly \"kibana.alert.suppression.docs_count\"?: number | undefined; readonly 'event.kind'?: string | undefined; }" + "{ readonly '@timestamp': string; readonly \"kibana.alert.rule.rule_type_id\": string; readonly \"kibana.alert.rule.consumer\": string; readonly \"kibana.alert.rule.producer\": string; readonly \"kibana.space_ids\": string[]; readonly \"kibana.alert.uuid\": string; readonly \"kibana.alert.instance.id\": string; readonly \"kibana.alert.status\": string; readonly \"kibana.alert.rule.category\": string; readonly \"kibana.alert.rule.uuid\": string; readonly \"kibana.alert.rule.name\": string; readonly tags?: string[] | undefined; readonly 'event.action'?: string | undefined; readonly \"kibana.alert.rule.execution.uuid\"?: string | undefined; readonly \"kibana.alert.rule.parameters\"?: { [key: string]: unknown; } | undefined; readonly \"kibana.alert.start\"?: string | undefined; readonly \"kibana.alert.time_range\"?: unknown; readonly \"kibana.alert.end\"?: string | undefined; readonly \"kibana.alert.duration.us\"?: number | undefined; readonly \"kibana.alert.severity\"?: string | undefined; readonly \"kibana.alert.flapping\"?: boolean | undefined; readonly \"kibana.version\"?: string | undefined; readonly \"ecs.version\"?: string | undefined; readonly \"kibana.alert.risk_score\"?: number | undefined; readonly \"kibana.alert.workflow_status\"?: string | undefined; readonly \"kibana.alert.workflow_user\"?: string | undefined; readonly \"kibana.alert.workflow_reason\"?: string | undefined; readonly \"kibana.alert.system_status\"?: string | undefined; readonly \"kibana.alert.action_group\"?: string | undefined; readonly \"kibana.alert.reason\"?: string | undefined; readonly \"kibana.alert.rule.author\"?: string | undefined; readonly \"kibana.alert.rule.created_at\"?: string | undefined; readonly \"kibana.alert.rule.created_by\"?: string | undefined; readonly \"kibana.alert.rule.description\"?: string | undefined; readonly \"kibana.alert.rule.enabled\"?: string | undefined; readonly \"kibana.alert.rule.from\"?: string | undefined; readonly \"kibana.alert.rule.interval\"?: string | undefined; readonly \"kibana.alert.rule.license\"?: string | undefined; readonly \"kibana.alert.rule.note\"?: string | undefined; readonly \"kibana.alert.rule.references\"?: string[] | undefined; readonly \"kibana.alert.rule.rule_id\"?: string | undefined; readonly \"kibana.alert.rule.rule_name_override\"?: string | undefined; readonly \"kibana.alert.rule.tags\"?: string[] | undefined; readonly \"kibana.alert.rule.to\"?: string | undefined; readonly \"kibana.alert.rule.type\"?: string | undefined; readonly \"kibana.alert.rule.updated_at\"?: string | undefined; readonly \"kibana.alert.rule.updated_by\"?: string | undefined; readonly \"kibana.alert.rule.version\"?: string | undefined; readonly \"kibana.alert.suppression.terms.field\"?: string[] | undefined; readonly \"kibana.alert.suppression.terms.value\"?: string[] | undefined; readonly \"kibana.alert.suppression.start\"?: string | undefined; readonly \"kibana.alert.suppression.end\"?: string | undefined; readonly \"kibana.alert.suppression.docs_count\"?: number | undefined; readonly 'event.kind'?: string | undefined; }" ], "path": "x-pack/plugins/rule_registry/common/parse_technical_fields.ts", "deprecated": false, diff --git a/api_docs/rule_registry.mdx b/api_docs/rule_registry.mdx index d977c76b72971..a4c65e081973e 100644 --- a/api_docs/rule_registry.mdx +++ b/api_docs/rule_registry.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ruleRegistry title: "ruleRegistry" image: https://source.unsplash.com/400x175/?github description: API docs for the ruleRegistry plugin -date: 2022-11-29 +date: 2022-12-06 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 983cba71020b0..7d67a6ae310b9 100644 --- a/api_docs/runtime_fields.mdx +++ b/api_docs/runtime_fields.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/runtimeFields title: "runtimeFields" image: https://source.unsplash.com/400x175/?github description: API docs for the runtimeFields plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'runtimeFields'] --- import runtimeFieldsObj from './runtime_fields.devdocs.json'; diff --git a/api_docs/saved_objects.devdocs.json b/api_docs/saved_objects.devdocs.json index 46665808b0549..0762363169d52 100644 --- a/api_docs/saved_objects.devdocs.json +++ b/api_docs/saved_objects.devdocs.json @@ -631,14 +631,6 @@ "plugin": "embeddable", "path": "src/plugins/embeddable/public/lib/attribute_service/attribute_service.tsx" }, - { - "plugin": "discover", - "path": "src/plugins/discover/public/application/main/components/top_nav/on_save_search.tsx" - }, - { - "plugin": "discover", - "path": "src/plugins/discover/public/application/main/components/top_nav/on_save_search.tsx" - }, { "plugin": "presentationUtil", "path": "src/plugins/presentation_util/public/components/saved_object_save_modal_dashboard.tsx" @@ -655,6 +647,14 @@ "plugin": "dashboard", "path": "src/plugins/dashboard/public/application/top_nav/save_modal.tsx" }, + { + "plugin": "discover", + "path": "src/plugins/discover/public/application/main/components/top_nav/on_save_search.tsx" + }, + { + "plugin": "discover", + "path": "src/plugins/discover/public/application/main/components/top_nav/on_save_search.tsx" + }, { "plugin": "graph", "path": "x-pack/plugins/graph/public/components/save_modal.tsx" diff --git a/api_docs/saved_objects.mdx b/api_docs/saved_objects.mdx index 4339f937b58f1..fd36a83407f44 100644 --- a/api_docs/saved_objects.mdx +++ b/api_docs/saved_objects.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjects title: "savedObjects" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjects plugin -date: 2022-11-29 +date: 2022-12-06 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 3e4117eb6d957..7ac14f75e2ff4 100644 --- a/api_docs/saved_objects_finder.mdx +++ b/api_docs/saved_objects_finder.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsFinder title: "savedObjectsFinder" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsFinder plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsFinder'] --- import savedObjectsFinderObj from './saved_objects_finder.devdocs.json'; diff --git a/api_docs/saved_objects_management.devdocs.json b/api_docs/saved_objects_management.devdocs.json index 5712c5eb8d603..eec243d87398b 100644 --- a/api_docs/saved_objects_management.devdocs.json +++ b/api_docs/saved_objects_management.devdocs.json @@ -302,7 +302,7 @@ "section": "def-public.SavedObjectsManagementRecord", "text": "SavedObjectsManagementRecord" }, - ") => React.ReactNode) | undefined; hidden?: boolean | undefined; color?: string | undefined; id?: string | undefined; className?: string | undefined; title?: string | undefined; onChange?: React.FormEventHandler | undefined; onKeyDown?: React.KeyboardEventHandler | undefined; onClick?: React.MouseEventHandler | undefined; width?: string | undefined; security?: string | undefined; field: (string & {}) | keyof ", + ") => React.ReactNode) | undefined; hidden?: boolean | undefined; color?: string | undefined; id?: string | undefined; className?: string | undefined; title?: string | undefined; onChange?: React.FormEventHandler | undefined; onKeyDown?: React.KeyboardEventHandler | undefined; onClick?: React.MouseEventHandler | undefined; security?: string | undefined; field: (string & {}) | keyof ", { "pluginId": "savedObjectsManagement", "scope": "public", @@ -310,11 +310,11 @@ "section": "def-public.SavedObjectsManagementRecord", "text": "SavedObjectsManagementRecord" }, - "; headers?: string | undefined; defaultValue?: string | number | readonly string[] | undefined; lang?: string | undefined; defaultChecked?: boolean | undefined; suppressContentEditableWarning?: boolean | undefined; suppressHydrationWarning?: boolean | undefined; accessKey?: string | undefined; contentEditable?: \"inherit\" | Booleanish | undefined; contextMenu?: string | undefined; dir?: string | undefined; draggable?: Booleanish | undefined; placeholder?: string | undefined; slot?: string | undefined; spellCheck?: Booleanish | undefined; style?: React.CSSProperties | undefined; tabIndex?: number | undefined; translate?: \"no\" | \"yes\" | undefined; radioGroup?: string | undefined; role?: React.AriaRole | undefined; about?: string | undefined; datatype?: string | undefined; inlist?: any; prefix?: string | undefined; property?: string | undefined; resource?: string | undefined; typeof?: string | undefined; vocab?: string | undefined; autoCapitalize?: string | undefined; autoCorrect?: string | undefined; autoSave?: string | undefined; itemProp?: string | undefined; itemScope?: boolean | undefined; itemType?: string | undefined; itemID?: string | undefined; itemRef?: string | undefined; results?: number | undefined; unselectable?: \"on\" | \"off\" | undefined; inputMode?: \"none\" | \"email\" | \"search\" | \"text\" | \"tel\" | \"url\" | \"numeric\" | \"decimal\" | undefined; is?: string | undefined; 'aria-activedescendant'?: string | undefined; 'aria-atomic'?: Booleanish | undefined; 'aria-autocomplete'?: \"none\" | \"list\" | \"inline\" | \"both\" | undefined; 'aria-busy'?: Booleanish | undefined; 'aria-checked'?: boolean | \"mixed\" | \"false\" | \"true\" | undefined; 'aria-colcount'?: number | undefined; 'aria-colindex'?: number | undefined; 'aria-colspan'?: number | undefined; 'aria-controls'?: string | undefined; 'aria-current'?: boolean | \"date\" | \"location\" | \"time\" | \"page\" | \"false\" | \"true\" | \"step\" | undefined; 'aria-describedby'?: string | undefined; 'aria-details'?: string | undefined; 'aria-disabled'?: Booleanish | undefined; 'aria-dropeffect'?: \"none\" | \"copy\" | \"link\" | \"execute\" | \"move\" | \"popup\" | undefined; 'aria-errormessage'?: string | undefined; 'aria-expanded'?: Booleanish | undefined; 'aria-flowto'?: string | undefined; 'aria-grabbed'?: Booleanish | undefined; 'aria-haspopup'?: boolean | \"grid\" | \"menu\" | \"false\" | \"true\" | \"dialog\" | \"listbox\" | \"tree\" | undefined; 'aria-hidden'?: Booleanish | undefined; 'aria-invalid'?: boolean | \"false\" | \"true\" | \"grammar\" | \"spelling\" | undefined; 'aria-keyshortcuts'?: string | undefined; 'aria-label'?: string | undefined; 'aria-labelledby'?: string | undefined; 'aria-level'?: number | undefined; 'aria-live'?: \"off\" | \"assertive\" | \"polite\" | undefined; 'aria-modal'?: Booleanish | undefined; 'aria-multiline'?: Booleanish | undefined; 'aria-multiselectable'?: Booleanish | undefined; 'aria-orientation'?: \"horizontal\" | \"vertical\" | undefined; 'aria-owns'?: string | undefined; 'aria-placeholder'?: string | undefined; 'aria-posinset'?: number | undefined; 'aria-pressed'?: boolean | \"mixed\" | \"false\" | \"true\" | undefined; 'aria-readonly'?: Booleanish | undefined; 'aria-relevant'?: \"all\" | \"text\" | \"additions\" | \"additions removals\" | \"additions text\" | \"removals\" | \"removals additions\" | \"removals text\" | \"text additions\" | \"text removals\" | undefined; 'aria-required'?: Booleanish | undefined; 'aria-roledescription'?: string | undefined; 'aria-rowcount'?: number | undefined; 'aria-rowindex'?: number | undefined; 'aria-rowspan'?: number | undefined; 'aria-selected'?: Booleanish | undefined; 'aria-setsize'?: number | undefined; 'aria-sort'?: \"none\" | \"other\" | \"ascending\" | \"descending\" | undefined; 'aria-valuemax'?: number | undefined; 'aria-valuemin'?: number | undefined; 'aria-valuenow'?: number | undefined; 'aria-valuetext'?: string | undefined; dangerouslySetInnerHTML?: { __html: string; } | undefined; onCopy?: React.ClipboardEventHandler | undefined; onCopyCapture?: React.ClipboardEventHandler | undefined; onCut?: React.ClipboardEventHandler | undefined; onCutCapture?: React.ClipboardEventHandler | undefined; onPaste?: React.ClipboardEventHandler | undefined; onPasteCapture?: React.ClipboardEventHandler | undefined; onCompositionEnd?: React.CompositionEventHandler | undefined; onCompositionEndCapture?: React.CompositionEventHandler | undefined; onCompositionStart?: React.CompositionEventHandler | undefined; onCompositionStartCapture?: React.CompositionEventHandler | undefined; onCompositionUpdate?: React.CompositionEventHandler | undefined; onCompositionUpdateCapture?: React.CompositionEventHandler | undefined; onFocus?: React.FocusEventHandler | undefined; onFocusCapture?: React.FocusEventHandler | undefined; onBlur?: React.FocusEventHandler | undefined; onBlurCapture?: React.FocusEventHandler | undefined; onChangeCapture?: React.FormEventHandler | undefined; onBeforeInput?: React.FormEventHandler | undefined; onBeforeInputCapture?: React.FormEventHandler | undefined; onInput?: React.FormEventHandler | undefined; onInputCapture?: React.FormEventHandler | undefined; onReset?: React.FormEventHandler | undefined; onResetCapture?: React.FormEventHandler | undefined; onSubmit?: React.FormEventHandler | undefined; onSubmitCapture?: React.FormEventHandler | undefined; onInvalid?: React.FormEventHandler | undefined; onInvalidCapture?: React.FormEventHandler | undefined; onLoad?: React.ReactEventHandler | undefined; onLoadCapture?: React.ReactEventHandler | undefined; onErrorCapture?: React.ReactEventHandler | undefined; onKeyDownCapture?: React.KeyboardEventHandler | undefined; onKeyPress?: React.KeyboardEventHandler | undefined; onKeyPressCapture?: React.KeyboardEventHandler | undefined; onKeyUp?: React.KeyboardEventHandler | undefined; onKeyUpCapture?: React.KeyboardEventHandler | undefined; onAbort?: React.ReactEventHandler | undefined; onAbortCapture?: React.ReactEventHandler | undefined; onCanPlay?: React.ReactEventHandler | undefined; onCanPlayCapture?: React.ReactEventHandler | undefined; onCanPlayThrough?: React.ReactEventHandler | undefined; onCanPlayThroughCapture?: React.ReactEventHandler | undefined; onDurationChange?: React.ReactEventHandler | undefined; onDurationChangeCapture?: React.ReactEventHandler | undefined; onEmptied?: React.ReactEventHandler | undefined; onEmptiedCapture?: React.ReactEventHandler | undefined; onEncrypted?: React.ReactEventHandler | undefined; onEncryptedCapture?: React.ReactEventHandler | undefined; onEnded?: React.ReactEventHandler | undefined; onEndedCapture?: React.ReactEventHandler | undefined; onLoadedData?: React.ReactEventHandler | undefined; onLoadedDataCapture?: React.ReactEventHandler | undefined; onLoadedMetadata?: React.ReactEventHandler | undefined; onLoadedMetadataCapture?: React.ReactEventHandler | undefined; onLoadStart?: React.ReactEventHandler | undefined; onLoadStartCapture?: React.ReactEventHandler | undefined; onPause?: React.ReactEventHandler | undefined; onPauseCapture?: React.ReactEventHandler | undefined; onPlay?: React.ReactEventHandler | undefined; onPlayCapture?: React.ReactEventHandler | undefined; onPlaying?: React.ReactEventHandler | undefined; onPlayingCapture?: React.ReactEventHandler | undefined; onProgress?: React.ReactEventHandler | undefined; onProgressCapture?: React.ReactEventHandler | undefined; onRateChange?: React.ReactEventHandler | undefined; onRateChangeCapture?: React.ReactEventHandler | undefined; onSeeked?: React.ReactEventHandler | undefined; onSeekedCapture?: React.ReactEventHandler | undefined; onSeeking?: React.ReactEventHandler | undefined; onSeekingCapture?: React.ReactEventHandler | undefined; onStalled?: React.ReactEventHandler | undefined; onStalledCapture?: React.ReactEventHandler | undefined; onSuspend?: React.ReactEventHandler | undefined; onSuspendCapture?: React.ReactEventHandler | undefined; onTimeUpdate?: React.ReactEventHandler | undefined; onTimeUpdateCapture?: React.ReactEventHandler | undefined; onVolumeChange?: React.ReactEventHandler | undefined; onVolumeChangeCapture?: React.ReactEventHandler | undefined; onWaiting?: React.ReactEventHandler | undefined; onWaitingCapture?: React.ReactEventHandler | undefined; onAuxClick?: React.MouseEventHandler | undefined; onAuxClickCapture?: React.MouseEventHandler | undefined; onClickCapture?: React.MouseEventHandler | undefined; onContextMenu?: React.MouseEventHandler | undefined; onContextMenuCapture?: React.MouseEventHandler | undefined; onDoubleClick?: React.MouseEventHandler | undefined; onDoubleClickCapture?: React.MouseEventHandler | undefined; onDrag?: React.DragEventHandler | undefined; onDragCapture?: React.DragEventHandler | undefined; onDragEnd?: React.DragEventHandler | undefined; onDragEndCapture?: React.DragEventHandler | undefined; onDragEnter?: React.DragEventHandler | undefined; onDragEnterCapture?: React.DragEventHandler | undefined; onDragExit?: React.DragEventHandler | undefined; onDragExitCapture?: React.DragEventHandler | undefined; onDragLeave?: React.DragEventHandler | undefined; onDragLeaveCapture?: React.DragEventHandler | undefined; onDragOver?: React.DragEventHandler | undefined; onDragOverCapture?: React.DragEventHandler | undefined; onDragStart?: React.DragEventHandler | undefined; onDragStartCapture?: React.DragEventHandler | undefined; onDrop?: React.DragEventHandler | undefined; onDropCapture?: React.DragEventHandler | undefined; onMouseDown?: React.MouseEventHandler | undefined; onMouseDownCapture?: React.MouseEventHandler | undefined; onMouseEnter?: React.MouseEventHandler | undefined; onMouseLeave?: React.MouseEventHandler | undefined; onMouseMove?: React.MouseEventHandler | undefined; onMouseMoveCapture?: React.MouseEventHandler | undefined; onMouseOut?: React.MouseEventHandler | undefined; onMouseOutCapture?: React.MouseEventHandler | undefined; onMouseOver?: React.MouseEventHandler | undefined; onMouseOverCapture?: React.MouseEventHandler | undefined; onMouseUp?: React.MouseEventHandler | undefined; onMouseUpCapture?: React.MouseEventHandler | undefined; onSelect?: React.ReactEventHandler | undefined; onSelectCapture?: React.ReactEventHandler | undefined; onTouchCancel?: React.TouchEventHandler | undefined; onTouchCancelCapture?: React.TouchEventHandler | undefined; onTouchEnd?: React.TouchEventHandler | undefined; onTouchEndCapture?: React.TouchEventHandler | undefined; onTouchMove?: React.TouchEventHandler | undefined; onTouchMoveCapture?: React.TouchEventHandler | undefined; onTouchStart?: React.TouchEventHandler | undefined; onTouchStartCapture?: React.TouchEventHandler | undefined; onPointerDown?: React.PointerEventHandler | undefined; onPointerDownCapture?: React.PointerEventHandler | undefined; onPointerMove?: React.PointerEventHandler | undefined; onPointerMoveCapture?: React.PointerEventHandler | undefined; onPointerUp?: React.PointerEventHandler | undefined; onPointerUpCapture?: React.PointerEventHandler | undefined; onPointerCancel?: React.PointerEventHandler | undefined; onPointerCancelCapture?: React.PointerEventHandler | undefined; onPointerEnter?: React.PointerEventHandler | undefined; onPointerEnterCapture?: React.PointerEventHandler | undefined; onPointerLeave?: React.PointerEventHandler | undefined; onPointerLeaveCapture?: React.PointerEventHandler | undefined; onPointerOver?: React.PointerEventHandler | undefined; onPointerOverCapture?: React.PointerEventHandler | undefined; onPointerOut?: React.PointerEventHandler | undefined; onPointerOutCapture?: React.PointerEventHandler | undefined; onGotPointerCapture?: React.PointerEventHandler | undefined; onGotPointerCaptureCapture?: React.PointerEventHandler | undefined; onLostPointerCapture?: React.PointerEventHandler | undefined; onLostPointerCaptureCapture?: React.PointerEventHandler | undefined; onScroll?: React.UIEventHandler | undefined; onScrollCapture?: React.UIEventHandler | undefined; onWheel?: React.WheelEventHandler | undefined; onWheelCapture?: React.WheelEventHandler | undefined; onAnimationStart?: React.AnimationEventHandler | undefined; onAnimationStartCapture?: React.AnimationEventHandler | undefined; onAnimationEnd?: React.AnimationEventHandler | undefined; onAnimationEndCapture?: React.AnimationEventHandler | undefined; onAnimationIteration?: React.AnimationEventHandler | undefined; onAnimationIterationCapture?: React.AnimationEventHandler | undefined; onTransitionEnd?: React.TransitionEventHandler | undefined; onTransitionEndCapture?: React.TransitionEventHandler | undefined; 'data-test-subj'?: string | undefined; css?: ", + "; headers?: string | undefined; defaultValue?: string | number | readonly string[] | undefined; lang?: string | undefined; defaultChecked?: boolean | undefined; suppressContentEditableWarning?: boolean | undefined; suppressHydrationWarning?: boolean | undefined; accessKey?: string | undefined; contentEditable?: \"inherit\" | Booleanish | undefined; contextMenu?: string | undefined; dir?: string | undefined; draggable?: Booleanish | undefined; placeholder?: string | undefined; slot?: string | undefined; spellCheck?: Booleanish | undefined; style?: React.CSSProperties | undefined; tabIndex?: number | undefined; translate?: \"no\" | \"yes\" | undefined; radioGroup?: string | undefined; role?: React.AriaRole | undefined; about?: string | undefined; datatype?: string | undefined; inlist?: any; prefix?: string | undefined; property?: string | undefined; resource?: string | undefined; typeof?: string | undefined; vocab?: string | undefined; autoCapitalize?: string | undefined; autoCorrect?: string | undefined; autoSave?: string | undefined; itemProp?: string | undefined; itemScope?: boolean | undefined; itemType?: string | undefined; itemID?: string | undefined; itemRef?: string | undefined; results?: number | undefined; unselectable?: \"on\" | \"off\" | undefined; inputMode?: \"none\" | \"email\" | \"search\" | \"text\" | \"url\" | \"tel\" | \"numeric\" | \"decimal\" | undefined; is?: string | undefined; 'aria-activedescendant'?: string | undefined; 'aria-atomic'?: Booleanish | undefined; 'aria-autocomplete'?: \"none\" | \"list\" | \"inline\" | \"both\" | undefined; 'aria-busy'?: Booleanish | undefined; 'aria-checked'?: boolean | \"mixed\" | \"false\" | \"true\" | undefined; 'aria-colcount'?: number | undefined; 'aria-colindex'?: number | undefined; 'aria-colspan'?: number | undefined; 'aria-controls'?: string | undefined; 'aria-current'?: boolean | \"date\" | \"location\" | \"time\" | \"page\" | \"false\" | \"true\" | \"step\" | undefined; 'aria-describedby'?: string | undefined; 'aria-details'?: string | undefined; 'aria-disabled'?: Booleanish | undefined; 'aria-dropeffect'?: \"none\" | \"copy\" | \"link\" | \"execute\" | \"move\" | \"popup\" | undefined; 'aria-errormessage'?: string | undefined; 'aria-expanded'?: Booleanish | undefined; 'aria-flowto'?: string | undefined; 'aria-grabbed'?: Booleanish | undefined; 'aria-haspopup'?: boolean | \"grid\" | \"menu\" | \"false\" | \"true\" | \"dialog\" | \"listbox\" | \"tree\" | undefined; 'aria-hidden'?: Booleanish | undefined; 'aria-invalid'?: boolean | \"false\" | \"true\" | \"grammar\" | \"spelling\" | undefined; 'aria-keyshortcuts'?: string | undefined; 'aria-label'?: string | undefined; 'aria-labelledby'?: string | undefined; 'aria-level'?: number | undefined; 'aria-live'?: \"off\" | \"assertive\" | \"polite\" | undefined; 'aria-modal'?: Booleanish | undefined; 'aria-multiline'?: Booleanish | undefined; 'aria-multiselectable'?: Booleanish | undefined; 'aria-orientation'?: \"horizontal\" | \"vertical\" | undefined; 'aria-owns'?: string | undefined; 'aria-placeholder'?: string | undefined; 'aria-posinset'?: number | undefined; 'aria-pressed'?: boolean | \"mixed\" | \"false\" | \"true\" | undefined; 'aria-readonly'?: Booleanish | undefined; 'aria-relevant'?: \"all\" | \"text\" | \"additions\" | \"additions removals\" | \"additions text\" | \"removals\" | \"removals additions\" | \"removals text\" | \"text additions\" | \"text removals\" | undefined; 'aria-required'?: Booleanish | undefined; 'aria-roledescription'?: string | undefined; 'aria-rowcount'?: number | undefined; 'aria-rowindex'?: number | undefined; 'aria-rowspan'?: number | undefined; 'aria-selected'?: Booleanish | undefined; 'aria-setsize'?: number | undefined; 'aria-sort'?: \"none\" | \"other\" | \"ascending\" | \"descending\" | undefined; 'aria-valuemax'?: number | undefined; 'aria-valuemin'?: number | undefined; 'aria-valuenow'?: number | undefined; 'aria-valuetext'?: string | undefined; dangerouslySetInnerHTML?: { __html: string; } | undefined; onCopy?: React.ClipboardEventHandler | undefined; onCopyCapture?: React.ClipboardEventHandler | undefined; onCut?: React.ClipboardEventHandler | undefined; onCutCapture?: React.ClipboardEventHandler | undefined; onPaste?: React.ClipboardEventHandler | undefined; onPasteCapture?: React.ClipboardEventHandler | undefined; onCompositionEnd?: React.CompositionEventHandler | undefined; onCompositionEndCapture?: React.CompositionEventHandler | undefined; onCompositionStart?: React.CompositionEventHandler | undefined; onCompositionStartCapture?: React.CompositionEventHandler | undefined; onCompositionUpdate?: React.CompositionEventHandler | undefined; onCompositionUpdateCapture?: React.CompositionEventHandler | undefined; onFocus?: React.FocusEventHandler | undefined; onFocusCapture?: React.FocusEventHandler | undefined; onBlur?: React.FocusEventHandler | undefined; onBlurCapture?: React.FocusEventHandler | undefined; onChangeCapture?: React.FormEventHandler | undefined; onBeforeInput?: React.FormEventHandler | undefined; onBeforeInputCapture?: React.FormEventHandler | undefined; onInput?: React.FormEventHandler | undefined; onInputCapture?: React.FormEventHandler | undefined; onReset?: React.FormEventHandler | undefined; onResetCapture?: React.FormEventHandler | undefined; onSubmit?: React.FormEventHandler | undefined; onSubmitCapture?: React.FormEventHandler | undefined; onInvalid?: React.FormEventHandler | undefined; onInvalidCapture?: React.FormEventHandler | undefined; onLoad?: React.ReactEventHandler | undefined; onLoadCapture?: React.ReactEventHandler | undefined; onErrorCapture?: React.ReactEventHandler | undefined; onKeyDownCapture?: React.KeyboardEventHandler | undefined; onKeyPress?: React.KeyboardEventHandler | undefined; onKeyPressCapture?: React.KeyboardEventHandler | undefined; onKeyUp?: React.KeyboardEventHandler | undefined; onKeyUpCapture?: React.KeyboardEventHandler | undefined; onAbort?: React.ReactEventHandler | undefined; onAbortCapture?: React.ReactEventHandler | undefined; onCanPlay?: React.ReactEventHandler | undefined; onCanPlayCapture?: React.ReactEventHandler | undefined; onCanPlayThrough?: React.ReactEventHandler | undefined; onCanPlayThroughCapture?: React.ReactEventHandler | undefined; onDurationChange?: React.ReactEventHandler | undefined; onDurationChangeCapture?: React.ReactEventHandler | undefined; onEmptied?: React.ReactEventHandler | undefined; onEmptiedCapture?: React.ReactEventHandler | undefined; onEncrypted?: React.ReactEventHandler | undefined; onEncryptedCapture?: React.ReactEventHandler | undefined; onEnded?: React.ReactEventHandler | undefined; onEndedCapture?: React.ReactEventHandler | undefined; onLoadedData?: React.ReactEventHandler | undefined; onLoadedDataCapture?: React.ReactEventHandler | undefined; onLoadedMetadata?: React.ReactEventHandler | undefined; onLoadedMetadataCapture?: React.ReactEventHandler | undefined; onLoadStart?: React.ReactEventHandler | undefined; onLoadStartCapture?: React.ReactEventHandler | undefined; onPause?: React.ReactEventHandler | undefined; onPauseCapture?: React.ReactEventHandler | undefined; onPlay?: React.ReactEventHandler | undefined; onPlayCapture?: React.ReactEventHandler | undefined; onPlaying?: React.ReactEventHandler | undefined; onPlayingCapture?: React.ReactEventHandler | undefined; onProgress?: React.ReactEventHandler | undefined; onProgressCapture?: React.ReactEventHandler | undefined; onRateChange?: React.ReactEventHandler | undefined; onRateChangeCapture?: React.ReactEventHandler | undefined; onSeeked?: React.ReactEventHandler | undefined; onSeekedCapture?: React.ReactEventHandler | undefined; onSeeking?: React.ReactEventHandler | undefined; onSeekingCapture?: React.ReactEventHandler | undefined; onStalled?: React.ReactEventHandler | undefined; onStalledCapture?: React.ReactEventHandler | undefined; onSuspend?: React.ReactEventHandler | undefined; onSuspendCapture?: React.ReactEventHandler | undefined; onTimeUpdate?: React.ReactEventHandler | undefined; onTimeUpdateCapture?: React.ReactEventHandler | undefined; onVolumeChange?: React.ReactEventHandler | undefined; onVolumeChangeCapture?: React.ReactEventHandler | undefined; onWaiting?: React.ReactEventHandler | undefined; onWaitingCapture?: React.ReactEventHandler | undefined; onAuxClick?: React.MouseEventHandler | undefined; onAuxClickCapture?: React.MouseEventHandler | undefined; onClickCapture?: React.MouseEventHandler | undefined; onContextMenu?: React.MouseEventHandler | undefined; onContextMenuCapture?: React.MouseEventHandler | undefined; onDoubleClick?: React.MouseEventHandler | undefined; onDoubleClickCapture?: React.MouseEventHandler | undefined; onDrag?: React.DragEventHandler | undefined; onDragCapture?: React.DragEventHandler | undefined; onDragEnd?: React.DragEventHandler | undefined; onDragEndCapture?: React.DragEventHandler | undefined; onDragEnter?: React.DragEventHandler | undefined; onDragEnterCapture?: React.DragEventHandler | undefined; onDragExit?: React.DragEventHandler | undefined; onDragExitCapture?: React.DragEventHandler | undefined; onDragLeave?: React.DragEventHandler | undefined; onDragLeaveCapture?: React.DragEventHandler | undefined; onDragOver?: React.DragEventHandler | undefined; onDragOverCapture?: React.DragEventHandler | undefined; onDragStart?: React.DragEventHandler | undefined; onDragStartCapture?: React.DragEventHandler | undefined; onDrop?: React.DragEventHandler | undefined; onDropCapture?: React.DragEventHandler | undefined; onMouseDown?: React.MouseEventHandler | undefined; onMouseDownCapture?: React.MouseEventHandler | undefined; onMouseEnter?: React.MouseEventHandler | undefined; onMouseLeave?: React.MouseEventHandler | undefined; onMouseMove?: React.MouseEventHandler | undefined; onMouseMoveCapture?: React.MouseEventHandler | undefined; onMouseOut?: React.MouseEventHandler | undefined; onMouseOutCapture?: React.MouseEventHandler | undefined; onMouseOver?: React.MouseEventHandler | undefined; onMouseOverCapture?: React.MouseEventHandler | undefined; onMouseUp?: React.MouseEventHandler | undefined; onMouseUpCapture?: React.MouseEventHandler | undefined; onSelect?: React.ReactEventHandler | undefined; onSelectCapture?: React.ReactEventHandler | undefined; onTouchCancel?: React.TouchEventHandler | undefined; onTouchCancelCapture?: React.TouchEventHandler | undefined; onTouchEnd?: React.TouchEventHandler | undefined; onTouchEndCapture?: React.TouchEventHandler | undefined; onTouchMove?: React.TouchEventHandler | undefined; onTouchMoveCapture?: React.TouchEventHandler | undefined; onTouchStart?: React.TouchEventHandler | undefined; onTouchStartCapture?: React.TouchEventHandler | undefined; onPointerDown?: React.PointerEventHandler | undefined; onPointerDownCapture?: React.PointerEventHandler | undefined; onPointerMove?: React.PointerEventHandler | undefined; onPointerMoveCapture?: React.PointerEventHandler | undefined; onPointerUp?: React.PointerEventHandler | undefined; onPointerUpCapture?: React.PointerEventHandler | undefined; onPointerCancel?: React.PointerEventHandler | undefined; onPointerCancelCapture?: React.PointerEventHandler | undefined; onPointerEnter?: React.PointerEventHandler | undefined; onPointerEnterCapture?: React.PointerEventHandler | undefined; onPointerLeave?: React.PointerEventHandler | undefined; onPointerLeaveCapture?: React.PointerEventHandler | undefined; onPointerOver?: React.PointerEventHandler | undefined; onPointerOverCapture?: React.PointerEventHandler | undefined; onPointerOut?: React.PointerEventHandler | undefined; onPointerOutCapture?: React.PointerEventHandler | undefined; onGotPointerCapture?: React.PointerEventHandler | undefined; onGotPointerCaptureCapture?: React.PointerEventHandler | undefined; onLostPointerCapture?: React.PointerEventHandler | undefined; onLostPointerCaptureCapture?: React.PointerEventHandler | undefined; onScroll?: React.UIEventHandler | undefined; onScrollCapture?: React.UIEventHandler | undefined; onWheel?: React.WheelEventHandler | undefined; onWheelCapture?: React.WheelEventHandler | undefined; onAnimationStart?: React.AnimationEventHandler | undefined; onAnimationStartCapture?: React.AnimationEventHandler | undefined; onAnimationEnd?: React.AnimationEventHandler | undefined; onAnimationEndCapture?: React.AnimationEventHandler | undefined; onAnimationIteration?: React.AnimationEventHandler | undefined; onAnimationIterationCapture?: React.AnimationEventHandler | undefined; onTransitionEnd?: React.TransitionEventHandler | undefined; onTransitionEndCapture?: React.TransitionEventHandler | undefined; 'data-test-subj'?: string | undefined; css?: ", "Interpolation", "<", "Theme", - ">; height?: string | number | undefined; readOnly?: boolean | undefined; align?: ", + ">; height?: string | number | undefined; width?: string | undefined; readOnly?: boolean | undefined; align?: ", "HorizontalAlignment", " | undefined; abbr?: string | undefined; footer?: string | React.ReactElement> | ((props: ", "EuiTableFooterProps", diff --git a/api_docs/saved_objects_management.mdx b/api_docs/saved_objects_management.mdx index 35685af811fda..6f2a973f3465c 100644 --- a/api_docs/saved_objects_management.mdx +++ b/api_docs/saved_objects_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsManagement title: "savedObjectsManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsManagement plugin -date: 2022-11-29 +date: 2022-12-06 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 cd73a126d89e4..28366f90e3a50 100644 --- a/api_docs/saved_objects_tagging.mdx +++ b/api_docs/saved_objects_tagging.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsTagging title: "savedObjectsTagging" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsTagging plugin -date: 2022-11-29 +date: 2022-12-06 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 0c1f90beaae99..b0e43505cb269 100644 --- a/api_docs/saved_objects_tagging_oss.mdx +++ b/api_docs/saved_objects_tagging_oss.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsTaggingOss title: "savedObjectsTaggingOss" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsTaggingOss plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsTaggingOss'] --- import savedObjectsTaggingOssObj from './saved_objects_tagging_oss.devdocs.json'; diff --git a/api_docs/saved_search.devdocs.json b/api_docs/saved_search.devdocs.json index 8b7345d50d881..ba9542747b9ab 100644 --- a/api_docs/saved_search.devdocs.json +++ b/api_docs/saved_search.devdocs.json @@ -819,6 +819,20 @@ "path": "src/plugins/saved_search/public/services/saved_searches/types.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "savedSearch", + "id": "def-public.SavedSearch.breakdownField", + "type": "string", + "tags": [], + "label": "breakdownField", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "src/plugins/saved_search/public/services/saved_searches/types.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false diff --git a/api_docs/saved_search.mdx b/api_docs/saved_search.mdx index 631442e3db809..61864a66a5a26 100644 --- a/api_docs/saved_search.mdx +++ b/api_docs/saved_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedSearch title: "savedSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the savedSearch plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedSearch'] --- import savedSearchObj from './saved_search.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Data Discovery](https://github.com/orgs/elastic/teams/kibana-data-disco | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 44 | 0 | 44 | 1 | +| 45 | 0 | 45 | 1 | ## Client diff --git a/api_docs/screenshot_mode.mdx b/api_docs/screenshot_mode.mdx index 81960e7cf92cf..fda614bc83a44 100644 --- a/api_docs/screenshot_mode.mdx +++ b/api_docs/screenshot_mode.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/screenshotMode title: "screenshotMode" image: https://source.unsplash.com/400x175/?github description: API docs for the screenshotMode plugin -date: 2022-11-29 +date: 2022-12-06 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 eee0d688596a1..f9cc541b394da 100644 --- a/api_docs/screenshotting.mdx +++ b/api_docs/screenshotting.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/screenshotting title: "screenshotting" image: https://source.unsplash.com/400x175/?github description: API docs for the screenshotting plugin -date: 2022-11-29 +date: 2022-12-06 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 73a7bf61b2509..3d4fc14cd9a44 100644 --- a/api_docs/security.mdx +++ b/api_docs/security.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/security title: "security" image: https://source.unsplash.com/400x175/?github description: API docs for the security plugin -date: 2022-11-29 +date: 2022-12-06 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 519589842552b..1b7004b155d1d 100644 --- a/api_docs/security_solution.devdocs.json +++ b/api_docs/security_solution.devdocs.json @@ -64,7 +64,7 @@ "label": "experimentalFeatures", "description": [], "signature": [ - "{ readonly tGridEnabled: boolean; readonly tGridEventRenderedViewEnabled: boolean; readonly excludePoliciesInFilterEnabled: boolean; readonly kubernetesEnabled: boolean; readonly disableIsolationUIPendingStatuses: boolean; readonly pendingActionResponsesWithAck: boolean; readonly policyListEnabled: boolean; readonly policyResponseInFleetEnabled: boolean; readonly chartEmbeddablesEnabled: boolean; readonly previewTelemetryUrlEnabled: boolean; readonly responseActionsConsoleEnabled: boolean; readonly insightsRelatedAlertsByProcessAncestry: boolean; readonly extendedRuleExecutionLoggingEnabled: boolean; readonly socTrendsEnabled: boolean; readonly responseActionsEnabled: boolean; readonly endpointRbacEnabled: boolean; readonly endpointRbacV1Enabled: boolean; readonly alertDetailsPageEnabled: boolean; readonly responseActionGetFileEnabled: boolean; }" + "{ readonly tGridEnabled: boolean; readonly tGridEventRenderedViewEnabled: boolean; readonly excludePoliciesInFilterEnabled: boolean; readonly kubernetesEnabled: boolean; readonly disableIsolationUIPendingStatuses: boolean; readonly pendingActionResponsesWithAck: boolean; readonly policyListEnabled: boolean; readonly policyResponseInFleetEnabled: boolean; readonly chartEmbeddablesEnabled: boolean; readonly previewTelemetryUrlEnabled: boolean; readonly responseActionsConsoleEnabled: boolean; readonly insightsRelatedAlertsByProcessAncestry: boolean; readonly extendedRuleExecutionLoggingEnabled: boolean; readonly socTrendsEnabled: boolean; readonly responseActionsEnabled: boolean; readonly endpointRbacEnabled: boolean; readonly endpointRbacV1Enabled: boolean; readonly alertDetailsPageEnabled: boolean; readonly responseActionGetFileEnabled: boolean; readonly riskyHostsEnabled: boolean; readonly riskyUsersEnabled: boolean; }" ], "path": "x-pack/plugins/security_solution/public/plugin.tsx", "deprecated": false, @@ -2008,7 +2008,7 @@ "label": "ConfigType", "description": [], "signature": [ - "Readonly<{} & { signalsIndex: string; maxRuleImportExportSize: number; maxRuleImportPayloadBytes: number; maxTimelineImportExportSize: number; maxTimelineImportPayloadBytes: number; alertMergeStrategy: \"allFields\" | \"missingFields\" | \"noFields\"; alertIgnoreFields: string[]; enableExperimental: string[]; packagerTaskInterval: string; prebuiltRulesFromFileSystem: boolean; prebuiltRulesFromSavedObjects: boolean; }> & { experimentalFeatures: Readonly<{ tGridEnabled: boolean; tGridEventRenderedViewEnabled: boolean; excludePoliciesInFilterEnabled: boolean; kubernetesEnabled: boolean; disableIsolationUIPendingStatuses: boolean; pendingActionResponsesWithAck: boolean; policyListEnabled: boolean; policyResponseInFleetEnabled: boolean; chartEmbeddablesEnabled: boolean; previewTelemetryUrlEnabled: boolean; responseActionsConsoleEnabled: boolean; insightsRelatedAlertsByProcessAncestry: boolean; extendedRuleExecutionLoggingEnabled: boolean; socTrendsEnabled: boolean; responseActionsEnabled: boolean; endpointRbacEnabled: boolean; endpointRbacV1Enabled: boolean; alertDetailsPageEnabled: boolean; responseActionGetFileEnabled: boolean; }>; }" + "Readonly<{} & { signalsIndex: string; maxRuleImportExportSize: number; maxRuleImportPayloadBytes: number; maxTimelineImportExportSize: number; maxTimelineImportPayloadBytes: number; alertMergeStrategy: \"allFields\" | \"missingFields\" | \"noFields\"; alertIgnoreFields: string[]; enableExperimental: string[]; packagerTaskInterval: string; prebuiltRulesFromFileSystem: boolean; prebuiltRulesFromSavedObjects: boolean; }> & { experimentalFeatures: Readonly<{ tGridEnabled: boolean; tGridEventRenderedViewEnabled: boolean; excludePoliciesInFilterEnabled: boolean; kubernetesEnabled: boolean; disableIsolationUIPendingStatuses: boolean; pendingActionResponsesWithAck: boolean; policyListEnabled: boolean; policyResponseInFleetEnabled: boolean; chartEmbeddablesEnabled: boolean; previewTelemetryUrlEnabled: boolean; responseActionsConsoleEnabled: boolean; insightsRelatedAlertsByProcessAncestry: boolean; extendedRuleExecutionLoggingEnabled: boolean; socTrendsEnabled: boolean; responseActionsEnabled: boolean; endpointRbacEnabled: boolean; endpointRbacV1Enabled: boolean; alertDetailsPageEnabled: boolean; responseActionGetFileEnabled: boolean; riskyHostsEnabled: boolean; riskyUsersEnabled: boolean; }>; }" ], "path": "x-pack/plugins/security_solution/server/config.ts", "deprecated": false, diff --git a/api_docs/security_solution.mdx b/api_docs/security_solution.mdx index fb525ed645566..b01233eb7b862 100644 --- a/api_docs/security_solution.mdx +++ b/api_docs/security_solution.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/securitySolution title: "securitySolution" image: https://source.unsplash.com/400x175/?github description: API docs for the securitySolution plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'securitySolution'] --- import securitySolutionObj from './security_solution.devdocs.json'; diff --git a/api_docs/session_view.mdx b/api_docs/session_view.mdx index 8315b96b4c61c..a6ec7b973cd73 100644 --- a/api_docs/session_view.mdx +++ b/api_docs/session_view.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/sessionView title: "sessionView" image: https://source.unsplash.com/400x175/?github description: API docs for the sessionView plugin -date: 2022-11-29 +date: 2022-12-06 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 f94528841588d..469b39680ac01 100644 --- a/api_docs/share.mdx +++ b/api_docs/share.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/share title: "share" image: https://source.unsplash.com/400x175/?github description: API docs for the share plugin -date: 2022-11-29 +date: 2022-12-06 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 e1777690bd5a0..4f774c08218d7 100644 --- a/api_docs/snapshot_restore.mdx +++ b/api_docs/snapshot_restore.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/snapshotRestore title: "snapshotRestore" image: https://source.unsplash.com/400x175/?github description: API docs for the snapshotRestore plugin -date: 2022-11-29 +date: 2022-12-06 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 77e12276279cb..1697ab8495843 100644 --- a/api_docs/spaces.mdx +++ b/api_docs/spaces.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/spaces title: "spaces" image: https://source.unsplash.com/400x175/?github description: API docs for the spaces plugin -date: 2022-11-29 +date: 2022-12-06 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 65a000b6be96e..77172023a15c2 100644 --- a/api_docs/stack_alerts.mdx +++ b/api_docs/stack_alerts.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/stackAlerts title: "stackAlerts" image: https://source.unsplash.com/400x175/?github description: API docs for the stackAlerts plugin -date: 2022-11-29 +date: 2022-12-06 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 d05297fc1ff3b..3a492d7473f39 100644 --- a/api_docs/stack_connectors.mdx +++ b/api_docs/stack_connectors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/stackConnectors title: "stackConnectors" image: https://source.unsplash.com/400x175/?github description: API docs for the stackConnectors plugin -date: 2022-11-29 +date: 2022-12-06 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 bf22216975436..b1c3e3324973d 100644 --- a/api_docs/task_manager.mdx +++ b/api_docs/task_manager.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/taskManager title: "taskManager" image: https://source.unsplash.com/400x175/?github description: API docs for the taskManager plugin -date: 2022-11-29 +date: 2022-12-06 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 ec21bd6362af1..0a25aa3877b44 100644 --- a/api_docs/telemetry.mdx +++ b/api_docs/telemetry.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetry title: "telemetry" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetry plugin -date: 2022-11-29 +date: 2022-12-06 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 b08f8dc9555ad..9898ba4ec976f 100644 --- a/api_docs/telemetry_collection_manager.mdx +++ b/api_docs/telemetry_collection_manager.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetryCollectionManager title: "telemetryCollectionManager" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetryCollectionManager plugin -date: 2022-11-29 +date: 2022-12-06 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 990e579ed2487..cacc0a540af38 100644 --- a/api_docs/telemetry_collection_xpack.mdx +++ b/api_docs/telemetry_collection_xpack.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetryCollectionXpack title: "telemetryCollectionXpack" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetryCollectionXpack plugin -date: 2022-11-29 +date: 2022-12-06 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 b62e059d549ae..31fb7d6dc7a9e 100644 --- a/api_docs/telemetry_management_section.mdx +++ b/api_docs/telemetry_management_section.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetryManagementSection title: "telemetryManagementSection" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetryManagementSection plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryManagementSection'] --- import telemetryManagementSectionObj from './telemetry_management_section.devdocs.json'; diff --git a/api_docs/threat_intelligence.devdocs.json b/api_docs/threat_intelligence.devdocs.json index 537c8c1268807..bf7f44448dd5f 100644 --- a/api_docs/threat_intelligence.devdocs.json +++ b/api_docs/threat_intelligence.devdocs.json @@ -222,10 +222,10 @@ }, { "parentPluginId": "threatIntelligence", - "id": "def-public.SecuritySolutionPluginContext.getSecuritySolutionStore", + "id": "def-public.SecuritySolutionPluginContext.securitySolutionStore", "type": "Object", "tags": [], - "label": "getSecuritySolutionStore", + "label": "securitySolutionStore", "description": [ "\nSecurity Solution store" ], @@ -389,6 +389,119 @@ "trackAdoption": false } ] + }, + { + "parentPluginId": "threatIntelligence", + "id": "def-public.SecuritySolutionPluginContext.registerQuery", + "type": "Function", + "tags": [], + "label": "registerQuery", + "description": [ + "\nRegister query in security solution store for tracking and centralized refresh support" + ], + "signature": [ + "(query: { id: string; loading: boolean; refetch: VoidFunction; }) => void" + ], + "path": "x-pack/plugins/threat_intelligence/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "threatIntelligence", + "id": "def-public.SecuritySolutionPluginContext.registerQuery.$1", + "type": "Object", + "tags": [], + "label": "query", + "description": [], + "path": "x-pack/plugins/threat_intelligence/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "threatIntelligence", + "id": "def-public.SecuritySolutionPluginContext.registerQuery.$1.id", + "type": "string", + "tags": [], + "label": "id", + "description": [], + "path": "x-pack/plugins/threat_intelligence/public/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "threatIntelligence", + "id": "def-public.SecuritySolutionPluginContext.registerQuery.$1.loading", + "type": "boolean", + "tags": [], + "label": "loading", + "description": [], + "path": "x-pack/plugins/threat_intelligence/public/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "threatIntelligence", + "id": "def-public.SecuritySolutionPluginContext.registerQuery.$1.refetch", + "type": "Function", + "tags": [], + "label": "refetch", + "description": [], + "signature": [ + "VoidFunction" + ], + "path": "x-pack/plugins/threat_intelligence/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [] + } + ] + } + ], + "returnComment": [] + }, + { + "parentPluginId": "threatIntelligence", + "id": "def-public.SecuritySolutionPluginContext.deregisterQuery", + "type": "Function", + "tags": [], + "label": "deregisterQuery", + "description": [ + "\nDeregister stale query" + ], + "signature": [ + "(query: { id: string; }) => void" + ], + "path": "x-pack/plugins/threat_intelligence/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "threatIntelligence", + "id": "def-public.SecuritySolutionPluginContext.deregisterQuery.$1", + "type": "Object", + "tags": [], + "label": "query", + "description": [], + "path": "x-pack/plugins/threat_intelligence/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "threatIntelligence", + "id": "def-public.SecuritySolutionPluginContext.deregisterQuery.$1.id", + "type": "string", + "tags": [], + "label": "id", + "description": [], + "path": "x-pack/plugins/threat_intelligence/public/types.ts", + "deprecated": false, + "trackAdoption": false + } + ] + } + ], + "returnComment": [] } ], "initialIsOpen": false diff --git a/api_docs/threat_intelligence.mdx b/api_docs/threat_intelligence.mdx index 366d0a62cb80d..0e3075a724a1e 100644 --- a/api_docs/threat_intelligence.mdx +++ b/api_docs/threat_intelligence.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/threatIntelligence title: "threatIntelligence" image: https://source.unsplash.com/400x175/?github description: API docs for the threatIntelligence plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'threatIntelligence'] --- import threatIntelligenceObj from './threat_intelligence.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Protections Experience Team](https://github.com/orgs/elastic/teams/prot | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 26 | 0 | 8 | 3 | +| 34 | 0 | 14 | 3 | ## Client diff --git a/api_docs/timelines.devdocs.json b/api_docs/timelines.devdocs.json index 8b99cb421526f..b6d49bf07cf6d 100644 --- a/api_docs/timelines.devdocs.json +++ b/api_docs/timelines.devdocs.json @@ -7325,7 +7325,7 @@ "section": "def-common.RowRenderer", "text": "RowRenderer" }, - "[] | undefined; setFlyoutAlert?: ((data: any) => void) | undefined; scopeId: string; truncate?: boolean | undefined; key?: string | undefined; closeCellPopover?: (() => void) | undefined; }" + "[] | undefined; setFlyoutAlert?: ((data: any) => void) | undefined; scopeId: string; truncate?: boolean | undefined; key?: string | undefined; closeCellPopover?: (() => void) | undefined; enableActions?: boolean | undefined; }" ], "path": "x-pack/plugins/timelines/common/types/timeline/cells/index.ts", "deprecated": false, diff --git a/api_docs/timelines.mdx b/api_docs/timelines.mdx index 4305ffc074574..804656a3d20f1 100644 --- a/api_docs/timelines.mdx +++ b/api_docs/timelines.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/timelines title: "timelines" image: https://source.unsplash.com/400x175/?github description: API docs for the timelines plugin -date: 2022-11-29 +date: 2022-12-06 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 2e03deaf490d5..27fc618bceffe 100644 --- a/api_docs/transform.mdx +++ b/api_docs/transform.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/transform title: "transform" image: https://source.unsplash.com/400x175/?github description: API docs for the transform plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'transform'] --- import transformObj from './transform.devdocs.json'; diff --git a/api_docs/triggers_actions_ui.devdocs.json b/api_docs/triggers_actions_ui.devdocs.json index 4a808e78a85a8..401d2fbb4aaa7 100644 --- a/api_docs/triggers_actions_ui.devdocs.json +++ b/api_docs/triggers_actions_ui.devdocs.json @@ -5396,6 +5396,20 @@ "path": "x-pack/plugins/triggers_actions_ui/public/types.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "triggersActionsUi", + "id": "def-public.RuleTypeModel.alertDetailsAppSection", + "type": "CompoundType", + "tags": [], + "label": "alertDetailsAppSection", + "description": [], + "signature": [ + "React.FunctionComponent | React.LazyExoticComponent> | undefined" + ], + "path": "x-pack/plugins/triggers_actions_ui/public/types.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false diff --git a/api_docs/triggers_actions_ui.mdx b/api_docs/triggers_actions_ui.mdx index 79125f066c25e..69ddb5c1093bf 100644 --- a/api_docs/triggers_actions_ui.mdx +++ b/api_docs/triggers_actions_ui.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/triggersActionsUi title: "triggersActionsUi" image: https://source.unsplash.com/400x175/?github description: API docs for the triggersActionsUi plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'triggersActionsUi'] --- import triggersActionsUiObj from './triggers_actions_ui.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Response Ops](https://github.com/orgs/elastic/teams/response-ops) for q | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 531 | 11 | 502 | 51 | +| 532 | 11 | 503 | 51 | ## Client diff --git a/api_docs/ui_actions.mdx b/api_docs/ui_actions.mdx index 07501695fdeaa..5fa67581c820d 100644 --- a/api_docs/ui_actions.mdx +++ b/api_docs/ui_actions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/uiActions title: "uiActions" image: https://source.unsplash.com/400x175/?github description: API docs for the uiActions plugin -date: 2022-11-29 +date: 2022-12-06 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 a1cf77e7a98cf..a80c3ff9fb9df 100644 --- a/api_docs/ui_actions_enhanced.mdx +++ b/api_docs/ui_actions_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/uiActionsEnhanced title: "uiActionsEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the uiActionsEnhanced plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'uiActionsEnhanced'] --- import uiActionsEnhancedObj from './ui_actions_enhanced.devdocs.json'; diff --git a/api_docs/unified_field_list.devdocs.json b/api_docs/unified_field_list.devdocs.json index 116fac3c5a0a5..60a10d66079c0 100644 --- a/api_docs/unified_field_list.devdocs.json +++ b/api_docs/unified_field_list.devdocs.json @@ -530,6 +530,79 @@ "returnComment": [], "initialIsOpen": false }, + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.hasQuerySubscriberData", + "type": "Function", + "tags": [], + "label": "hasQuerySubscriberData", + "description": [ + "\nChecks if query result is ready to be used" + ], + "signature": [ + "(result: ", + { + "pluginId": "unifiedFieldList", + "scope": "public", + "docId": "kibUnifiedFieldListPluginApi", + "section": "def-public.QuerySubscriberResult", + "text": "QuerySubscriberResult" + }, + ") => result is { query: ", + { + "pluginId": "@kbn/es-query", + "scope": "common", + "docId": "kibKbnEsQueryPluginApi", + "section": "def-common.Query", + "text": "Query" + }, + " | ", + { + "pluginId": "@kbn/es-query", + "scope": "common", + "docId": "kibKbnEsQueryPluginApi", + "section": "def-common.AggregateQuery", + "text": "AggregateQuery" + }, + "; filters: ", + { + "pluginId": "@kbn/es-query", + "scope": "common", + "docId": "kibKbnEsQueryPluginApi", + "section": "def-common.Filter", + "text": "Filter" + }, + "[]; fromDate: string; toDate: string; }" + ], + "path": "src/plugins/unified_field_list/public/hooks/use_query_subscriber.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.hasQuerySubscriberData.$1", + "type": "Object", + "tags": [], + "label": "result", + "description": [], + "signature": [ + { + "pluginId": "unifiedFieldList", + "scope": "public", + "docId": "kibUnifiedFieldListPluginApi", + "section": "def-public.QuerySubscriberResult", + "text": "QuerySubscriberResult" + } + ], + "path": "src/plugins/unified_field_list/public/hooks/use_query_subscriber.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, { "parentPluginId": "unifiedFieldList", "id": "def-public.loadFieldExisting", @@ -975,7 +1048,7 @@ "label": "useGroupedFields", "description": [], "signature": [ - "({\n dataViewId,\n allFields,\n services,\n fieldsExistenceReader,\n onOverrideFieldGroupDetails,\n onSupportedFieldFilter,\n onSelectedFieldFilter,\n onFilterField,\n}: ", + "({\n dataViewId,\n allFields,\n services,\n fieldsExistenceReader,\n isAffectedByGlobalFilter = false,\n popularFieldsLimit,\n sortedSelectedFields,\n onOverrideFieldGroupDetails,\n onSupportedFieldFilter,\n onSelectedFieldFilter,\n onFilterField,\n}: ", { "pluginId": "unifiedFieldList", "scope": "public", @@ -1002,7 +1075,7 @@ "id": "def-public.useGroupedFields.$1", "type": "Object", "tags": [], - "label": "{\n dataViewId,\n allFields,\n services,\n fieldsExistenceReader,\n onOverrideFieldGroupDetails,\n onSupportedFieldFilter,\n onSelectedFieldFilter,\n onFilterField,\n}", + "label": "{\n dataViewId,\n allFields,\n services,\n fieldsExistenceReader,\n isAffectedByGlobalFilter = false,\n popularFieldsLimit,\n sortedSelectedFields,\n onOverrideFieldGroupDetails,\n onSupportedFieldFilter,\n onSelectedFieldFilter,\n onFilterField,\n}", "description": [], "signature": [ { @@ -1030,7 +1103,7 @@ "tags": [], "label": "useQuerySubscriber", "description": [ - "\nMemorizes current query and filters" + "\nMemorizes current query, filters and absolute date range" ], "signature": [ "({ data }: ", @@ -1181,6 +1254,20 @@ "deprecated": false, "trackAdoption": false, "children": [ + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.ExistingFieldsFetcherParams.disableAutoFetching", + "type": "CompoundType", + "tags": [], + "label": "disableAutoFetching", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "src/plugins/unified_field_list/public/hooks/use_existing_fields.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "unifiedFieldList", "id": "def-public.ExistingFieldsFetcherParams.dataViews", @@ -1209,6 +1296,9 @@ "tags": [], "label": "fromDate", "description": [], + "signature": [ + "string | undefined" + ], "path": "src/plugins/unified_field_list/public/hooks/use_existing_fields.ts", "deprecated": false, "trackAdoption": false @@ -1220,6 +1310,9 @@ "tags": [], "label": "toDate", "description": [], + "signature": [ + "string | undefined" + ], "path": "src/plugins/unified_field_list/public/hooks/use_existing_fields.ts", "deprecated": false, "trackAdoption": false @@ -1246,7 +1339,8 @@ "docId": "kibKbnEsQueryPluginApi", "section": "def-common.AggregateQuery", "text": "AggregateQuery" - } + }, + " | undefined" ], "path": "src/plugins/unified_field_list/public/hooks/use_existing_fields.ts", "deprecated": false, @@ -1267,7 +1361,7 @@ "section": "def-common.Filter", "text": "Filter" }, - "[]" + "[] | undefined" ], "path": "src/plugins/unified_field_list/public/hooks/use_existing_fields.ts", "deprecated": false, @@ -1584,12 +1678,16 @@ "FieldsGroup", " | undefined; SelectedFields?: ", "FieldsGroup", + " | undefined; PopularFields?: ", + "FieldsGroup", " | undefined; AvailableFields?: ", "FieldsGroup", " | undefined; EmptyFields?: ", "FieldsGroup", " | undefined; MetaFields?: ", "FieldsGroup", + " | undefined; UnmappedFields?: ", + "FieldsGroup", " | undefined; }" ], "path": "src/plugins/unified_field_list/public/components/field_list/field_list_grouped.tsx", @@ -1635,7 +1733,15 @@ "label": "renderFieldItem", "description": [], "signature": [ - "(params: { field: T; hideDetails?: boolean | undefined; itemIndex: number; groupIndex: number; }) => JSX.Element" + "(params: { field: T; hideDetails?: boolean | undefined; itemIndex: number; groupIndex: number; groupName: ", + { + "pluginId": "unifiedFieldList", + "scope": "public", + "docId": "kibUnifiedFieldListPluginApi", + "section": "def-public.FieldsGroupNames", + "text": "FieldsGroupNames" + }, + "; }) => JSX.Element" ], "path": "src/plugins/unified_field_list/public/components/field_list/field_list_grouped.tsx", "deprecated": false, @@ -1650,7 +1756,15 @@ "label": "params", "description": [], "signature": [ - "{ field: T; hideDetails?: boolean | undefined; itemIndex: number; groupIndex: number; }" + "{ field: T; hideDetails?: boolean | undefined; itemIndex: number; groupIndex: number; groupName: ", + { + "pluginId": "unifiedFieldList", + "scope": "public", + "docId": "kibUnifiedFieldListPluginApi", + "section": "def-public.FieldsGroupNames", + "text": "FieldsGroupNames" + }, + "; }" ], "path": "src/plugins/unified_field_list/public/components/field_list/fields_accordion.tsx", "deprecated": false, @@ -1658,6 +1772,17 @@ } ] }, + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.FieldListGroupedProps.scrollToTopResetCounter", + "type": "number", + "tags": [], + "label": "scrollToTopResetCounter", + "description": [], + "path": "src/plugins/unified_field_list/public/components/field_list/field_list_grouped.tsx", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "unifiedFieldList", "id": "def-public.FieldListGroupedProps.screenReaderDescriptionForSearchInputId", @@ -2952,12 +3077,12 @@ { "parentPluginId": "unifiedFieldList", "id": "def-public.GroupedFieldsParams.allFields", - "type": "Array", + "type": "CompoundType", "tags": [], "label": "allFields", "description": [], "signature": [ - "T[]" + "T[] | null" ], "path": "src/plugins/unified_field_list/public/hooks/use_grouped_fields.ts", "deprecated": false, @@ -3006,6 +3131,48 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.GroupedFieldsParams.isAffectedByGlobalFilter", + "type": "CompoundType", + "tags": [], + "label": "isAffectedByGlobalFilter", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "src/plugins/unified_field_list/public/hooks/use_grouped_fields.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.GroupedFieldsParams.popularFieldsLimit", + "type": "number", + "tags": [], + "label": "popularFieldsLimit", + "description": [], + "signature": [ + "number | undefined" + ], + "path": "src/plugins/unified_field_list/public/hooks/use_grouped_fields.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.GroupedFieldsParams.sortedSelectedFields", + "type": "Array", + "tags": [], + "label": "sortedSelectedFields", + "description": [], + "signature": [ + "T[] | undefined" + ], + "path": "src/plugins/unified_field_list/public/hooks/use_grouped_fields.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "unifiedFieldList", "id": "def-public.GroupedFieldsParams.onOverrideFieldGroupDetails", @@ -3192,17 +3359,63 @@ "FieldsGroup", " | undefined; SelectedFields?: ", "FieldsGroup", + " | undefined; PopularFields?: ", + "FieldsGroup", " | undefined; AvailableFields?: ", "FieldsGroup", " | undefined; EmptyFields?: ", "FieldsGroup", " | undefined; MetaFields?: ", "FieldsGroup", + " | undefined; UnmappedFields?: ", + "FieldsGroup", " | undefined; }" ], "path": "src/plugins/unified_field_list/public/hooks/use_grouped_fields.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.GroupedFieldsResult.scrollToTopResetCounter", + "type": "number", + "tags": [], + "label": "scrollToTopResetCounter", + "description": [], + "path": "src/plugins/unified_field_list/public/hooks/use_grouped_fields.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.GroupedFieldsResult.fieldsExistenceStatus", + "type": "Enum", + "tags": [], + "label": "fieldsExistenceStatus", + "description": [], + "signature": [ + { + "pluginId": "unifiedFieldList", + "scope": "public", + "docId": "kibUnifiedFieldListPluginApi", + "section": "def-public.ExistenceFetchStatus", + "text": "ExistenceFetchStatus" + } + ], + "path": "src/plugins/unified_field_list/public/hooks/use_grouped_fields.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.GroupedFieldsResult.fieldsExistInIndex", + "type": "boolean", + "tags": [], + "label": "fieldsExistInIndex", + "description": [], + "path": "src/plugins/unified_field_list/public/hooks/use_grouped_fields.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false @@ -3360,6 +3573,34 @@ "path": "src/plugins/unified_field_list/public/hooks/use_query_subscriber.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.QuerySubscriberResult.fromDate", + "type": "string", + "tags": [], + "label": "fromDate", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "src/plugins/unified_field_list/public/hooks/use_query_subscriber.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "unifiedFieldList", + "id": "def-public.QuerySubscriberResult.toDate", + "type": "string", + "tags": [], + "label": "toDate", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "src/plugins/unified_field_list/public/hooks/use_query_subscriber.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false @@ -3567,12 +3808,16 @@ "FieldsGroup", " | undefined; SelectedFields?: ", "FieldsGroup", + " | undefined; PopularFields?: ", + "FieldsGroup", " | undefined; AvailableFields?: ", "FieldsGroup", " | undefined; EmptyFields?: ", "FieldsGroup", " | undefined; MetaFields?: ", "FieldsGroup", + " | undefined; UnmappedFields?: ", + "FieldsGroup", " | undefined; }" ], "path": "src/plugins/unified_field_list/public/types.ts", diff --git a/api_docs/unified_field_list.mdx b/api_docs/unified_field_list.mdx index 338709f15d5b3..6ed9dc3725a5a 100644 --- a/api_docs/unified_field_list.mdx +++ b/api_docs/unified_field_list.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedFieldList title: "unifiedFieldList" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedFieldList plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedFieldList'] --- import unifiedFieldListObj from './unified_field_list.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Data Discovery](https://github.com/orgs/elastic/teams/kibana-data-disco | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 203 | 0 | 192 | 7 | +| 215 | 0 | 203 | 7 | ## Client diff --git a/api_docs/unified_histogram.devdocs.json b/api_docs/unified_histogram.devdocs.json index 5ea1d379e5aea..7a881fb33eed3 100644 --- a/api_docs/unified_histogram.devdocs.json +++ b/api_docs/unified_histogram.devdocs.json @@ -3,253 +3,6 @@ "client": { "classes": [], "functions": [ - { - "parentPluginId": "unifiedHistogram", - "id": "def-public.buildChartData", - "type": "Function", - "tags": [], - "label": "buildChartData", - "description": [ - "\nConvert the response from the chart request into a format that can be used\nby the unified histogram chart. The returned object should be used to update\n{@link UnifiedHistogramChartContext.bucketInterval} and {@link UnifiedHistogramChartContext.data}." - ], - "signature": [ - "({ data, dataView, timeInterval, response, }: { data: ", - { - "pluginId": "data", - "scope": "public", - "docId": "kibDataPluginApi", - "section": "def-public.DataPublicPluginStart", - "text": "DataPublicPluginStart" - }, - "; dataView: ", - { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataView", - "text": "DataView" - }, - "; timeInterval?: string | undefined; response?: ", - "SearchResponse", - "> | undefined; }) => { bucketInterval?: undefined; chartData?: undefined; } | { bucketInterval: ", - { - "pluginId": "unifiedHistogram", - "scope": "public", - "docId": "kibUnifiedHistogramPluginApi", - "section": "def-public.UnifiedHistogramBucketInterval", - "text": "UnifiedHistogramBucketInterval" - }, - " | undefined; chartData: ", - { - "pluginId": "unifiedHistogram", - "scope": "public", - "docId": "kibUnifiedHistogramPluginApi", - "section": "def-public.UnifiedHistogramChartData", - "text": "UnifiedHistogramChartData" - }, - "; }" - ], - "path": "src/plugins/unified_histogram/public/chart/build_chart_data.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "unifiedHistogram", - "id": "def-public.buildChartData.$1", - "type": "Object", - "tags": [], - "label": "{\n data,\n dataView,\n timeInterval,\n response,\n}", - "description": [], - "path": "src/plugins/unified_histogram/public/chart/build_chart_data.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "unifiedHistogram", - "id": "def-public.buildChartData.$1.data", - "type": "Object", - "tags": [], - "label": "data", - "description": [], - "signature": [ - { - "pluginId": "data", - "scope": "public", - "docId": "kibDataPluginApi", - "section": "def-public.DataPublicPluginStart", - "text": "DataPublicPluginStart" - } - ], - "path": "src/plugins/unified_histogram/public/chart/build_chart_data.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "unifiedHistogram", - "id": "def-public.buildChartData.$1.dataView", - "type": "Object", - "tags": [], - "label": "dataView", - "description": [], - "signature": [ - { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataView", - "text": "DataView" - } - ], - "path": "src/plugins/unified_histogram/public/chart/build_chart_data.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "unifiedHistogram", - "id": "def-public.buildChartData.$1.timeInterval", - "type": "string", - "tags": [], - "label": "timeInterval", - "description": [], - "signature": [ - "string | undefined" - ], - "path": "src/plugins/unified_histogram/public/chart/build_chart_data.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "unifiedHistogram", - "id": "def-public.buildChartData.$1.response", - "type": "Object", - "tags": [], - "label": "response", - "description": [], - "signature": [ - "SearchResponse", - "> | undefined" - ], - "path": "src/plugins/unified_histogram/public/chart/build_chart_data.ts", - "deprecated": false, - "trackAdoption": false - } - ] - } - ], - "returnComment": [], - "initialIsOpen": false - }, - { - "parentPluginId": "unifiedHistogram", - "id": "def-public.getChartAggConfigs", - "type": "Function", - "tags": [], - "label": "getChartAggConfigs", - "description": [ - "\nHelper function to get the agg configs required for the unified histogram chart request" - ], - "signature": [ - "({\n dataView,\n timeInterval,\n data,\n}: { dataView: ", - { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataView", - "text": "DataView" - }, - "; timeInterval: string; data: ", - { - "pluginId": "data", - "scope": "public", - "docId": "kibDataPluginApi", - "section": "def-public.DataPublicPluginStart", - "text": "DataPublicPluginStart" - }, - "; }) => ", - { - "pluginId": "data", - "scope": "common", - "docId": "kibDataSearchPluginApi", - "section": "def-common.AggConfigs", - "text": "AggConfigs" - } - ], - "path": "src/plugins/unified_histogram/public/chart/get_chart_agg_configs.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "unifiedHistogram", - "id": "def-public.getChartAggConfigs.$1", - "type": "Object", - "tags": [], - "label": "{\n dataView,\n timeInterval,\n data,\n}", - "description": [], - "path": "src/plugins/unified_histogram/public/chart/get_chart_agg_configs.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "unifiedHistogram", - "id": "def-public.getChartAggConfigs.$1.dataView", - "type": "Object", - "tags": [], - "label": "dataView", - "description": [], - "signature": [ - { - "pluginId": "dataViews", - "scope": "common", - "docId": "kibDataViewsPluginApi", - "section": "def-common.DataView", - "text": "DataView" - } - ], - "path": "src/plugins/unified_histogram/public/chart/get_chart_agg_configs.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "unifiedHistogram", - "id": "def-public.getChartAggConfigs.$1.timeInterval", - "type": "string", - "tags": [], - "label": "timeInterval", - "description": [], - "path": "src/plugins/unified_histogram/public/chart/get_chart_agg_configs.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "unifiedHistogram", - "id": "def-public.getChartAggConfigs.$1.data", - "type": "Object", - "tags": [], - "label": "data", - "description": [], - "signature": [ - { - "pluginId": "data", - "scope": "public", - "docId": "kibDataPluginApi", - "section": "def-public.DataPublicPluginStart", - "text": "DataPublicPluginStart" - } - ], - "path": "src/plugins/unified_histogram/public/chart/get_chart_agg_configs.ts", - "deprecated": false, - "trackAdoption": false - } - ] - } - ], - "returnComment": [], - "initialIsOpen": false - }, { "parentPluginId": "unifiedHistogram", "id": "def-public.UnifiedHistogramLayout", @@ -296,12 +49,12 @@ "interfaces": [ { "parentPluginId": "unifiedHistogram", - "id": "def-public.UnifiedHistogramBucketInterval", + "id": "def-public.UnifiedHistogramBreakdownContext", "type": "Interface", "tags": [], - "label": "UnifiedHistogramBucketInterval", + "label": "UnifiedHistogramBreakdownContext", "description": [ - "\nThe bucketInterval object returned by {@link buildChartData} that\nshould be used to set {@link UnifiedHistogramChartContext.bucketInterval}" + "\nContext object for the histogram breakdown" ], "path": "src/plugins/unified_histogram/public/types.ts", "deprecated": false, @@ -309,41 +62,22 @@ "children": [ { "parentPluginId": "unifiedHistogram", - "id": "def-public.UnifiedHistogramBucketInterval.scaled", - "type": "CompoundType", - "tags": [], - "label": "scaled", - "description": [], - "signature": [ - "boolean | undefined" - ], - "path": "src/plugins/unified_histogram/public/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "unifiedHistogram", - "id": "def-public.UnifiedHistogramBucketInterval.description", - "type": "string", + "id": "def-public.UnifiedHistogramBreakdownContext.field", + "type": "Object", "tags": [], - "label": "description", - "description": [], - "signature": [ - "string | undefined" + "label": "field", + "description": [ + "\nThe field used for the breakdown" ], - "path": "src/plugins/unified_histogram/public/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "unifiedHistogram", - "id": "def-public.UnifiedHistogramBucketInterval.scale", - "type": "number", - "tags": [], - "label": "scale", - "description": [], "signature": [ - "number | undefined" + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewField", + "text": "DataViewField" + }, + " | undefined" ], "path": "src/plugins/unified_histogram/public/types.ts", "deprecated": false, @@ -365,22 +99,6 @@ "deprecated": false, "trackAdoption": false, "children": [ - { - "parentPluginId": "unifiedHistogram", - "id": "def-public.UnifiedHistogramChartContext.status", - "type": "CompoundType", - "tags": [], - "label": "status", - "description": [ - "\nThe fetch status of the chart request" - ], - "signature": [ - "\"loading\" | \"error\" | \"complete\" | \"partial\" | \"uninitialized\"" - ], - "path": "src/plugins/unified_histogram/public/types.ts", - "deprecated": false, - "trackAdoption": false - }, { "parentPluginId": "unifiedHistogram", "id": "def-public.UnifiedHistogramChartContext.hidden", @@ -415,61 +133,15 @@ }, { "parentPluginId": "unifiedHistogram", - "id": "def-public.UnifiedHistogramChartContext.bucketInterval", - "type": "Object", - "tags": [], - "label": "bucketInterval", - "description": [ - "\nThe bucketInterval object returned by {@link buildChartData}" - ], - "signature": [ - { - "pluginId": "unifiedHistogram", - "scope": "public", - "docId": "kibUnifiedHistogramPluginApi", - "section": "def-public.UnifiedHistogramBucketInterval", - "text": "UnifiedHistogramBucketInterval" - }, - " | undefined" - ], - "path": "src/plugins/unified_histogram/public/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "unifiedHistogram", - "id": "def-public.UnifiedHistogramChartContext.data", - "type": "Object", - "tags": [], - "label": "data", - "description": [ - "\nThe chartData object returned by {@link buildChartData}" - ], - "signature": [ - { - "pluginId": "unifiedHistogram", - "scope": "public", - "docId": "kibUnifiedHistogramPluginApi", - "section": "def-public.UnifiedHistogramChartData", - "text": "UnifiedHistogramChartData" - }, - " | undefined" - ], - "path": "src/plugins/unified_histogram/public/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "unifiedHistogram", - "id": "def-public.UnifiedHistogramChartContext.error", - "type": "Object", + "id": "def-public.UnifiedHistogramChartContext.title", + "type": "string", "tags": [], - "label": "error", + "label": "title", "description": [ - "\nError from failed chart request" + "\nThe chart title -- sets the title property on the Lens chart input" ], "signature": [ - "Error | undefined" + "string | undefined" ], "path": "src/plugins/unified_histogram/public/types.ts", "deprecated": false, @@ -480,12 +152,12 @@ }, { "parentPluginId": "unifiedHistogram", - "id": "def-public.UnifiedHistogramChartData", + "id": "def-public.UnifiedHistogramChartLoadEvent", "type": "Interface", "tags": [], - "label": "UnifiedHistogramChartData", + "label": "UnifiedHistogramChartLoadEvent", "description": [ - "\nThe chartData object returned by {@link buildChartData} that\nshould be used to set {@link UnifiedHistogramChartContext.data}" + "\nEmitted when the histogram loading status changes" ], "path": "src/plugins/unified_histogram/public/types.ts", "deprecated": false, @@ -493,27 +165,12 @@ "children": [ { "parentPluginId": "unifiedHistogram", - "id": "def-public.UnifiedHistogramChartData.values", - "type": "Array", + "id": "def-public.UnifiedHistogramChartLoadEvent.complete", + "type": "boolean", "tags": [], - "label": "values", - "description": [], - "signature": [ - "{ x: number; y: number; }[]" - ], - "path": "src/plugins/unified_histogram/public/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "unifiedHistogram", - "id": "def-public.UnifiedHistogramChartData.xAxisOrderedValues", - "type": "Array", - "tags": [], - "label": "xAxisOrderedValues", - "description": [], - "signature": [ - "number[]" + "label": "complete", + "description": [ + "\nTrue if loading is complete" ], "path": "src/plugins/unified_histogram/public/types.ts", "deprecated": false, @@ -521,82 +178,39 @@ }, { "parentPluginId": "unifiedHistogram", - "id": "def-public.UnifiedHistogramChartData.xAxisFormat", + "id": "def-public.UnifiedHistogramChartLoadEvent.adapters", "type": "Object", "tags": [], - "label": "xAxisFormat", - "description": [], + "label": "adapters", + "description": [ + "\nInspector adapters for the request" + ], "signature": [ - "{ id?: string | undefined; params?: ", + "{ requests?: ", { - "pluginId": "fieldFormats", + "pluginId": "inspector", "scope": "common", - "docId": "kibFieldFormatsPluginApi", - "section": "def-common.FieldFormatParams", - "text": "FieldFormatParams" + "docId": "kibInspectorPluginApi", + "section": "def-common.RequestAdapter", + "text": "RequestAdapter" }, - "<{ pattern: string; }> | undefined; }" - ], - "path": "src/plugins/unified_histogram/public/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "unifiedHistogram", - "id": "def-public.UnifiedHistogramChartData.yAxisFormat", - "type": "Object", - "tags": [], - "label": "yAxisFormat", - "description": [], - "signature": [ - "{ id?: string | undefined; params?: ", + " | undefined; tables?: ", { - "pluginId": "fieldFormats", + "pluginId": "expressions", "scope": "common", - "docId": "kibFieldFormatsPluginApi", - "section": "def-common.FieldFormatParams", - "text": "FieldFormatParams" + "docId": "kibExpressionsPluginApi", + "section": "def-common.TablesAdapter", + "text": "TablesAdapter" }, - "<{ pattern: string; }> | undefined; }" - ], - "path": "src/plugins/unified_histogram/public/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "unifiedHistogram", - "id": "def-public.UnifiedHistogramChartData.xAxisLabel", - "type": "string", - "tags": [], - "label": "xAxisLabel", - "description": [], - "path": "src/plugins/unified_histogram/public/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "unifiedHistogram", - "id": "def-public.UnifiedHistogramChartData.yAxisLabel", - "type": "string", - "tags": [], - "label": "yAxisLabel", - "description": [], - "signature": [ - "string | undefined" - ], - "path": "src/plugins/unified_histogram/public/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "unifiedHistogram", - "id": "def-public.UnifiedHistogramChartData.ordered", - "type": "Object", - "tags": [], - "label": "ordered", - "description": [], - "signature": [ - "Ordered" + " | undefined; expression?: ", + { + "pluginId": "expressions", + "scope": "common", + "docId": "kibExpressionsPluginApi", + "section": "def-common.ExpressionsInspectorAdapter", + "text": "ExpressionsInspectorAdapter" + }, + " | undefined; }" ], "path": "src/plugins/unified_histogram/public/types.ts", "deprecated": false, @@ -628,7 +242,14 @@ "\nThe fetch status of the hits count request" ], "signature": [ - "\"loading\" | \"error\" | \"complete\" | \"partial\" | \"uninitialized\"" + { + "pluginId": "unifiedHistogram", + "scope": "public", + "docId": "kibUnifiedHistogramPluginApi", + "section": "def-public.UnifiedHistogramFetchStatus", + "text": "UnifiedHistogramFetchStatus" + }, + " | undefined" ], "path": "src/plugins/unified_histogram/public/types.ts", "deprecated": false, @@ -680,7 +301,9 @@ "type": "string", "tags": [], "label": "className", - "description": [], + "description": [ + "\nOptional class name to add to the layout container" + ], "signature": [ "string | undefined" ], @@ -694,7 +317,9 @@ "type": "Object", "tags": [], "label": "services", - "description": [], + "description": [ + "\nRequired services" + ], "signature": [ { "pluginId": "unifiedHistogram", @@ -708,6 +333,67 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramLayoutProps.dataView", + "type": "Object", + "tags": [], + "label": "dataView", + "description": [ + "\nThe current data view" + ], + "signature": [ + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataView", + "text": "DataView" + } + ], + "path": "src/plugins/unified_histogram/public/layout/layout.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramLayoutProps.lastReloadRequestTime", + "type": "number", + "tags": [], + "label": "lastReloadRequestTime", + "description": [ + "\nCan be updated to `Date.now()` to force a refresh" + ], + "signature": [ + "number | undefined" + ], + "path": "src/plugins/unified_histogram/public/layout/layout.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramLayoutProps.request", + "type": "Object", + "tags": [], + "label": "request", + "description": [ + "\nContext object for requests made by unified histogram components -- optional" + ], + "signature": [ + { + "pluginId": "unifiedHistogram", + "scope": "public", + "docId": "kibUnifiedHistogramPluginApi", + "section": "def-public.UnifiedHistogramRequestContext", + "text": "UnifiedHistogramRequestContext" + }, + " | undefined" + ], + "path": "src/plugins/unified_histogram/public/layout/layout.tsx", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "unifiedHistogram", "id": "def-public.UnifiedHistogramLayoutProps.hits", @@ -754,6 +440,29 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramLayoutProps.breakdown", + "type": "Object", + "tags": [], + "label": "breakdown", + "description": [ + "\nContext object for the breakdown -- leave undefined to hide the breakdown" + ], + "signature": [ + { + "pluginId": "unifiedHistogram", + "scope": "public", + "docId": "kibUnifiedHistogramPluginApi", + "section": "def-public.UnifiedHistogramBreakdownContext", + "text": "UnifiedHistogramBreakdownContext" + }, + " | undefined" + ], + "path": "src/plugins/unified_histogram/public/layout/layout.tsx", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "unifiedHistogram", "id": "def-public.UnifiedHistogramLayoutProps.resizeRef", @@ -846,12 +555,128 @@ "\nCallback to invoke when the user clicks the edit visualization button -- leave undefined to hide the button" ], "signature": [ - "(() => void) | undefined" + "((lensAttributes: LensAttributes<\"lnsXY\", ", + { + "pluginId": "lens", + "scope": "public", + "docId": "kibLensPluginApi", + "section": "def-public.XYState", + "text": "XYState" + }, + "> | LensAttributes<\"lnsPie\", ", + { + "pluginId": "lens", + "scope": "common", + "docId": "kibLensPluginApi", + "section": "def-common.PieVisualizationState", + "text": "PieVisualizationState" + }, + "> | LensAttributes<\"lnsDatatable\", ", + { + "pluginId": "lens", + "scope": "public", + "docId": "kibLensPluginApi", + "section": "def-public.DatatableVisualizationState", + "text": "DatatableVisualizationState" + }, + "> | LensAttributes<\"lnsLegacyMetric\", ", + { + "pluginId": "lens", + "scope": "common", + "docId": "kibLensPluginApi", + "section": "def-common.LegacyMetricState", + "text": "LegacyMetricState" + }, + "> | LensAttributes<\"lnsMetric\", ", + "MetricVisualizationState", + "> | LensAttributes<\"lnsHeatmap\", ", + { + "pluginId": "lens", + "scope": "public", + "docId": "kibLensPluginApi", + "section": "def-public.HeatmapVisualizationState", + "text": "HeatmapVisualizationState" + }, + "> | LensAttributes<\"lnsGauge\", ", + { + "pluginId": "lens", + "scope": "public", + "docId": "kibLensPluginApi", + "section": "def-public.GaugeVisualizationState", + "text": "GaugeVisualizationState" + }, + "> | LensAttributes) => void) | undefined" ], "path": "src/plugins/unified_histogram/public/layout/layout.tsx", "deprecated": false, "trackAdoption": false, - "children": [], + "children": [ + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramLayoutProps.onEditVisualization.$1", + "type": "CompoundType", + "tags": [], + "label": "lensAttributes", + "description": [], + "signature": [ + "LensAttributes<\"lnsXY\", ", + { + "pluginId": "lens", + "scope": "public", + "docId": "kibLensPluginApi", + "section": "def-public.XYState", + "text": "XYState" + }, + "> | LensAttributes<\"lnsPie\", ", + { + "pluginId": "lens", + "scope": "common", + "docId": "kibLensPluginApi", + "section": "def-common.PieVisualizationState", + "text": "PieVisualizationState" + }, + "> | LensAttributes<\"lnsDatatable\", ", + { + "pluginId": "lens", + "scope": "public", + "docId": "kibLensPluginApi", + "section": "def-public.DatatableVisualizationState", + "text": "DatatableVisualizationState" + }, + "> | LensAttributes<\"lnsLegacyMetric\", ", + { + "pluginId": "lens", + "scope": "common", + "docId": "kibLensPluginApi", + "section": "def-common.LegacyMetricState", + "text": "LegacyMetricState" + }, + "> | LensAttributes<\"lnsMetric\", ", + "MetricVisualizationState", + "> | LensAttributes<\"lnsHeatmap\", ", + { + "pluginId": "lens", + "scope": "public", + "docId": "kibLensPluginApi", + "section": "def-public.HeatmapVisualizationState", + "text": "HeatmapVisualizationState" + }, + "> | LensAttributes<\"lnsGauge\", ", + { + "pluginId": "lens", + "scope": "public", + "docId": "kibLensPluginApi", + "section": "def-public.GaugeVisualizationState", + "text": "GaugeVisualizationState" + }, + "> | LensAttributes" + ], + "path": "src/plugins/unified_histogram/public/layout/layout.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], "returnComment": [] }, { @@ -921,6 +746,221 @@ } ], "returnComment": [] + }, + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramLayoutProps.onBreakdownFieldChange", + "type": "Function", + "tags": [], + "label": "onBreakdownFieldChange", + "description": [ + "\nCallback to update the breakdown field -- should set {@link UnifiedHistogramBreakdownContext.field} to breakdownField" + ], + "signature": [ + "((breakdownField: ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewField", + "text": "DataViewField" + }, + " | undefined) => void) | undefined" + ], + "path": "src/plugins/unified_histogram/public/layout/layout.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramLayoutProps.onBreakdownFieldChange.$1", + "type": "Object", + "tags": [], + "label": "breakdownField", + "description": [], + "signature": [ + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataViewField", + "text": "DataViewField" + }, + " | undefined" + ], + "path": "src/plugins/unified_histogram/public/layout/layout.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramLayoutProps.onTotalHitsChange", + "type": "Function", + "tags": [], + "label": "onTotalHitsChange", + "description": [ + "\nCallback to update the total hits -- should set {@link UnifiedHistogramHitsContext.status} to status\nand {@link UnifiedHistogramHitsContext.total} to result" + ], + "signature": [ + "((status: ", + { + "pluginId": "unifiedHistogram", + "scope": "public", + "docId": "kibUnifiedHistogramPluginApi", + "section": "def-public.UnifiedHistogramFetchStatus", + "text": "UnifiedHistogramFetchStatus" + }, + ", result?: number | Error | undefined) => void) | undefined" + ], + "path": "src/plugins/unified_histogram/public/layout/layout.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramLayoutProps.onTotalHitsChange.$1", + "type": "Enum", + "tags": [], + "label": "status", + "description": [], + "signature": [ + { + "pluginId": "unifiedHistogram", + "scope": "public", + "docId": "kibUnifiedHistogramPluginApi", + "section": "def-public.UnifiedHistogramFetchStatus", + "text": "UnifiedHistogramFetchStatus" + } + ], + "path": "src/plugins/unified_histogram/public/layout/layout.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramLayoutProps.onTotalHitsChange.$2", + "type": "CompoundType", + "tags": [], + "label": "result", + "description": [], + "signature": [ + "number | Error | undefined" + ], + "path": "src/plugins/unified_histogram/public/layout/layout.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramLayoutProps.onChartLoad", + "type": "Function", + "tags": [], + "label": "onChartLoad", + "description": [ + "\nCalled when the histogram loading status changes" + ], + "signature": [ + "((event: ", + { + "pluginId": "unifiedHistogram", + "scope": "public", + "docId": "kibUnifiedHistogramPluginApi", + "section": "def-public.UnifiedHistogramChartLoadEvent", + "text": "UnifiedHistogramChartLoadEvent" + }, + ") => void) | undefined" + ], + "path": "src/plugins/unified_histogram/public/layout/layout.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramLayoutProps.onChartLoad.$1", + "type": "Object", + "tags": [], + "label": "event", + "description": [], + "signature": [ + { + "pluginId": "unifiedHistogram", + "scope": "public", + "docId": "kibUnifiedHistogramPluginApi", + "section": "def-public.UnifiedHistogramChartLoadEvent", + "text": "UnifiedHistogramChartLoadEvent" + } + ], + "path": "src/plugins/unified_histogram/public/layout/layout.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramRequestContext", + "type": "Interface", + "tags": [], + "label": "UnifiedHistogramRequestContext", + "description": [ + "\nContext object for requests made by unified histogram components" + ], + "path": "src/plugins/unified_histogram/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramRequestContext.searchSessionId", + "type": "string", + "tags": [], + "label": "searchSessionId", + "description": [ + "\nCurrent search session ID" + ], + "signature": [ + "string | undefined" + ], + "path": "src/plugins/unified_histogram/public/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramRequestContext.adapter", + "type": "Object", + "tags": [], + "label": "adapter", + "description": [ + "\nThe adapter to use for requests (does not apply to Lens requests)" + ], + "signature": [ + { + "pluginId": "inspector", + "scope": "common", + "docId": "kibInspectorPluginApi", + "section": "def-common.RequestAdapter", + "text": "RequestAdapter" + }, + " | undefined" + ], + "path": "src/plugins/unified_histogram/public/types.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false @@ -1045,24 +1085,81 @@ "path": "src/plugins/unified_histogram/public/types.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramServices.lens", + "type": "Object", + "tags": [], + "label": "lens", + "description": [], + "signature": [ + { + "pluginId": "lens", + "scope": "public", + "docId": "kibLensPluginApi", + "section": "def-public.LensPublicStart", + "text": "LensPublicStart" + } + ], + "path": "src/plugins/unified_histogram/public/types.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false } ], - "enums": [], - "misc": [ + "enums": [ { "parentPluginId": "unifiedHistogram", "id": "def-public.UnifiedHistogramFetchStatus", - "type": "Type", + "type": "Enum", "tags": [], "label": "UnifiedHistogramFetchStatus", "description": [ "\nThe fetch status of a unified histogram request" ], + "path": "src/plugins/unified_histogram/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + } + ], + "misc": [ + { + "parentPluginId": "unifiedHistogram", + "id": "def-public.UnifiedHistogramAdapters", + "type": "Type", + "tags": [], + "label": "UnifiedHistogramAdapters", + "description": [], "signature": [ - "\"loading\" | \"error\" | \"complete\" | \"partial\" | \"uninitialized\"" + "{ requests?: ", + { + "pluginId": "inspector", + "scope": "common", + "docId": "kibInspectorPluginApi", + "section": "def-common.RequestAdapter", + "text": "RequestAdapter" + }, + " | undefined; tables?: ", + { + "pluginId": "expressions", + "scope": "common", + "docId": "kibExpressionsPluginApi", + "section": "def-common.TablesAdapter", + "text": "TablesAdapter" + }, + " | undefined; expression?: ", + { + "pluginId": "expressions", + "scope": "common", + "docId": "kibExpressionsPluginApi", + "section": "def-common.ExpressionsInspectorAdapter", + "text": "ExpressionsInspectorAdapter" + }, + " | undefined; }" ], "path": "src/plugins/unified_histogram/public/types.ts", "deprecated": false, diff --git a/api_docs/unified_histogram.mdx b/api_docs/unified_histogram.mdx index 3f55a049b08df..516370395fbb4 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: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedHistogram'] --- import unifiedHistogramObj from './unified_histogram.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Data Discovery](https://github.com/orgs/elastic/teams/kibana-data-disco | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 56 | 0 | 29 | 0 | +| 52 | 0 | 15 | 0 | ## Client @@ -31,6 +31,9 @@ Contact [Data Discovery](https://github.com/orgs/elastic/teams/kibana-data-disco ### Interfaces +### Enums + + ### Consts, variables and types diff --git a/api_docs/unified_search.devdocs.json b/api_docs/unified_search.devdocs.json index 67bef40170498..15e716b82ecad 100644 --- a/api_docs/unified_search.devdocs.json +++ b/api_docs/unified_search.devdocs.json @@ -2212,7 +2212,63 @@ }, ">, {}: ", "UnifiedSearchServerPluginSetupDependencies", - ") => { autocomplete: { getAutocompleteSettings: () => { terminateAfter: number; timeout: number; }; }; }" + ") => { autocomplete: { getAutocompleteSettings: () => { terminateAfter: number; timeout: number; }; getInitializerContextConfig: () => { legacy: { globalConfig$: ", + "Observable", + " moment.Duration; humanize: { (argWithSuffix?: boolean | undefined, argThresholds?: moment.argThresholdOpts | undefined): string; (argThresholds?: moment.argThresholdOpts | undefined): string; }; abs: () => moment.Duration; as: (units: moment.unitOfTime.Base) => number; get: (units: moment.unitOfTime.Base) => number; milliseconds: () => number; asMilliseconds: () => number; seconds: () => number; asSeconds: () => number; minutes: () => number; asMinutes: () => number; hours: () => number; asHours: () => number; days: () => number; asDays: () => number; weeks: () => number; asWeeks: () => number; months: () => number; asMonths: () => number; years: () => number; asYears: () => number; add: (inp?: moment.DurationInputArg1, unit?: moment.unitOfTime.DurationConstructor | undefined) => moment.Duration; subtract: (inp?: moment.DurationInputArg1, unit?: moment.unitOfTime.DurationConstructor | undefined) => moment.Duration; locale: { (): string; (locale: moment.LocaleSpecifier): moment.Duration; }; localeData: () => moment.Locale; toISOString: () => string; toJSON: () => string; isValid: () => boolean; lang: { (locale: moment.LocaleSpecifier): moment.Moment; (): moment.Locale; }; toIsoString: () => string; format: moment.Format; }>; readonly shardTimeout: Readonly<{ clone: () => moment.Duration; humanize: { (argWithSuffix?: boolean | undefined, argThresholds?: moment.argThresholdOpts | undefined): string; (argThresholds?: moment.argThresholdOpts | undefined): string; }; abs: () => moment.Duration; as: (units: moment.unitOfTime.Base) => number; get: (units: moment.unitOfTime.Base) => number; milliseconds: () => number; asMilliseconds: () => number; seconds: () => number; asSeconds: () => number; minutes: () => number; asMinutes: () => number; hours: () => number; asHours: () => number; days: () => number; asDays: () => number; weeks: () => number; asWeeks: () => number; months: () => number; asMonths: () => number; years: () => number; asYears: () => number; add: (inp?: moment.DurationInputArg1, unit?: moment.unitOfTime.DurationConstructor | undefined) => moment.Duration; subtract: (inp?: moment.DurationInputArg1, unit?: moment.unitOfTime.DurationConstructor | undefined) => moment.Duration; locale: { (): string; (locale: moment.LocaleSpecifier): moment.Duration; }; localeData: () => moment.Locale; toISOString: () => string; toJSON: () => string; isValid: () => boolean; lang: { (locale: moment.LocaleSpecifier): moment.Moment; (): moment.Locale; }; toIsoString: () => string; format: moment.Format; }>; readonly pingTimeout: Readonly<{ clone: () => moment.Duration; humanize: { (argWithSuffix?: boolean | undefined, argThresholds?: moment.argThresholdOpts | undefined): string; (argThresholds?: moment.argThresholdOpts | undefined): string; }; abs: () => moment.Duration; as: (units: moment.unitOfTime.Base) => number; get: (units: moment.unitOfTime.Base) => number; milliseconds: () => number; asMilliseconds: () => number; seconds: () => number; asSeconds: () => number; minutes: () => number; asMinutes: () => number; hours: () => number; asHours: () => number; days: () => number; asDays: () => number; weeks: () => number; asWeeks: () => number; months: () => number; asMonths: () => number; years: () => number; asYears: () => number; add: (inp?: moment.DurationInputArg1, unit?: moment.unitOfTime.DurationConstructor | undefined) => moment.Duration; subtract: (inp?: moment.DurationInputArg1, unit?: moment.unitOfTime.DurationConstructor | undefined) => moment.Duration; locale: { (): string; (locale: moment.LocaleSpecifier): moment.Duration; }; localeData: () => moment.Locale; toISOString: () => string; toJSON: () => string; isValid: () => boolean; lang: { (locale: moment.LocaleSpecifier): moment.Moment; (): moment.Locale; }; toIsoString: () => string; format: moment.Format; }>; }>; path: Readonly<{ readonly data: string; }>; savedObjects: Readonly<{ readonly maxImportPayloadBytes: Readonly<{ isGreaterThan: (other: ", + { + "pluginId": "@kbn/config-schema", + "scope": "server", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-server.ByteSizeValue", + "text": "ByteSizeValue" + }, + ") => boolean; isLessThan: (other: ", + { + "pluginId": "@kbn/config-schema", + "scope": "server", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-server.ByteSizeValue", + "text": "ByteSizeValue" + }, + ") => boolean; isEqualTo: (other: ", + { + "pluginId": "@kbn/config-schema", + "scope": "server", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-server.ByteSizeValue", + "text": "ByteSizeValue" + }, + ") => boolean; getValueInBytes: () => number; toString: (returnUnit?: ", + "ByteSizeValueUnit", + " | undefined) => string; }>; }>; }>>; get: () => Readonly<{ elasticsearch: Readonly<{ readonly requestTimeout: Readonly<{ clone: () => moment.Duration; humanize: { (argWithSuffix?: boolean | undefined, argThresholds?: moment.argThresholdOpts | undefined): string; (argThresholds?: moment.argThresholdOpts | undefined): string; }; abs: () => moment.Duration; as: (units: moment.unitOfTime.Base) => number; get: (units: moment.unitOfTime.Base) => number; milliseconds: () => number; asMilliseconds: () => number; seconds: () => number; asSeconds: () => number; minutes: () => number; asMinutes: () => number; hours: () => number; asHours: () => number; days: () => number; asDays: () => number; weeks: () => number; asWeeks: () => number; months: () => number; asMonths: () => number; years: () => number; asYears: () => number; add: (inp?: moment.DurationInputArg1, unit?: moment.unitOfTime.DurationConstructor | undefined) => moment.Duration; subtract: (inp?: moment.DurationInputArg1, unit?: moment.unitOfTime.DurationConstructor | undefined) => moment.Duration; locale: { (): string; (locale: moment.LocaleSpecifier): moment.Duration; }; localeData: () => moment.Locale; toISOString: () => string; toJSON: () => string; isValid: () => boolean; lang: { (locale: moment.LocaleSpecifier): moment.Moment; (): moment.Locale; }; toIsoString: () => string; format: moment.Format; }>; readonly shardTimeout: Readonly<{ clone: () => moment.Duration; humanize: { (argWithSuffix?: boolean | undefined, argThresholds?: moment.argThresholdOpts | undefined): string; (argThresholds?: moment.argThresholdOpts | undefined): string; }; abs: () => moment.Duration; as: (units: moment.unitOfTime.Base) => number; get: (units: moment.unitOfTime.Base) => number; milliseconds: () => number; asMilliseconds: () => number; seconds: () => number; asSeconds: () => number; minutes: () => number; asMinutes: () => number; hours: () => number; asHours: () => number; days: () => number; asDays: () => number; weeks: () => number; asWeeks: () => number; months: () => number; asMonths: () => number; years: () => number; asYears: () => number; add: (inp?: moment.DurationInputArg1, unit?: moment.unitOfTime.DurationConstructor | undefined) => moment.Duration; subtract: (inp?: moment.DurationInputArg1, unit?: moment.unitOfTime.DurationConstructor | undefined) => moment.Duration; locale: { (): string; (locale: moment.LocaleSpecifier): moment.Duration; }; localeData: () => moment.Locale; toISOString: () => string; toJSON: () => string; isValid: () => boolean; lang: { (locale: moment.LocaleSpecifier): moment.Moment; (): moment.Locale; }; toIsoString: () => string; format: moment.Format; }>; readonly pingTimeout: Readonly<{ clone: () => moment.Duration; humanize: { (argWithSuffix?: boolean | undefined, argThresholds?: moment.argThresholdOpts | undefined): string; (argThresholds?: moment.argThresholdOpts | undefined): string; }; abs: () => moment.Duration; as: (units: moment.unitOfTime.Base) => number; get: (units: moment.unitOfTime.Base) => number; milliseconds: () => number; asMilliseconds: () => number; seconds: () => number; asSeconds: () => number; minutes: () => number; asMinutes: () => number; hours: () => number; asHours: () => number; days: () => number; asDays: () => number; weeks: () => number; asWeeks: () => number; months: () => number; asMonths: () => number; years: () => number; asYears: () => number; add: (inp?: moment.DurationInputArg1, unit?: moment.unitOfTime.DurationConstructor | undefined) => moment.Duration; subtract: (inp?: moment.DurationInputArg1, unit?: moment.unitOfTime.DurationConstructor | undefined) => moment.Duration; locale: { (): string; (locale: moment.LocaleSpecifier): moment.Duration; }; localeData: () => moment.Locale; toISOString: () => string; toJSON: () => string; isValid: () => boolean; lang: { (locale: moment.LocaleSpecifier): moment.Moment; (): moment.Locale; }; toIsoString: () => string; format: moment.Format; }>; }>; path: Readonly<{ readonly data: string; }>; savedObjects: Readonly<{ readonly maxImportPayloadBytes: Readonly<{ isGreaterThan: (other: ", + { + "pluginId": "@kbn/config-schema", + "scope": "server", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-server.ByteSizeValue", + "text": "ByteSizeValue" + }, + ") => boolean; isLessThan: (other: ", + { + "pluginId": "@kbn/config-schema", + "scope": "server", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-server.ByteSizeValue", + "text": "ByteSizeValue" + }, + ") => boolean; isEqualTo: (other: ", + { + "pluginId": "@kbn/config-schema", + "scope": "server", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-server.ByteSizeValue", + "text": "ByteSizeValue" + }, + ") => boolean; getValueInBytes: () => number; toString: (returnUnit?: ", + "ByteSizeValueUnit", + " | undefined) => string; }>; }>; }>; }; create: ; valueSuggestions: Readonly<{} & { timeout: moment.Duration; enabled: boolean; tiers: string[]; terminateAfter: moment.Duration; }>; }>; }>>() => ", + "Observable", + "; get: ; valueSuggestions: Readonly<{} & { timeout: moment.Duration; enabled: boolean; tiers: string[]; terminateAfter: moment.Duration; }>; }>; }>>() => T; }; }; }" ], "path": "src/plugins/unified_search/server/plugin.ts", "deprecated": false, @@ -2389,7 +2445,63 @@ "label": "autocomplete", "description": [], "signature": [ - "{ getAutocompleteSettings: () => { terminateAfter: number; timeout: number; }; }" + "{ getAutocompleteSettings: () => { terminateAfter: number; timeout: number; }; getInitializerContextConfig: () => { legacy: { globalConfig$: ", + "Observable", + " moment.Duration; humanize: { (argWithSuffix?: boolean | undefined, argThresholds?: moment.argThresholdOpts | undefined): string; (argThresholds?: moment.argThresholdOpts | undefined): string; }; abs: () => moment.Duration; as: (units: moment.unitOfTime.Base) => number; get: (units: moment.unitOfTime.Base) => number; milliseconds: () => number; asMilliseconds: () => number; seconds: () => number; asSeconds: () => number; minutes: () => number; asMinutes: () => number; hours: () => number; asHours: () => number; days: () => number; asDays: () => number; weeks: () => number; asWeeks: () => number; months: () => number; asMonths: () => number; years: () => number; asYears: () => number; add: (inp?: moment.DurationInputArg1, unit?: moment.unitOfTime.DurationConstructor | undefined) => moment.Duration; subtract: (inp?: moment.DurationInputArg1, unit?: moment.unitOfTime.DurationConstructor | undefined) => moment.Duration; locale: { (): string; (locale: moment.LocaleSpecifier): moment.Duration; }; localeData: () => moment.Locale; toISOString: () => string; toJSON: () => string; isValid: () => boolean; lang: { (locale: moment.LocaleSpecifier): moment.Moment; (): moment.Locale; }; toIsoString: () => string; format: moment.Format; }>; readonly shardTimeout: Readonly<{ clone: () => moment.Duration; humanize: { (argWithSuffix?: boolean | undefined, argThresholds?: moment.argThresholdOpts | undefined): string; (argThresholds?: moment.argThresholdOpts | undefined): string; }; abs: () => moment.Duration; as: (units: moment.unitOfTime.Base) => number; get: (units: moment.unitOfTime.Base) => number; milliseconds: () => number; asMilliseconds: () => number; seconds: () => number; asSeconds: () => number; minutes: () => number; asMinutes: () => number; hours: () => number; asHours: () => number; days: () => number; asDays: () => number; weeks: () => number; asWeeks: () => number; months: () => number; asMonths: () => number; years: () => number; asYears: () => number; add: (inp?: moment.DurationInputArg1, unit?: moment.unitOfTime.DurationConstructor | undefined) => moment.Duration; subtract: (inp?: moment.DurationInputArg1, unit?: moment.unitOfTime.DurationConstructor | undefined) => moment.Duration; locale: { (): string; (locale: moment.LocaleSpecifier): moment.Duration; }; localeData: () => moment.Locale; toISOString: () => string; toJSON: () => string; isValid: () => boolean; lang: { (locale: moment.LocaleSpecifier): moment.Moment; (): moment.Locale; }; toIsoString: () => string; format: moment.Format; }>; readonly pingTimeout: Readonly<{ clone: () => moment.Duration; humanize: { (argWithSuffix?: boolean | undefined, argThresholds?: moment.argThresholdOpts | undefined): string; (argThresholds?: moment.argThresholdOpts | undefined): string; }; abs: () => moment.Duration; as: (units: moment.unitOfTime.Base) => number; get: (units: moment.unitOfTime.Base) => number; milliseconds: () => number; asMilliseconds: () => number; seconds: () => number; asSeconds: () => number; minutes: () => number; asMinutes: () => number; hours: () => number; asHours: () => number; days: () => number; asDays: () => number; weeks: () => number; asWeeks: () => number; months: () => number; asMonths: () => number; years: () => number; asYears: () => number; add: (inp?: moment.DurationInputArg1, unit?: moment.unitOfTime.DurationConstructor | undefined) => moment.Duration; subtract: (inp?: moment.DurationInputArg1, unit?: moment.unitOfTime.DurationConstructor | undefined) => moment.Duration; locale: { (): string; (locale: moment.LocaleSpecifier): moment.Duration; }; localeData: () => moment.Locale; toISOString: () => string; toJSON: () => string; isValid: () => boolean; lang: { (locale: moment.LocaleSpecifier): moment.Moment; (): moment.Locale; }; toIsoString: () => string; format: moment.Format; }>; }>; path: Readonly<{ readonly data: string; }>; savedObjects: Readonly<{ readonly maxImportPayloadBytes: Readonly<{ isGreaterThan: (other: ", + { + "pluginId": "@kbn/config-schema", + "scope": "server", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-server.ByteSizeValue", + "text": "ByteSizeValue" + }, + ") => boolean; isLessThan: (other: ", + { + "pluginId": "@kbn/config-schema", + "scope": "server", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-server.ByteSizeValue", + "text": "ByteSizeValue" + }, + ") => boolean; isEqualTo: (other: ", + { + "pluginId": "@kbn/config-schema", + "scope": "server", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-server.ByteSizeValue", + "text": "ByteSizeValue" + }, + ") => boolean; getValueInBytes: () => number; toString: (returnUnit?: ", + "ByteSizeValueUnit", + " | undefined) => string; }>; }>; }>>; get: () => Readonly<{ elasticsearch: Readonly<{ readonly requestTimeout: Readonly<{ clone: () => moment.Duration; humanize: { (argWithSuffix?: boolean | undefined, argThresholds?: moment.argThresholdOpts | undefined): string; (argThresholds?: moment.argThresholdOpts | undefined): string; }; abs: () => moment.Duration; as: (units: moment.unitOfTime.Base) => number; get: (units: moment.unitOfTime.Base) => number; milliseconds: () => number; asMilliseconds: () => number; seconds: () => number; asSeconds: () => number; minutes: () => number; asMinutes: () => number; hours: () => number; asHours: () => number; days: () => number; asDays: () => number; weeks: () => number; asWeeks: () => number; months: () => number; asMonths: () => number; years: () => number; asYears: () => number; add: (inp?: moment.DurationInputArg1, unit?: moment.unitOfTime.DurationConstructor | undefined) => moment.Duration; subtract: (inp?: moment.DurationInputArg1, unit?: moment.unitOfTime.DurationConstructor | undefined) => moment.Duration; locale: { (): string; (locale: moment.LocaleSpecifier): moment.Duration; }; localeData: () => moment.Locale; toISOString: () => string; toJSON: () => string; isValid: () => boolean; lang: { (locale: moment.LocaleSpecifier): moment.Moment; (): moment.Locale; }; toIsoString: () => string; format: moment.Format; }>; readonly shardTimeout: Readonly<{ clone: () => moment.Duration; humanize: { (argWithSuffix?: boolean | undefined, argThresholds?: moment.argThresholdOpts | undefined): string; (argThresholds?: moment.argThresholdOpts | undefined): string; }; abs: () => moment.Duration; as: (units: moment.unitOfTime.Base) => number; get: (units: moment.unitOfTime.Base) => number; milliseconds: () => number; asMilliseconds: () => number; seconds: () => number; asSeconds: () => number; minutes: () => number; asMinutes: () => number; hours: () => number; asHours: () => number; days: () => number; asDays: () => number; weeks: () => number; asWeeks: () => number; months: () => number; asMonths: () => number; years: () => number; asYears: () => number; add: (inp?: moment.DurationInputArg1, unit?: moment.unitOfTime.DurationConstructor | undefined) => moment.Duration; subtract: (inp?: moment.DurationInputArg1, unit?: moment.unitOfTime.DurationConstructor | undefined) => moment.Duration; locale: { (): string; (locale: moment.LocaleSpecifier): moment.Duration; }; localeData: () => moment.Locale; toISOString: () => string; toJSON: () => string; isValid: () => boolean; lang: { (locale: moment.LocaleSpecifier): moment.Moment; (): moment.Locale; }; toIsoString: () => string; format: moment.Format; }>; readonly pingTimeout: Readonly<{ clone: () => moment.Duration; humanize: { (argWithSuffix?: boolean | undefined, argThresholds?: moment.argThresholdOpts | undefined): string; (argThresholds?: moment.argThresholdOpts | undefined): string; }; abs: () => moment.Duration; as: (units: moment.unitOfTime.Base) => number; get: (units: moment.unitOfTime.Base) => number; milliseconds: () => number; asMilliseconds: () => number; seconds: () => number; asSeconds: () => number; minutes: () => number; asMinutes: () => number; hours: () => number; asHours: () => number; days: () => number; asDays: () => number; weeks: () => number; asWeeks: () => number; months: () => number; asMonths: () => number; years: () => number; asYears: () => number; add: (inp?: moment.DurationInputArg1, unit?: moment.unitOfTime.DurationConstructor | undefined) => moment.Duration; subtract: (inp?: moment.DurationInputArg1, unit?: moment.unitOfTime.DurationConstructor | undefined) => moment.Duration; locale: { (): string; (locale: moment.LocaleSpecifier): moment.Duration; }; localeData: () => moment.Locale; toISOString: () => string; toJSON: () => string; isValid: () => boolean; lang: { (locale: moment.LocaleSpecifier): moment.Moment; (): moment.Locale; }; toIsoString: () => string; format: moment.Format; }>; }>; path: Readonly<{ readonly data: string; }>; savedObjects: Readonly<{ readonly maxImportPayloadBytes: Readonly<{ isGreaterThan: (other: ", + { + "pluginId": "@kbn/config-schema", + "scope": "server", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-server.ByteSizeValue", + "text": "ByteSizeValue" + }, + ") => boolean; isLessThan: (other: ", + { + "pluginId": "@kbn/config-schema", + "scope": "server", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-server.ByteSizeValue", + "text": "ByteSizeValue" + }, + ") => boolean; isEqualTo: (other: ", + { + "pluginId": "@kbn/config-schema", + "scope": "server", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-server.ByteSizeValue", + "text": "ByteSizeValue" + }, + ") => boolean; getValueInBytes: () => number; toString: (returnUnit?: ", + "ByteSizeValueUnit", + " | undefined) => string; }>; }>; }>; }; create: ; valueSuggestions: Readonly<{} & { timeout: moment.Duration; enabled: boolean; tiers: string[]; terminateAfter: moment.Duration; }>; }>; }>>() => ", + "Observable", + "; get: ; valueSuggestions: Readonly<{} & { timeout: moment.Duration; enabled: boolean; tiers: string[]; terminateAfter: moment.Duration; }>; }>; }>>() => T; }; }" ], "path": "src/plugins/unified_search/server/plugin.ts", "deprecated": false, diff --git a/api_docs/unified_search.mdx b/api_docs/unified_search.mdx index 098818c4a2822..541ddaa1d833a 100644 --- a/api_docs/unified_search.mdx +++ b/api_docs/unified_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedSearch title: "unifiedSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedSearch plugin -date: 2022-11-29 +date: 2022-12-06 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 10fd7363546f8..c712e9aedc5b1 100644 --- a/api_docs/unified_search_autocomplete.mdx +++ b/api_docs/unified_search_autocomplete.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedSearch-autocomplete title: "unifiedSearch.autocomplete" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedSearch.autocomplete plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedSearch.autocomplete'] --- import unifiedSearchAutocompleteObj from './unified_search_autocomplete.devdocs.json'; diff --git a/api_docs/url_forwarding.mdx b/api_docs/url_forwarding.mdx index a047cdd6b0a78..1b6f8246208a0 100644 --- a/api_docs/url_forwarding.mdx +++ b/api_docs/url_forwarding.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/urlForwarding title: "urlForwarding" image: https://source.unsplash.com/400x175/?github description: API docs for the urlForwarding plugin -date: 2022-11-29 +date: 2022-12-06 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 00c3e8ba6631e..558cc3e447e90 100644 --- a/api_docs/usage_collection.mdx +++ b/api_docs/usage_collection.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/usageCollection title: "usageCollection" image: https://source.unsplash.com/400x175/?github description: API docs for the usageCollection plugin -date: 2022-11-29 +date: 2022-12-06 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 312c64e2c7895..33f455584f77d 100644 --- a/api_docs/ux.mdx +++ b/api_docs/ux.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ux title: "ux" image: https://source.unsplash.com/400x175/?github description: API docs for the ux plugin -date: 2022-11-29 +date: 2022-12-06 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 aea78ef415f37..ada62356443b5 100644 --- a/api_docs/vis_default_editor.mdx +++ b/api_docs/vis_default_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visDefaultEditor title: "visDefaultEditor" image: https://source.unsplash.com/400x175/?github description: API docs for the visDefaultEditor plugin -date: 2022-11-29 +date: 2022-12-06 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 05b7a0685e2da..a8daaef1592a8 100644 --- a/api_docs/vis_type_gauge.mdx +++ b/api_docs/vis_type_gauge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeGauge title: "visTypeGauge" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeGauge plugin -date: 2022-11-29 +date: 2022-12-06 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 cce08ff6cdec1..c2925dadbc203 100644 --- a/api_docs/vis_type_heatmap.mdx +++ b/api_docs/vis_type_heatmap.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeHeatmap title: "visTypeHeatmap" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeHeatmap plugin -date: 2022-11-29 +date: 2022-12-06 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 ed472c72b0e5c..b2cf964c6ceb6 100644 --- a/api_docs/vis_type_pie.mdx +++ b/api_docs/vis_type_pie.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypePie title: "visTypePie" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypePie plugin -date: 2022-11-29 +date: 2022-12-06 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 d0a4905175d00..fa6224b4060bf 100644 --- a/api_docs/vis_type_table.mdx +++ b/api_docs/vis_type_table.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeTable title: "visTypeTable" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeTable plugin -date: 2022-11-29 +date: 2022-12-06 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 222f56432d03c..1b25eee004e2b 100644 --- a/api_docs/vis_type_timelion.mdx +++ b/api_docs/vis_type_timelion.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeTimelion title: "visTypeTimelion" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeTimelion plugin -date: 2022-11-29 +date: 2022-12-06 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 96c355d356d9e..b10f3bb9f6da9 100644 --- a/api_docs/vis_type_timeseries.mdx +++ b/api_docs/vis_type_timeseries.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeTimeseries title: "visTypeTimeseries" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeTimeseries plugin -date: 2022-11-29 +date: 2022-12-06 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 68e8f4a3841c1..430151dc5c26f 100644 --- a/api_docs/vis_type_vega.mdx +++ b/api_docs/vis_type_vega.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeVega title: "visTypeVega" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeVega plugin -date: 2022-11-29 +date: 2022-12-06 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 59bff3f2f0c54..cdf56efe992a0 100644 --- a/api_docs/vis_type_vislib.mdx +++ b/api_docs/vis_type_vislib.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeVislib title: "visTypeVislib" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeVislib plugin -date: 2022-11-29 +date: 2022-12-06 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 f3c2e3decda66..2f6c080e9a626 100644 --- a/api_docs/vis_type_xy.mdx +++ b/api_docs/vis_type_xy.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeXy title: "visTypeXy" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeXy plugin -date: 2022-11-29 +date: 2022-12-06 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 83623b42885e7..879e5181b4c14 100644 --- a/api_docs/visualizations.mdx +++ b/api_docs/visualizations.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visualizations title: "visualizations" image: https://source.unsplash.com/400x175/?github description: API docs for the visualizations plugin -date: 2022-11-29 +date: 2022-12-06 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visualizations'] --- import visualizationsObj from './visualizations.devdocs.json'; diff --git a/docs/concepts/kuery.asciidoc b/docs/concepts/kuery.asciidoc index 4e8b6bc4043e0..4eb95fa444058 100644 --- a/docs/concepts/kuery.asciidoc +++ b/docs/concepts/kuery.asciidoc @@ -184,3 +184,65 @@ documents where any sub-field of `http.response` contains “error”, use the f ------------------- http.response.*: error ------------------- + +[discrete] +=== Querying nested fields + +Querying {ref}/nested.html[nested fields] requires a special syntax. Consider the +following document, where `user` is a nested field: + +[source,yaml] +------------------- +{ + "user" : [ + { + "first" : "John", + "last" : "Smith" + }, + { + "first" : "Alice", + "last" : "White" + } + ] +} +------------------- + +To find documents where a single value inside the `user` array contains a first name of +“Alice” and last name of “White”, use the following: + +[source,yaml] +------------------- +user:{ first: "Alice" and last: "White" } +------------------- + +Because nested fields can be inside other nested fields, +you must specify the full path of the nested field you want to query. +For example, consider the following document where `user` and `names` are both nested fields: + +[source,yaml] +------------------- +{ + "user": [ + { + "names": [ + { + "first": "John", + "last": "Smith" + }, + { + "first": "Alice", + "last": "White" + } + ] + } + ] +} +------------------- + +To find documents where a single value inside the `user.names` array contains a first name of “Alice” *and* +last name of “White”, use the following: + +[source,yaml] +------------------- +user.names:{ first: "Alice" and last: "White" } +------------------- diff --git a/docs/index-custom-title-page.html b/docs/index-custom-title-page.html index f605cfce3dee9..4c9fe7af5ba59 100644 --- a/docs/index-custom-title-page.html +++ b/docs/index-custom-title-page.html @@ -63,7 +63,7 @@

Bring your data to life

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

@@ -113,6 +113,29 @@

Get to know Kibana

+
+
+

+ + Get started +

+
+ +
+

diff --git a/docs/user/alerting/create-and-manage-rules.asciidoc b/docs/user/alerting/create-and-manage-rules.asciidoc index 15de5944b59fc..d9d5c7bd3d5b0 100644 --- a/docs/user/alerting/create-and-manage-rules.asciidoc +++ b/docs/user/alerting/create-and-manage-rules.asciidoc @@ -104,7 +104,7 @@ image::images/rule-flyout-rule-conditions.png[UI for defining rule conditions on [[defining-rules-actions-details]] ==== Action type and details -To receive notifications when a rule meets the defined conditions, you must add one or more actions. Start by selecting a type of connector for your action: +Actions are optional when you create a rule. However, to receive notifications when a rule meets the defined conditions, you must add one or more actions. Start by selecting a type of connector for your action: [role="screenshot"] image::images/rule-flyout-connector-type-selection.png[UI for selecting an action type] @@ -118,6 +118,8 @@ Each action type exposes different properties. For example, an email action allo [role="screenshot"] image::images/rule-flyout-action-details.png[UI for defining an email action] +You can attach more than one action. Clicking the *Add action* button will prompt you to select another rule type and repeat the above steps again. + [float] [[defining-rules-actions-variables]] ===== Action variables @@ -145,17 +147,29 @@ Some cases exist where the variable values will be "escaped", when used in a con Mustache also supports "triple braces" of the form `{{{variable name}}}`, which indicates no escaping should be done at all. Care should be used when using this form, as it could end up rendering the variable content in such a way as to make the resulting parameter invalid or formatted incorrectly. +[float] +[[defining-rules-actions-variable-context]] +===== Action variable context + Each rule type defines additional variables as properties of the variable `context`. For example, if a rule type defines a variable `value`, it can be used in an action parameter as `{{context.value}}`. -For diagnostic or exploratory purposes, action variables whose values are objects, such as `context`, can be referenced directly as variables. The resulting value will be a JSON representation of the object. For example, if an action parameter includes `{{context}}`, it will expand to the JSON representation of all the variables and values provided by the rule type. +For diagnostic or exploratory purposes, action variables whose values are objects, such as `context`, can be referenced directly as variables. The resulting value will be a JSON representation of the object. For example, if an action parameter includes `{{context}}`, it will expand to the JSON representation of all the variables and values provided by the rule type. To see alert-specific variables, use `{{.}} `. -You can attach more than one action. Clicking the *Add action* button will prompt you to select another rule type and repeat the above steps again. +For situations where your rule response returns arrays of data, you can loop through the `context` by -[NOTE] -============================================== -Actions are not required on rules. You can run a rule without actions to -understand its behavior, then <> later. -============================================== +[source] +-------------------------------------------------- +{{#context}}{{.}}{{/context}} +-------------------------------------------------- + +For example, looping through search result hits may appear + +[source] +-------------------------------------------------- +triggering data was: +{{#context.hits}} - {{_source.message}} +{{/context.hits}} +-------------------------------------------------- [float] [[controlling-rules]] diff --git a/examples/controls_example/public/app.tsx b/examples/controls_example/public/app.tsx index 831635b8af4da..501d48af70656 100644 --- a/examples/controls_example/public/app.tsx +++ b/examples/controls_example/public/app.tsx @@ -9,23 +9,23 @@ import React from 'react'; import ReactDOM from 'react-dom'; -import type { DataView } from '@kbn/data-views-plugin/public'; import { AppMountParameters } from '@kbn/core/public'; import { KibanaPageTemplate } from '@kbn/shared-ux-page-kibana-template'; import { ControlsExampleStartDeps } from './plugin'; import { BasicReduxExample } from './basic_redux_example'; -interface Props { - dataView: DataView; -} - -const ControlsExamples = ({ dataView }: Props) => { +const ControlsExamples = ({ dataViewId }: { dataViewId?: string }) => { + const examples = dataViewId ? ( + <> + + + ) : ( +
{'Please install e-commerce sample data to run controls examples.'}
+ ); return ( - - - + {examples} ); }; @@ -35,8 +35,7 @@ export const renderApp = async ( { element }: AppMountParameters ) => { const dataViews = await data.dataViews.find('kibana_sample_data_ecommerce'); - if (dataViews.length > 0) { - ReactDOM.render(, element); - } + const dataViewId = dataViews.length > 0 ? dataViews[0].id : undefined; + ReactDOM.render(, element); return () => ReactDOM.unmountComponentAtNode(element); }; diff --git a/examples/controls_example/public/basic_redux_example.tsx b/examples/controls_example/public/basic_redux_example.tsx index bca34e61042f6..03edcd82b71a2 100644 --- a/examples/controls_example/public/basic_redux_example.tsx +++ b/examples/controls_example/public/basic_redux_example.tsx @@ -11,12 +11,10 @@ import React, { useMemo, useState } from 'react'; import { LazyControlGroupRenderer, ControlGroupContainer, - ControlGroupInput, useControlGroupContainerContext, ControlStyle, } from '@kbn/controls-plugin/public'; import { withSuspense } from '@kbn/presentation-util-plugin/public'; -import type { DataView } from '@kbn/data-views-plugin/public'; import { EuiButtonGroup, EuiFlexGroup, @@ -26,27 +24,24 @@ import { EuiText, EuiTitle, } from '@elastic/eui'; -import { getDefaultControlGroupInput } from '@kbn/controls-plugin/common'; -interface Props { - dataView: DataView; -} const ControlGroupRenderer = withSuspense(LazyControlGroupRenderer); -export const BasicReduxExample = ({ dataView }: Props) => { - const [myControlGroup, setControlGroup] = useState(); - const [currentControlStyle, setCurrentControlStyle] = useState('oneLine'); +export const BasicReduxExample = ({ dataViewId }: { dataViewId: string }) => { + const [controlGroup, setControlGroup] = useState(); const ControlGroupReduxWrapper = useMemo(() => { - if (myControlGroup) return myControlGroup.getReduxEmbeddableTools().Wrapper; - }, [myControlGroup]); + if (controlGroup) return controlGroup.getReduxEmbeddableTools().Wrapper; + }, [controlGroup]); const ButtonControls = () => { const { useEmbeddableDispatch, + useEmbeddableSelector: select, actions: { setControlStyle }, } = useControlGroupContainerContext(); const dispatch = useEmbeddableDispatch(); + const controlStyle = select((state) => state.explicitInput.controlStyle); return ( <> @@ -71,9 +66,8 @@ export const BasicReduxExample = ({ dataView }: Props) => { value: 'twoLine' as ControlStyle, }, ]} - idSelected={currentControlStyle} + idSelected={controlStyle} onChange={(id, value) => { - setCurrentControlStyle(value); dispatch(setControlStyle(value)); }} type="single" @@ -105,20 +99,17 @@ export const BasicReduxExample = ({ dataView }: Props) => { )} { - setControlGroup(controlGroup); + onLoadComplete={async (newControlGroup) => { + setControlGroup(newControlGroup); }} - getCreationOptions={async (controlGroupInputBuilder) => { - const initialInput: Partial = { - ...getDefaultControlGroupInput(), - defaultControlWidth: 'small', - }; - await controlGroupInputBuilder.addDataControlFromField(initialInput, { - dataViewId: dataView.id ?? 'kibana_sample_data_ecommerce', + getInitialInput={async (initialInput, builder) => { + await builder.addDataControlFromField(initialInput, { + dataViewId, fieldName: 'customer_first_name.keyword', + width: 'small', }); - await controlGroupInputBuilder.addDataControlFromField(initialInput, { - dataViewId: dataView.id ?? 'kibana_sample_data_ecommerce', + await builder.addDataControlFromField(initialInput, { + dataViewId, fieldName: 'customer_last_name.keyword', width: 'medium', grow: false, diff --git a/examples/guided_onboarding_example/.i18nrc.json b/examples/guided_onboarding_example/.i18nrc.json index f6b9143021db1..bc262e538ba9e 100755 --- a/examples/guided_onboarding_example/.i18nrc.json +++ b/examples/guided_onboarding_example/.i18nrc.json @@ -3,5 +3,5 @@ "paths": { "guidedOnboardingExample": "." }, - "translations": ["translations/ja-JP.json"] + "translations": [] } diff --git a/examples/guided_onboarding_example/public/components/main.tsx b/examples/guided_onboarding_example/public/components/main.tsx index 0b8099595d5cd..b2c7723d320e1 100644 --- a/examples/guided_onboarding_example/public/components/main.tsx +++ b/examples/guided_onboarding_example/public/components/main.tsx @@ -27,7 +27,6 @@ import { } from '@elastic/eui'; import type { GuideState, GuideStepIds, GuideId, GuideStep } from '@kbn/guided-onboarding'; import type { GuidedOnboardingPluginStart } from '@kbn/guided-onboarding-plugin/public'; -import { guidesConfig } from '@kbn/guided-onboarding-plugin/public'; interface MainProps { guidedOnboarding: GuidedOnboardingPluginStart; @@ -75,7 +74,15 @@ export const Main = (props: MainProps) => { }; const updateGuideState = async () => { - const selectedGuideConfig = guidesConfig[selectedGuide!]; + if (!selectedGuide) { + return; + } + + const selectedGuideConfig = await guidedOnboardingApi?.getGuideConfig(selectedGuide); + + if (!selectedGuideConfig) { + return; + } const selectedStepIndex = selectedGuideConfig.steps.findIndex( (step) => step.id === selectedStep! ); @@ -199,7 +206,7 @@ export const Main = (props: MainProps) => { - {(Object.keys(guidesConfig) as GuideId[]).map((guideId) => { + {(['search', 'security', 'observability', 'testGuide'] as GuideId[]).map((guideId) => { const guideState = guidesState?.find((guide) => guide.guideId === guideId); return ( diff --git a/examples/screenshot_mode_example/.i18nrc.json b/examples/screenshot_mode_example/.i18nrc.json index cce0f6b34fea2..520a0f81bd832 100644 --- a/examples/screenshot_mode_example/.i18nrc.json +++ b/examples/screenshot_mode_example/.i18nrc.json @@ -3,5 +3,5 @@ "paths": { "screenshotModeExample": "." }, - "translations": ["translations/ja-JP.json"] + "translations": [] } diff --git a/fleet_packages.json b/fleet_packages.json index 94d383ff9f6e6..3b33407ef4aeb 100644 --- a/fleet_packages.json +++ b/fleet_packages.json @@ -20,7 +20,7 @@ [ { "name": "apm", - "version": "8.6.0-preview-1663775281", + "version": "8.7.0-preview-1669303673", "forceAlignStackVersion": true }, { @@ -29,7 +29,7 @@ }, { "name": "endpoint", - "version": "8.5.0" + "version": "8.7.0-next" }, { "name": "fleet_server", @@ -37,6 +37,6 @@ }, { "name": "synthetics", - "version": "0.10.3" + "version": "0.11.4" } -] +] \ No newline at end of file diff --git a/package.json b/package.json index 9adb50c712137..2f5d7a6349f14 100644 --- a/package.json +++ b/package.json @@ -72,7 +72,6 @@ "yarn": "^1.22.19" }, "resolutions": { - "**/@tanstack/match-sorter-utils": "8.1.1", "**/@types/node": "16.11.41", "**/chokidar": "^3.5.3", "**/deepmerge": "^4.2.2", @@ -104,11 +103,11 @@ "@dnd-kit/utilities": "^2.0.0", "@elastic/apm-rum": "^5.12.0", "@elastic/apm-rum-react": "^1.4.2", - "@elastic/charts": "50.2.1", + "@elastic/charts": "51.1.1", "@elastic/datemath": "5.0.3", "@elastic/elasticsearch": "npm:@elastic/elasticsearch-canary@8.5.0-canary.1", "@elastic/ems-client": "8.3.3", - "@elastic/eui": "70.2.4", + "@elastic/eui": "70.4.0", "@elastic/filesaver": "1.1.2", "@elastic/node-crypto": "1.2.1", "@elastic/numeral": "^2.5.1", @@ -356,6 +355,7 @@ "@kbn/osquery-io-ts-types": "link:bazel-bin/packages/kbn-osquery-io-ts-types", "@kbn/plugin-discovery": "link:bazel-bin/packages/kbn-plugin-discovery", "@kbn/react-field": "link:bazel-bin/packages/kbn-react-field", + "@kbn/rison": "link:bazel-bin/packages/kbn-rison", "@kbn/rule-data-utils": "link:bazel-bin/packages/kbn-rule-data-utils", "@kbn/safer-lodash-set": "link:bazel-bin/packages/kbn-safer-lodash-set", "@kbn/securitysolution-autocomplete": "link:bazel-bin/packages/kbn-securitysolution-autocomplete", @@ -418,6 +418,7 @@ "@kbn/shared-ux-prompt-no-data-views": "link:bazel-bin/packages/shared-ux/prompt/no_data_views/impl", "@kbn/shared-ux-prompt-no-data-views-mocks": "link:bazel-bin/packages/shared-ux/prompt/no_data_views/mocks", "@kbn/shared-ux-prompt-no-data-views-types": "link:bazel-bin/packages/shared-ux/prompt/no_data_views/types", + "@kbn/shared-ux-prompt-not-found": "link:bazel-bin/packages/shared-ux/prompt/not_found", "@kbn/shared-ux-router-mocks": "link:bazel-bin/packages/shared-ux/router/mocks", "@kbn/shared-ux-services": "link:bazel-bin/packages/kbn-shared-ux-services", "@kbn/shared-ux-storybook": "link:bazel-bin/packages/kbn-shared-ux-storybook", @@ -451,8 +452,8 @@ "@opentelemetry/semantic-conventions": "^1.4.0", "@reduxjs/toolkit": "1.7.2", "@slack/webhook": "^5.0.4", - "@tanstack/react-query": "^4.13.4", - "@tanstack/react-query-devtools": "^4.13.4", + "@tanstack/react-query": "^4.18.0", + "@tanstack/react-query-devtools": "^4.18.0", "@turf/along": "6.0.1", "@turf/area": "6.0.1", "@turf/bbox": "6.0.1", @@ -611,9 +612,9 @@ "react-dom": "^17.0.2", "react-dropzone": "^4.2.9", "react-fast-compare": "^2.0.4", - "react-focus-on": "^3.6.0", + "react-focus-on": "^3.7.0", "react-grid-layout": "^1.3.4", - "react-hook-form": "^7.39.5", + "react-hook-form": "^7.39.7", "react-intl": "^2.8.0", "react-is": "^17.0.2", "react-markdown": "^6.0.3", @@ -902,7 +903,7 @@ "@types/nock": "^10.0.3", "@types/node": "16.11.41", "@types/node-fetch": "^2.6.0", - "@types/node-forge": "^1.3.0", + "@types/node-forge": "^1.3.1", "@types/nodemailer": "^6.4.0", "@types/normalize-path": "^3.0.0", "@types/object-hash": "^1.3.0", diff --git a/packages/BUILD.bazel b/packages/BUILD.bazel index 5d08cafdfd028..78e7a74fa0b32 100644 --- a/packages/BUILD.bazel +++ b/packages/BUILD.bazel @@ -276,6 +276,7 @@ filegroup( "//packages/kbn-react-field:build", "//packages/kbn-repo-source-classifier:build", "//packages/kbn-repo-source-classifier-cli:build", + "//packages/kbn-rison:build", "//packages/kbn-rule-data-utils:build", "//packages/kbn-safer-lodash-set:build", "//packages/kbn-securitysolution-autocomplete:build", @@ -366,6 +367,7 @@ filegroup( "//packages/shared-ux/prompt/no_data_views/impl:build", "//packages/shared-ux/prompt/no_data_views/mocks:build", "//packages/shared-ux/prompt/no_data_views/types:build", + "//packages/shared-ux/prompt/not_found:build", "//packages/shared-ux/router/impl:build", "//packages/shared-ux/router/mocks:build", "//packages/shared-ux/router/types:build", @@ -639,6 +641,7 @@ filegroup( "//packages/kbn-react-field:build_types", "//packages/kbn-repo-source-classifier:build_types", "//packages/kbn-repo-source-classifier-cli:build_types", + "//packages/kbn-rison:build_types", "//packages/kbn-rule-data-utils:build_types", "//packages/kbn-safer-lodash-set:build_types", "//packages/kbn-securitysolution-autocomplete:build_types", @@ -714,6 +717,7 @@ filegroup( "//packages/shared-ux/page/solution_nav:build_types", "//packages/shared-ux/prompt/no_data_views/impl:build_types", "//packages/shared-ux/prompt/no_data_views/mocks:build_types", + "//packages/shared-ux/prompt/not_found:build_types", "//packages/shared-ux/router/impl:build_types", "//packages/shared-ux/router/mocks:build_types", "//packages/shared-ux/storybook/config:build_types", diff --git a/packages/core/overlays/core-overlays-browser-internal/src/modal/__snapshots__/modal_service.test.tsx.snap b/packages/core/overlays/core-overlays-browser-internal/src/modal/__snapshots__/modal_service.test.tsx.snap index 2b5f564dfb3ee..7105dcea02869 100644 --- a/packages/core/overlays/core-overlays-browser-internal/src/modal/__snapshots__/modal_service.test.tsx.snap +++ b/packages/core/overlays/core-overlays-browser-internal/src/modal/__snapshots__/modal_service.test.tsx.snap @@ -94,12 +94,12 @@ exports[`ModalService openConfirm() renders a mountpoint confirm message 2`] = ` data-eui="EuiFocusTrap" >
+
+
+
+
+ , + "container":
+
+
+
+ +
+
+
+
, + "debug": [Function], + "findAllByAltText": [Function], + "findAllByDisplayValue": [Function], + "findAllByLabelText": [Function], + "findAllByPlaceholderText": [Function], + "findAllByRole": [Function], + "findAllByTestId": [Function], + "findAllByText": [Function], + "findAllByTitle": [Function], + "findByAltText": [Function], + "findByDisplayValue": [Function], + "findByLabelText": [Function], + "findByPlaceholderText": [Function], + "findByRole": [Function], + "findByTestId": [Function], + "findByText": [Function], + "findByTitle": [Function], + "getAllByAltText": [Function], + "getAllByDisplayValue": [Function], + "getAllByLabelText": [Function], + "getAllByPlaceholderText": [Function], + "getAllByRole": [Function], + "getAllByTestId": [Function], + "getAllByText": [Function], + "getAllByTitle": [Function], + "getByAltText": [Function], + "getByDisplayValue": [Function], + "getByLabelText": [Function], + "getByPlaceholderText": [Function], + "getByRole": [Function], + "getByTestId": [Function], + "getByText": [Function], + "getByTitle": [Function], + "queryAllByAltText": [Function], + "queryAllByDisplayValue": [Function], + "queryAllByLabelText": [Function], + "queryAllByPlaceholderText": [Function], + "queryAllByRole": [Function], + "queryAllByTestId": [Function], + "queryAllByText": [Function], + "queryAllByTitle": [Function], + "queryByAltText": [Function], + "queryByDisplayValue": [Function], + "queryByLabelText": [Function], + "queryByPlaceholderText": [Function], + "queryByRole": [Function], + "queryByTestId": [Function], + "queryByText": [Function], + "queryByTitle": [Function], + "rerender": [Function], + "unmount": [Function], +} +`; + exports[`HeaderMenu should render button icon disabled 1`] = ` Object { "asFragment": [Function], @@ -61,7 +176,7 @@ Object {

diff --git a/packages/kbn-securitysolution-exception-list-components/src/header_menu/header_menu.test.tsx b/packages/kbn-securitysolution-exception-list-components/src/header_menu/header_menu.test.tsx index 509c9e81b3d7d..a22bd79f5a984 100644 --- a/packages/kbn-securitysolution-exception-list-components/src/header_menu/header_menu.test.tsx +++ b/packages/kbn-securitysolution-exception-list-components/src/header_menu/header_menu.test.tsx @@ -13,6 +13,17 @@ import { getSecurityLinkAction } from '../mocks/security_link_component.mock'; describe('HeaderMenu', () => { it('should render button icon with default settings', () => { + const wrapper = render( + + ); + + expect(wrapper).toMatchSnapshot(); + + expect(wrapper.getByTestId('ButtonIcon')).toBeInTheDocument(); + expect(wrapper.queryByTestId('EmptyButton')).not.toBeInTheDocument(); + expect(wrapper.queryByTestId('MenuPanel')).not.toBeInTheDocument(); + }); + it('should not render icon', () => { const wrapper = render(); expect(wrapper).toMatchSnapshot(); @@ -23,7 +34,11 @@ describe('HeaderMenu', () => { }); it('should render button icon disabled', () => { const wrapper = render( - + ); fireEvent.click(wrapper.getByTestId('ButtonIcon')); @@ -103,7 +118,13 @@ describe('HeaderMenu', () => { it('should render custom Actions', () => { const customActions = getSecurityLinkAction('headerMenuTest'); const wrapper = render( - + ); expect(wrapper).toMatchSnapshot(); @@ -117,7 +138,12 @@ describe('HeaderMenu', () => { const customAction = [...actions]; customAction[0].onClick = onEdit; const wrapper = render( - + ); const headerMenu = wrapper.getByTestId('headerMenuItems'); const click = createEvent.click(headerMenu); diff --git a/packages/kbn-securitysolution-exception-list-components/src/header_menu/index.tsx b/packages/kbn-securitysolution-exception-list-components/src/header_menu/index.tsx index a8e44a03473c5..f042be34a8cee 100644 --- a/packages/kbn-securitysolution-exception-list-components/src/header_menu/index.tsx +++ b/packages/kbn-securitysolution-exception-list-components/src/header_menu/index.tsx @@ -18,7 +18,9 @@ import { PanelPaddingSize, PopoverAnchorPosition, } from '@elastic/eui'; + import { ButtonContentIconSide } from '@elastic/eui/src/components/button/_button_content_deprecated'; +import { css } from '@emotion/react'; export interface Action { key: string; @@ -27,6 +29,7 @@ export interface Action { disabled?: boolean; onClick: (e: React.MouseEvent) => void; } + interface HeaderMenuComponentProps { disableActions: boolean; actions: Action[] | ReactElement[] | null; @@ -40,6 +43,12 @@ interface HeaderMenuComponentProps { panelPaddingSize?: PanelPaddingSize; } +const popoverHeightStyle = css` + max-height: 300px; + height: 100%; + overflow-x: hidden; + overflow-y: auto; +`; const HeaderMenuComponent: FC = ({ text, dataTestSubj, @@ -47,7 +56,7 @@ const HeaderMenuComponent: FC = ({ disableActions, emptyButton, useCustomActions, - iconType = 'boxesHorizontal', + iconType, iconSide = 'left', anchorPosition = 'downCenter', panelPaddingSize = 's', @@ -84,7 +93,7 @@ const HeaderMenuComponent: FC = ({ = ({ @@ -112,6 +121,8 @@ const HeaderMenuComponent: FC = ({ > {!itemActions ? null : (
-
-

- Edit List Name -

-
+ Edit List Name +

-
-

- Edit list name -

-
+ Edit list name +
]; + const component = render(); + expect(component.text()).toContain('I am a button'); + }); +}); diff --git a/packages/shared-ux/prompt/not_found/src/not_found_prompt.tsx b/packages/shared-ux/prompt/not_found/src/not_found_prompt.tsx new file mode 100644 index 0000000000000..c6129cd0916d8 --- /dev/null +++ b/packages/shared-ux/prompt/not_found/src/not_found_prompt.tsx @@ -0,0 +1,76 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 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, { useEffect, useState, useCallback, useMemo } from 'react'; +import { + EuiButtonEmpty, + EuiEmptyPrompt, + EuiEmptyPromptProps, + EuiImage, + useEuiTheme, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; + +const NOT_FOUND_TITLE = i18n.translate('sharedUXPackages.prompt.errors.notFound.title', { + defaultMessage: 'Page not found', +}); + +const NOT_FOUND_BODY = i18n.translate('sharedUXPackages.prompt.errors.notFound.body', { + defaultMessage: + "Sorry, the page you're looking for can't be found. It might have been removed or renamed, or maybe it never existed at all.", +}); + +const NOT_FOUND_GO_BACK = i18n.translate('sharedUXPackages.prompt.errors.notFound.goBacklabel', { + defaultMessage: 'Go back', +}); + +interface NotFoundProps { + /** Array of buttons, links and other actions to show at the bottom of the `EuiEmptyPrompt`. Defaults to a "Back" button. */ + actions?: EuiEmptyPromptProps['actions']; +} + +/** + * Predefined `EuiEmptyPrompt` for 404 pages. + */ +export const NotFoundPrompt = ({ actions }: NotFoundProps) => { + const { colorMode } = useEuiTheme(); + const [imageSrc, setImageSrc] = useState(); + const goBack = useCallback(() => history.back(), []); + + const DEFAULT_ACTIONS = useMemo( + () => [ + + {NOT_FOUND_GO_BACK} + , + ], + [goBack] + ); + + useEffect(() => { + const loadImage = async () => { + const { default: imgSrc } = await import( + `./assets/404_astronaut_${colorMode.toLowerCase()}.png` + ); + setImageSrc(imgSrc); + }; + loadImage(); + }, [colorMode]); + + const icon = imageSrc ? : null; + + return ( + {NOT_FOUND_TITLE}} + body={NOT_FOUND_BODY} + actions={actions ?? DEFAULT_ACTIONS} + /> + ); +}; diff --git a/packages/shared-ux/prompt/not_found/tsconfig.json b/packages/shared-ux/prompt/not_found/tsconfig.json new file mode 100644 index 0000000000000..044531bb66de4 --- /dev/null +++ b/packages/shared-ux/prompt/not_found/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../../../../tsconfig.bazel.json", + "compilerOptions": { + "declaration": true, + "emitDeclarationOnly": true, + "outDir": "target_types", + "types": ["jest", "node", "react", "@kbn/ambient-ui-types"] + }, + "include": ["**/*.ts", "**/*.tsx"] +} diff --git a/scripts/read_jest_help.mjs b/scripts/read_jest_help.mjs new file mode 100644 index 0000000000000..0a3ce69c02c93 --- /dev/null +++ b/scripts/read_jest_help.mjs @@ -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 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 Fsp from 'fs/promises'; +import Path from 'path'; + +import { createFailError } from '@kbn/dev-cli-errors'; +import { run } from '@kbn/dev-cli-runner'; +import { REPO_ROOT } from '@kbn/utils'; + +const FLAGS_FILE = 'packages/kbn-test/src/jest/jest_flags.json'; + +function readStdin() { + return new Promise((resolve, reject) => { + let buffer = ''; + let timer = setTimeout(() => { + reject( + createFailError('you must pipe the output of `yarn jest --help` to this script', { + showHelp: true, + }) + ); + }, 1000); + + process.stdin + .on('data', (chunk) => { + if (timer) { + clearTimeout(timer); + timer = undefined; + } + + buffer += chunk; + }) + .on('end', () => resolve(buffer)) + .on('error', reject); + }); +} + +run( + async ({ log }) => { + const lines = (await readStdin()).split('\n'); + + /** @type {{ string: string[], boolean: string[], alias: Record }} */ + const flags = { string: [], boolean: [], alias: {} }; + + /** @type {string | undefined} */ + let currentFlag; + + for (const line of lines) { + const flagMatch = line.match(/^\s+(?:-(\w), )?--(\w+)\s+/); + const typeMatch = line.match(/\[(boolean|string|array|number|choices: [^\]]+)\]/); + + if (flagMatch && currentFlag) { + throw createFailError(`unable to determine type for flag [${currentFlag}]`); + } + + if (flagMatch) { + currentFlag = flagMatch[2]; + if (flagMatch[1]) { + flags.alias[flagMatch[1]] = flagMatch[2]; + } + } + + if (currentFlag && typeMatch) { + switch (typeMatch[1]) { + case 'string': + case 'array': + case 'number': + flags.string.push(currentFlag); + break; + case 'boolean': + flags.boolean.push(currentFlag); + break; + default: + if (typeMatch[1].startsWith('choices: ')) { + flags.string.push(currentFlag); + break; + } + + throw createFailError(`unexpected flag type [${typeMatch[1]}]`); + } + currentFlag = undefined; + } + } + + await Fsp.writeFile( + Path.resolve(REPO_ROOT, FLAGS_FILE), + JSON.stringify( + { + string: flags.string.sort(function (a, b) { + return a.localeCompare(b); + }), + boolean: flags.boolean.sort(function (a, b) { + return a.localeCompare(b); + }), + alias: Object.fromEntries( + Object.entries(flags.alias).sort(function (a, b) { + return a[0].localeCompare(b[0]); + }) + ), + }, + null, + 2 + ) + ); + + log.success('wrote jest flag info to', FLAGS_FILE); + log.warning('make sure you bootstrap to rebuild @kbn/test'); + }, + { + usage: `yarn jest --help | node scripts/read_jest_help.mjs`, + description: ` + Jest no longer exposes the ability to parse CLI flags externally, so we use this + script to read the help output and convert it into parameters we can pass to getopts() + which will parse the flags similar to how Jest does it. + + getopts() doesn't support things like enums, or number flags, but if we use the generated + config then it will at least interpret which flags are expected, which are invalid, and + allow us to determine the correct config path based on the provided path while passing + the rest of the args directly to jest. + `, + flags: { + allowUnexpected: true, + guessTypesForUnexpectedFlags: false, + }, + } +); diff --git a/src/core/server/integration_tests/saved_objects/migrations/check_registered_types.test.ts b/src/core/server/integration_tests/saved_objects/migrations/check_registered_types.test.ts index 6bfbeafb03972..ff50b46b9b3f3 100644 --- a/src/core/server/integration_tests/saved_objects/migrations/check_registered_types.test.ts +++ b/src/core/server/integration_tests/saved_objects/migrations/check_registered_types.test.ts @@ -124,7 +124,7 @@ describe('checking migration metadata changes on all registered SO types', () => "osquery-saved-query": "7b213b4b7a3e59350e99c50e8df9948662ed493a", "query": "4640ef356321500a678869f24117b7091a911cb6", "sample-data-telemetry": "8b10336d9efae6f3d5593c4cc89fb4abcdf84e04", - "search": "d26771bcf7cd271162aab3a610b75249631ef6b1", + "search": "c48f5ab5d94545780ea98de1bff9e39f17f3606b", "search-session": "ba383309da68a15be3765977f7a44c84f0ec7964", "search-telemetry": "beb3fc25488c753f2a6dcff1845d667558712b66", "security-rule": "e0dfdba5d66139d0300723b2e6672993cd4a11f3", @@ -136,7 +136,7 @@ describe('checking migration metadata changes on all registered SO types', () => "siem-ui-timeline-pinned-event": "e2697b38751506c7fce6e8b7207a830483dc4283", "space": "c4a0acce1bd4b9cce85154f2a350624a53111c59", "spaces-usage-stats": "922d3235bbf519e3fb3b260e27248b1df8249b79", - "synthetics-monitor": "d784b64a3def47d3f3d1f367df71ae41ef33cb3c", + "synthetics-monitor": "7c1e5a78fb3b88cc03b441d3bf3714d9967ab214", "synthetics-privates-locations": "dd00385f4a27ef062c3e57312eeb3799872fa4af", "tag": "39413f4578cc2128c9a0fda97d0acd1c8862c47a", "task": "ef53d0f070bd54957b8fe22fae3b1ff208913f76", diff --git a/src/dev/bazel/ts_project.bzl b/src/dev/bazel/ts_project.bzl index afd28fa513164..5c4009d46fd19 100644 --- a/src/dev/bazel/ts_project.bzl +++ b/src/dev/bazel/ts_project.bzl @@ -2,7 +2,13 @@ load("@npm//@bazel/typescript:index.bzl", _ts_project = "ts_project") -def ts_project(validate = False, **kwargs): +def contains(list, item): + for i in list: + if i == item: + return True + return False + +def ts_project(validate = False, deps = [], **kwargs): """A macro around the upstream ts_project rule. Args: @@ -10,7 +16,11 @@ def ts_project(validate = False, **kwargs): **kwargs: the rest """ + if contains(deps, "@npm//tslib") == False: + deps = deps + ["@npm//tslib"] + _ts_project( validate = validate, + deps = deps, **kwargs ) diff --git a/src/dev/build/tasks/bundle_fleet_packages.ts b/src/dev/build/tasks/bundle_fleet_packages.ts index 9d27b3d9ecc10..f7fe9ffc76573 100644 --- a/src/dev/build/tasks/bundle_fleet_packages.ts +++ b/src/dev/build/tasks/bundle_fleet_packages.ts @@ -70,8 +70,12 @@ export const BundleFleetPackages: Task = { const archivePath = `${fleetPackage.name}-${versionToWrite}.zip`; let archiveUrl = `${eprUrl}/epr/${fleetPackage.name}/${fleetPackage.name}-${fleetPackage.version}.zip`; - // Point APM and Endpoint packages to package storage v2 - if (fleetPackage.name === 'apm' || fleetPackage.name === 'endpoint') { + // Point APM, Endpoint and Synthetics packages to package storage v2 + if ( + fleetPackage.name === 'apm' || + fleetPackage.name === 'endpoint' || + fleetPackage.name === 'synthetics' + ) { archiveUrl = `${PACKAGE_STORAGE_V2_URL}/epr/${fleetPackage.name}/${fleetPackage.name}-${fleetPackage.version}.zip`; } diff --git a/src/dev/build/tasks/os_packages/docker_generator/templates/ironbank/Dockerfile b/src/dev/build/tasks/os_packages/docker_generator/templates/ironbank/Dockerfile index 4dc44d861f104..184d2cfb9414d 100644 --- a/src/dev/build/tasks/os_packages/docker_generator/templates/ironbank/Dockerfile +++ b/src/dev/build/tasks/os_packages/docker_generator/templates/ironbank/Dockerfile @@ -4,7 +4,7 @@ ################################################################################ ARG BASE_REGISTRY=registry1.dso.mil ARG BASE_IMAGE=redhat/ubi/ubi8 -ARG BASE_TAG=8.6 +ARG BASE_TAG=8.7 FROM ${BASE_REGISTRY}/${BASE_IMAGE}:${BASE_TAG} as prep_files diff --git a/src/dev/license_checker/config.ts b/src/dev/license_checker/config.ts index eaa968f3c94e8..eebb7e8eabe58 100644 --- a/src/dev/license_checker/config.ts +++ b/src/dev/license_checker/config.ts @@ -84,6 +84,6 @@ export const LICENSE_OVERRIDES = { 'jsts@1.6.2': ['Eclipse Distribution License - v 1.0'], // cf. https://github.com/bjornharrtell/jsts '@mapbox/jsonlint-lines-primitives@2.0.2': ['MIT'], // license in readme https://github.com/tmcw/jsonlint '@elastic/ems-client@8.3.3': ['Elastic License 2.0'], - '@elastic/eui@70.2.4': ['SSPL-1.0 OR Elastic License 2.0'], + '@elastic/eui@70.4.0': ['SSPL-1.0 OR Elastic License 2.0'], 'language-subtag-registry@0.3.21': ['CC-BY-4.0'], // retired ODC‑By license https://github.com/mattcg/language-subtag-registry }; diff --git a/src/dev/performance/run_performance_cli.ts b/src/dev/performance/run_performance_cli.ts index fea2b27cc2616..ac0e708dcee0a 100644 --- a/src/dev/performance/run_performance_cli.ts +++ b/src/dev/performance/run_performance_cli.ts @@ -90,10 +90,11 @@ run( await startEs(); await runWarmup(journey); await runTest(journey); - await procRunner.stop('es'); } catch (e) { log.error(e); failedJourneys.push(journey); + } finally { + await procRunner.stop('es'); } } diff --git a/src/plugins/chart_expressions/expression_partition_vis/common/expression_functions/__snapshots__/mosaic_vis_function.test.ts.snap b/src/plugins/chart_expressions/expression_partition_vis/common/expression_functions/__snapshots__/mosaic_vis_function.test.ts.snap index c00de511b8afb..f8b999c2bb764 100644 --- a/src/plugins/chart_expressions/expression_partition_vis/common/expression_functions/__snapshots__/mosaic_vis_function.test.ts.snap +++ b/src/plugins/chart_expressions/expression_partition_vis/common/expression_functions/__snapshots__/mosaic_vis_function.test.ts.snap @@ -103,6 +103,7 @@ Object { "splitRow": undefined, }, "labels": Object { + "colorOverrides": Object {}, "last_level": false, "percentDecimals": 2, "position": "default", diff --git a/src/plugins/chart_expressions/expression_partition_vis/common/expression_functions/__snapshots__/pie_vis_function.test.ts.snap b/src/plugins/chart_expressions/expression_partition_vis/common/expression_functions/__snapshots__/pie_vis_function.test.ts.snap index 65cd755d51a07..9e71fcec0c8fa 100644 --- a/src/plugins/chart_expressions/expression_partition_vis/common/expression_functions/__snapshots__/pie_vis_function.test.ts.snap +++ b/src/plugins/chart_expressions/expression_partition_vis/common/expression_functions/__snapshots__/pie_vis_function.test.ts.snap @@ -104,6 +104,7 @@ Object { "emptySizeRatio": 0.3, "isDonut": true, "labels": Object { + "colorOverrides": Object {}, "last_level": false, "percentDecimals": 2, "position": "default", @@ -244,6 +245,7 @@ Object { "emptySizeRatio": 0.3, "isDonut": false, "labels": Object { + "colorOverrides": Object {}, "last_level": false, "percentDecimals": 2, "position": "default", diff --git a/src/plugins/chart_expressions/expression_partition_vis/common/expression_functions/__snapshots__/treemap_vis_function.test.ts.snap b/src/plugins/chart_expressions/expression_partition_vis/common/expression_functions/__snapshots__/treemap_vis_function.test.ts.snap index 5388a47242fb4..891b217df37f0 100644 --- a/src/plugins/chart_expressions/expression_partition_vis/common/expression_functions/__snapshots__/treemap_vis_function.test.ts.snap +++ b/src/plugins/chart_expressions/expression_partition_vis/common/expression_functions/__snapshots__/treemap_vis_function.test.ts.snap @@ -103,6 +103,7 @@ Object { "splitRow": undefined, }, "labels": Object { + "colorOverrides": Object {}, "last_level": false, "percentDecimals": 2, "position": "default", diff --git a/src/plugins/chart_expressions/expression_partition_vis/common/expression_functions/__snapshots__/waffle_vis_function.test.ts.snap b/src/plugins/chart_expressions/expression_partition_vis/common/expression_functions/__snapshots__/waffle_vis_function.test.ts.snap index 180c3221240ce..50400b3839b57 100644 --- a/src/plugins/chart_expressions/expression_partition_vis/common/expression_functions/__snapshots__/waffle_vis_function.test.ts.snap +++ b/src/plugins/chart_expressions/expression_partition_vis/common/expression_functions/__snapshots__/waffle_vis_function.test.ts.snap @@ -77,6 +77,7 @@ Object { "splitRow": undefined, }, "labels": Object { + "colorOverrides": Object {}, "last_level": false, "percentDecimals": 2, "position": "default", diff --git a/src/plugins/chart_expressions/expression_partition_vis/common/expression_functions/mosaic_vis_function.test.ts b/src/plugins/chart_expressions/expression_partition_vis/common/expression_functions/mosaic_vis_function.test.ts index 46816ee1f34b8..fd2951a2f1fb6 100644 --- a/src/plugins/chart_expressions/expression_partition_vis/common/expression_functions/mosaic_vis_function.test.ts +++ b/src/plugins/chart_expressions/expression_partition_vis/common/expression_functions/mosaic_vis_function.test.ts @@ -52,6 +52,7 @@ describe('interpreter/functions#mosaicVis', () => { percentDecimals: 2, truncate: 100, last_level: false, + colorOverrides: {}, }, metric: { type: 'vis_dimension', diff --git a/src/plugins/chart_expressions/expression_partition_vis/common/expression_functions/partition_labels_function.ts b/src/plugins/chart_expressions/expression_partition_vis/common/expression_functions/partition_labels_function.ts index 48ecab49dc23b..fbd8fa84d3a20 100644 --- a/src/plugins/chart_expressions/expression_partition_vis/common/expression_functions/partition_labels_function.ts +++ b/src/plugins/chart_expressions/expression_partition_vis/common/expression_functions/partition_labels_function.ts @@ -89,6 +89,15 @@ export const partitionLabelsFunction = (): ExpressionFunctionDefinition< ), options: [ValueFormats.PERCENT, ValueFormats.VALUE], }, + colorOverrides: { + types: ['string'], + help: i18n.translate( + 'expressionPartitionVis.partitionLabels.function.args.colorOverrides.help', + { + defaultMessage: 'Defines specific colors for specific labels.', + } + ), + }, }, fn: (context, args) => { return { @@ -97,8 +106,9 @@ export const partitionLabelsFunction = (): ExpressionFunctionDefinition< position: args.position, percentDecimals: args.percentDecimals, values: args.values, - truncate: args.truncate, valuesFormat: args.valuesFormat, + colorOverrides: args.colorOverrides ? JSON.parse(args.colorOverrides) : {}, + truncate: args.truncate, last_level: args.last_level, }; }, diff --git a/src/plugins/chart_expressions/expression_partition_vis/common/expression_functions/pie_vis_function.test.ts b/src/plugins/chart_expressions/expression_partition_vis/common/expression_functions/pie_vis_function.test.ts index 0c222758d912a..dc975e9a92758 100644 --- a/src/plugins/chart_expressions/expression_partition_vis/common/expression_functions/pie_vis_function.test.ts +++ b/src/plugins/chart_expressions/expression_partition_vis/common/expression_functions/pie_vis_function.test.ts @@ -53,6 +53,7 @@ describe('interpreter/functions#pieVis', () => { percentDecimals: 2, truncate: 100, last_level: false, + colorOverrides: {}, }, metrics: [ { diff --git a/src/plugins/chart_expressions/expression_partition_vis/common/expression_functions/treemap_vis_function.test.ts b/src/plugins/chart_expressions/expression_partition_vis/common/expression_functions/treemap_vis_function.test.ts index e5bc4115c1461..edc8ec8b99100 100644 --- a/src/plugins/chart_expressions/expression_partition_vis/common/expression_functions/treemap_vis_function.test.ts +++ b/src/plugins/chart_expressions/expression_partition_vis/common/expression_functions/treemap_vis_function.test.ts @@ -53,6 +53,7 @@ describe('interpreter/functions#treemapVis', () => { percentDecimals: 2, truncate: 100, last_level: false, + colorOverrides: {}, }, metrics: [ { diff --git a/src/plugins/chart_expressions/expression_partition_vis/common/expression_functions/waffle_vis_function.test.ts b/src/plugins/chart_expressions/expression_partition_vis/common/expression_functions/waffle_vis_function.test.ts index 4c81f64428a74..606ff2c9b84c2 100644 --- a/src/plugins/chart_expressions/expression_partition_vis/common/expression_functions/waffle_vis_function.test.ts +++ b/src/plugins/chart_expressions/expression_partition_vis/common/expression_functions/waffle_vis_function.test.ts @@ -53,6 +53,7 @@ describe('interpreter/functions#waffleVis', () => { percentDecimals: 2, truncate: 100, last_level: false, + colorOverrides: {}, }, metrics: [ { diff --git a/src/plugins/chart_expressions/expression_partition_vis/common/types/expression_functions.ts b/src/plugins/chart_expressions/expression_partition_vis/common/types/expression_functions.ts index 30c5aba33ebf1..f5f2f0ef7f3cd 100644 --- a/src/plugins/chart_expressions/expression_partition_vis/common/types/expression_functions.ts +++ b/src/plugins/chart_expressions/expression_partition_vis/common/types/expression_functions.ts @@ -36,6 +36,7 @@ export interface PartitionLabelsArguments { values: boolean; valuesFormat: ValueFormats; percentDecimals: number; + colorOverrides?: string; /** @deprecated This field is deprecated and going to be removed in the futher release versions. */ truncate?: number | null; /** @deprecated This field is deprecated and going to be removed in the futher release versions. */ @@ -50,6 +51,7 @@ export type ExpressionValuePartitionLabels = ExpressionValueBoxed< values: boolean; valuesFormat: ValueFormats; percentDecimals: number; + colorOverrides: Record; /** @deprecated This field is deprecated and going to be removed in the futher release versions. */ truncate?: number | null; /** @deprecated This field is deprecated and going to be removed in the futher release versions. */ diff --git a/src/plugins/chart_expressions/expression_partition_vis/common/types/expression_renderers.ts b/src/plugins/chart_expressions/expression_partition_vis/common/types/expression_renderers.ts index 9584a810d7ca4..b5c9ad985dd49 100644 --- a/src/plugins/chart_expressions/expression_partition_vis/common/types/expression_renderers.ts +++ b/src/plugins/chart_expressions/expression_partition_vis/common/types/expression_renderers.ts @@ -41,6 +41,7 @@ export interface LabelsParams { values: boolean; valuesFormat: ValueFormats; percentDecimals: number; + colorOverrides: Record; /** @deprecated This field is deprecated and going to be removed in the futher release versions. */ truncate?: number | null; /** @deprecated This field is deprecated and going to be removed in the futher release versions. */ @@ -95,7 +96,8 @@ export interface TreemapVisConfig extends VisCommonConfig { nestedLegend: boolean; } -export interface MosaicVisConfig extends Omit { +export interface MosaicVisConfig + extends Omit { metric: ExpressionValueVisDimension | string; nestedLegend: boolean; } diff --git a/src/plugins/chart_expressions/expression_partition_vis/public/__stories__/shared/config.ts b/src/plugins/chart_expressions/expression_partition_vis/public/__stories__/shared/config.ts index aa4023006d486..544e5ea0ce593 100644 --- a/src/plugins/chart_expressions/expression_partition_vis/public/__stories__/shared/config.ts +++ b/src/plugins/chart_expressions/expression_partition_vis/public/__stories__/shared/config.ts @@ -34,6 +34,7 @@ export const config: RenderValue['visConfig'] = { truncate: 0, valuesFormat: ValueFormats.PERCENT, last_level: false, + colorOverrides: {}, }, dimensions: { metrics: [ diff --git a/src/plugins/chart_expressions/expression_partition_vis/public/components/partition_vis_component.tsx b/src/plugins/chart_expressions/expression_partition_vis/public/components/partition_vis_component.tsx index ed1789f2ae4a9..352f03f59e619 100644 --- a/src/plugins/chart_expressions/expression_partition_vis/public/components/partition_vis_component.tsx +++ b/src/plugins/chart_expressions/expression_partition_vis/public/components/partition_vis_component.tsx @@ -290,7 +290,7 @@ const PartitionVisComponent = (props: PartitionVisComponentProps) => { bucketColumns, visParams, visData, - props.uiState?.get('vis.colors', {}), + { ...props.uiState?.get('vis.colors', {}), ...props.visParams.labels.colorOverrides }, visData.rows, props.palettesRegistry, formatters, @@ -304,6 +304,7 @@ const PartitionVisComponent = (props: PartitionVisComponentProps) => { visParams, visData, props.uiState, + props.visParams.labels.colorOverrides, props.palettesRegistry, formatters, services.fieldFormats, diff --git a/src/plugins/chart_expressions/expression_partition_vis/public/mocks.ts b/src/plugins/chart_expressions/expression_partition_vis/public/mocks.ts index c125243f3a09a..89c61b6e7818c 100644 --- a/src/plugins/chart_expressions/expression_partition_vis/public/mocks.ts +++ b/src/plugins/chart_expressions/expression_partition_vis/public/mocks.ts @@ -282,6 +282,7 @@ export const createMockPartitionVisParams = (): PartitionVisParams => { values: true, valuesFormat: ValueFormats.PERCENT, percentDecimals: 2, + colorOverrides: {}, }, legendPosition: 'right', nestedLegend: false, diff --git a/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_color.ts b/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_color.ts index 9e55bec92fbaf..16c49f1c31889 100644 --- a/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_color.ts +++ b/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_color.ts @@ -9,10 +9,12 @@ import { ShapeTreeNode } from '@elastic/charts'; import { isEqual } from 'lodash'; import type { PaletteRegistry, SeriesLayer, PaletteOutput, PaletteDefinition } from '@kbn/coloring'; import type { FieldFormatsStart } from '@kbn/field-formats-plugin/public'; +import type { FieldFormat } from '@kbn/field-formats-plugin/common'; import { lightenColor } from '@kbn/charts-plugin/public'; import type { Datatable, DatatableRow } from '@kbn/expressions-plugin/public'; import { BucketColumns, ChartTypes, PartitionVisParams } from '../../../common/types'; import { DistinctSeries, getDistinctSeries } from '../get_distinct_series'; +import { getNodeLabel } from './get_node_labels'; const isTreemapOrMosaicChart = (shape: ChartTypes) => [ChartTypes.MOSAIC, ChartTypes.TREEMAP].includes(shape); @@ -109,15 +111,24 @@ const getDistinctColor = ( const createSeriesLayers = ( d: ShapeTreeNode, parentSeries: DistinctSeries['parentSeries'], - isSplitChart: boolean + isSplitChart: boolean, + formatters: Record, + formatter: FieldFormatsStart, + column: Partial ) => { const seriesLayers: SeriesLayer[] = []; let tempParent: typeof d | typeof d['parent'] = d; while (tempParent.parent && tempParent.depth > 0) { const seriesName = String(tempParent.parent.children[tempParent.sortIndex][0]); const isSplitParentLayer = isSplitChart && parentSeries.includes(seriesName); + const formattedName = getNodeLabel( + tempParent.parent.children[tempParent.sortIndex][0], + column, + formatters, + formatter.deserialize + ); seriesLayers.unshift({ - name: seriesName, + name: formattedName ?? seriesName, rankAtDepth: isSplitParentLayer ? parentSeries.findIndex((name) => name === seriesName) : tempParent.sortIndex, @@ -130,15 +141,13 @@ const createSeriesLayers = ( return seriesLayers; }; -const overrideColorForOldVisualization = ( +const overrideColors = ( seriesLayers: SeriesLayer[], overwriteColors: { [key: string]: string }, name: string ) => { let overwriteColor; - // this is for supporting old visualizations (created by vislib plugin) - // it seems that there for some aggs, the uiState saved from vislib is - // different than the es-charts handle it + if (overwriteColors.hasOwnProperty(name)) { overwriteColor = overwriteColors[name]; } @@ -166,7 +175,8 @@ export const getColor = ( syncColors: boolean, isDarkMode: boolean, formatter: FieldFormatsStart, - format?: BucketColumns['format'] + column: Partial, + formatters: Record ) => { const distinctSeries = getDistinctSeries(rows, columns); const { parentSeries } = distinctSeries; @@ -177,8 +187,8 @@ export const getColor = ( const defaultColor = isDarkMode ? 'rgba(0,0,0,0)' : 'rgba(255,255,255,0)'; let name = ''; - if (format) { - name = formatter.deserialize(format).convert(dataName) ?? ''; + if (column.format) { + name = formatter.deserialize(column.format).convert(dataName) ?? ''; } if (visParams.distinctColors) { @@ -196,11 +206,19 @@ export const getColor = ( ); } - const seriesLayers = createSeriesLayers(d, parentSeries, isSplitChart); + const seriesLayers = createSeriesLayers( + d, + parentSeries, + isSplitChart, + formatters, + formatter, + column + ); - const overwriteColor = overrideColorForOldVisualization(seriesLayers, overwriteColors, name); - if (overwriteColor) { - return lightenColor(overwriteColor, seriesLayers.length, columns.length); + const overriddenColor = overrideColors(seriesLayers, overwriteColors, name); + if (overriddenColor) { + // this is necessary for supporting some old visualizations that defined their own colors (created by vislib plugin) + return lightenColor(overriddenColor, seriesLayers.length, columns.length); } if (chartType === ChartTypes.MOSAIC && byDataPalette && seriesLayers[1]) { diff --git a/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_layers.test.ts b/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_layers.test.ts index cab4beda3f794..d96ada51ba47a 100644 --- a/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_layers.test.ts +++ b/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_layers.test.ts @@ -8,9 +8,11 @@ import { ShapeTreeNode } from '@elastic/charts'; import type { PaletteDefinition, SeriesLayer } from '@kbn/coloring'; import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; +import { fieldFormatsMock } from '@kbn/field-formats-plugin/common/mocks'; import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; import { getColor } from './get_color'; import { createMockVisData, createMockBucketColumns, createMockPieParams } from '../../mocks'; +import { generateFormatters } from '../formatters'; import { ChartTypes } from '../../../common/types'; const visData = createMockVisData(); @@ -22,6 +24,8 @@ interface RangeProps { gte: number; lt: number; } +const defaultFormatter = jest.fn((...args) => fieldFormatsMock.deserialize(...args)); +const formatters = generateFormatters(visData, defaultFormatter); dataMock.fieldFormats = { deserialize: jest.fn(() => ({ @@ -82,7 +86,9 @@ describe('computeColor', () => { { getColor: () => undefined }, false, false, - dataMock.fieldFormats + dataMock.fieldFormats, + visData.columns[0], + formatters ); expect(color).toEqual(colors[0]); }); @@ -111,7 +117,9 @@ describe('computeColor', () => { { getColor: () => undefined }, false, false, - dataMock.fieldFormats + dataMock.fieldFormats, + visData.columns[0], + formatters ); expect(color).toEqual('color3'); }); @@ -139,7 +147,9 @@ describe('computeColor', () => { { getColor: () => undefined }, false, false, - dataMock.fieldFormats + dataMock.fieldFormats, + visData.columns[0], + formatters ); expect(color).toEqual('#000028'); }); @@ -175,6 +185,15 @@ describe('computeColor', () => { ...visParams, distinctColors: true, }; + const column = { + ...visData.columns[0], + format: { + id: 'range', + params: { + id: 'number', + }, + }, + }; const color = getColor( ChartTypes.PIE, d, @@ -189,12 +208,8 @@ describe('computeColor', () => { false, false, dataMock.fieldFormats, - { - id: 'range', - params: { - id: 'number', - }, - } + column, + formatters ); expect(color).toEqual('#3F6833'); }); @@ -229,7 +244,9 @@ describe('computeColor', () => { undefined, true, false, - dataMock.fieldFormats + dataMock.fieldFormats, + visData.columns[0], + formatters ); expect(registry.get().getCategoricalColor).toHaveBeenCalledWith( [expect.objectContaining({ name: 'Second level 1' })], @@ -268,7 +285,9 @@ describe('computeColor', () => { undefined, true, false, - dataMock.fieldFormats + dataMock.fieldFormats, + visData.columns[0], + formatters ); expect(registry.get().getCategoricalColor).toHaveBeenCalledWith( [expect.objectContaining({ name: 'First level' })], diff --git a/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_layers.ts b/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_layers.ts index c8d7d1f30b4d5..646a0e4b45d2e 100644 --- a/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_layers.ts +++ b/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_layers.ts @@ -79,7 +79,8 @@ export const getLayers = ( syncColors, isDarkMode, formatter, - col.format + col, + formatters ), }, }; diff --git a/src/plugins/controls/public/control_group/control_group_input_builder.ts b/src/plugins/controls/public/control_group/control_group_input_builder.ts new file mode 100644 index 0000000000000..867eea1c65f9c --- /dev/null +++ b/src/plugins/controls/public/control_group/control_group_input_builder.ts @@ -0,0 +1,149 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import uuid from 'uuid'; +import { ControlPanelState } from '../../common'; +import { + DEFAULT_CONTROL_GROW, + DEFAULT_CONTROL_WIDTH, +} from '../../common/control_group/control_group_constants'; +import { RangeValue } from '../../common/range_slider/types'; +import { + ControlInput, + ControlWidth, + DataControlInput, + OPTIONS_LIST_CONTROL, + RANGE_SLIDER_CONTROL, + TIME_SLIDER_CONTROL, +} from '..'; +import { ControlGroupInput } from './types'; +import { getCompatibleControlType, getNextPanelOrder } from './embeddable/control_group_helpers'; + +export interface AddDataControlProps { + controlId?: string; + dataViewId: string; + fieldName: string; + grow?: boolean; + title?: string; + width?: ControlWidth; +} + +export type AddOptionsListControlProps = AddDataControlProps & { + selectedOptions?: string[]; +}; + +export type AddRangeSliderControlProps = AddDataControlProps & { + value?: RangeValue; +}; + +export const controlGroupInputBuilder = { + addDataControlFromField: async ( + initialInput: Partial, + controlProps: AddDataControlProps + ) => { + const { controlId, dataViewId, fieldName, title } = controlProps; + const panelId = controlId ? controlId : uuid.v4(); + initialInput.panels = { + ...initialInput.panels, + [panelId]: { + order: getNextPanelOrder(initialInput), + type: await getCompatibleControlType({ dataViewId, fieldName }), + grow: getGrow(initialInput, controlProps), + width: getWidth(initialInput, controlProps), + explicitInput: { + id: panelId, + dataViewId, + fieldName, + title: title ?? fieldName, + }, + } as ControlPanelState, + }; + }, + addOptionsListControl: ( + initialInput: Partial, + controlProps: AddOptionsListControlProps + ) => { + const { controlId, dataViewId, fieldName, selectedOptions, title } = controlProps; + const panelId = controlId ? controlId : uuid.v4(); + initialInput.panels = { + ...initialInput.panels, + [panelId]: { + order: getNextPanelOrder(initialInput), + type: OPTIONS_LIST_CONTROL, + grow: getGrow(initialInput, controlProps), + width: getWidth(initialInput, controlProps), + explicitInput: { + id: panelId, + dataViewId, + fieldName, + selectedOptions, + title: title ?? fieldName, + }, + } as ControlPanelState, + }; + }, + addRangeSliderControl: ( + initialInput: Partial, + controlProps: AddRangeSliderControlProps + ) => { + const { controlId, dataViewId, fieldName, title, value } = controlProps; + const panelId = controlId ? controlId : uuid.v4(); + initialInput.panels = { + ...initialInput.panels, + [panelId]: { + order: getNextPanelOrder(initialInput), + type: RANGE_SLIDER_CONTROL, + grow: getGrow(initialInput, controlProps), + width: getWidth(initialInput, controlProps), + explicitInput: { + id: panelId, + dataViewId, + fieldName, + title: title ?? fieldName, + value: value ? value : ['', ''], + }, + } as ControlPanelState, + }; + }, + addTimeSliderControl: (initialInput: Partial) => { + const panelId = uuid.v4(); + initialInput.panels = { + ...initialInput.panels, + [panelId]: { + order: getNextPanelOrder(initialInput), + type: TIME_SLIDER_CONTROL, + grow: true, + width: 'large', + explicitInput: { + id: panelId, + title: 'timeslider', + }, + } as ControlPanelState, + }; + }, +}; + +function getGrow(initialInput: Partial, controlProps: AddDataControlProps) { + if (typeof controlProps.grow === 'boolean') { + return controlProps.grow; + } + + return typeof initialInput.defaultControlGrow === 'boolean' + ? initialInput.defaultControlGrow + : DEFAULT_CONTROL_GROW; +} + +function getWidth(initialInput: Partial, controlProps: AddDataControlProps) { + if (controlProps.width) { + return controlProps.width; + } + + return initialInput.defaultControlWidth + ? initialInput.defaultControlWidth + : DEFAULT_CONTROL_WIDTH; +} diff --git a/src/plugins/controls/public/control_group/control_group_renderer.tsx b/src/plugins/controls/public/control_group/control_group_renderer.tsx index 57245e23b2a1a..fc5852cff18e8 100644 --- a/src/plugins/controls/public/control_group/control_group_renderer.tsx +++ b/src/plugins/controls/public/control_group/control_group_renderer.tsx @@ -14,7 +14,7 @@ import { IEmbeddable } from '@kbn/embeddable-plugin/public'; import { useReduxContainerContext } from '@kbn/presentation-util-plugin/public'; import { pluginServices } from '../services'; -import { ControlPanelState, getDefaultControlGroupInput } from '../../common'; +import { getDefaultControlGroupInput } from '../../common'; import { ControlGroupInput, ControlGroupOutput, @@ -22,60 +22,29 @@ import { CONTROL_GROUP_TYPE, } from './types'; import { ControlGroupContainer } from './embeddable/control_group_container'; -import { DataControlInput } from '../types'; -import { getCompatibleControlType, getNextPanelOrder } from './embeddable/control_group_helpers'; import { controlGroupReducers } from './state/control_group_reducers'; - -const ControlGroupInputBuilder = { - addDataControlFromField: async ( - initialInput: Partial, - newPanelInput: { - title?: string; - panelId?: string; - fieldName: string; - dataViewId: string; - } & Partial - ) => { - const { defaultControlGrow, defaultControlWidth } = getDefaultControlGroupInput(); - const controlGrow = initialInput.defaultControlGrow ?? defaultControlGrow; - const controlWidth = initialInput.defaultControlWidth ?? defaultControlWidth; - - const { panelId, dataViewId, fieldName, title, grow, width } = newPanelInput; - const newPanelId = panelId || uuid.v4(); - const nextOrder = getNextPanelOrder(initialInput); - const controlType = await getCompatibleControlType({ dataViewId, fieldName }); - - initialInput.panels = { - ...initialInput.panels, - [newPanelId]: { - order: nextOrder, - type: controlType, - grow: grow ?? controlGrow, - width: width ?? controlWidth, - explicitInput: { id: newPanelId, dataViewId, fieldName, title: title ?? fieldName }, - } as ControlPanelState, - }; - }, -}; +import { controlGroupInputBuilder } from './control_group_input_builder'; export interface ControlGroupRendererProps { - onEmbeddableLoad: (controlGroupContainer: ControlGroupContainer) => void; - getCreationOptions: ( - builder: typeof ControlGroupInputBuilder + onLoadComplete?: (controlGroup: ControlGroupContainer) => void; + getInitialInput: ( + initialInput: Partial, + builder: typeof controlGroupInputBuilder ) => Promise>; } export const ControlGroupRenderer = ({ - onEmbeddableLoad, - getCreationOptions, + onLoadComplete, + getInitialInput, }: ControlGroupRendererProps) => { - const controlsRoot = useRef(null); - const [controlGroupContainer, setControlGroupContainer] = useState(); + const controlGroupRef = useRef(null); + const [controlGroup, setControlGroup] = useState(); const id = useMemo(() => uuid.v4(), []); /** * Use Lifecycles to load initial control group container */ useLifecycles( + // onMount () => { const { embeddable } = pluginServices.getServices(); (async () => { @@ -84,25 +53,28 @@ export const ControlGroupRenderer = ({ ControlGroupOutput, IEmbeddable >(CONTROL_GROUP_TYPE); - const container = (await factory?.create({ + const newControlGroup = (await factory?.create({ id, ...getDefaultControlGroupInput(), - ...(await getCreationOptions(ControlGroupInputBuilder)), + ...(await getInitialInput(getDefaultControlGroupInput(), controlGroupInputBuilder)), })) as ControlGroupContainer; - if (controlsRoot.current) { - container.render(controlsRoot.current); + if (controlGroupRef.current) { + newControlGroup.render(controlGroupRef.current); + } + setControlGroup(newControlGroup); + if (onLoadComplete) { + onLoadComplete(newControlGroup); } - setControlGroupContainer(container); - onEmbeddableLoad(container); })(); }, + // onUnmount () => { - controlGroupContainer?.destroy(); + controlGroup?.destroy(); } ); - return
; + return
; }; export const useControlGroupContainerContext = () => diff --git a/src/plugins/controls/public/control_group/index.ts b/src/plugins/controls/public/control_group/index.ts index b55d63134439b..1967a8074beab 100644 --- a/src/plugins/controls/public/control_group/index.ts +++ b/src/plugins/controls/public/control_group/index.ts @@ -14,6 +14,12 @@ export type { ControlGroupInput, ControlGroupOutput } from './types'; export { CONTROL_GROUP_TYPE } from './types'; export { ControlGroupContainerFactory } from './embeddable/control_group_container_factory'; +export { + type AddDataControlProps, + type AddOptionsListControlProps, + controlGroupInputBuilder, +} from './control_group_input_builder'; + export { type ControlGroupRendererProps, useControlGroupContainerContext, diff --git a/src/plugins/controls/public/index.ts b/src/plugins/controls/public/index.ts index 2b6732335472a..29c2af9ad46f5 100644 --- a/src/plugins/controls/public/index.ts +++ b/src/plugins/controls/public/index.ts @@ -22,6 +22,7 @@ export type { ControlStyle, ParentIgnoreSettings, ControlInput, + DataControlInput, } from '../common/types'; export { @@ -32,9 +33,12 @@ export { } from '../common'; export { + type AddDataControlProps, + type AddOptionsListControlProps, type ControlGroupContainer, ControlGroupContainerFactory, type ControlGroupInput, + controlGroupInputBuilder, type ControlGroupOutput, } from './control_group'; diff --git a/src/plugins/dashboard/tsconfig.json b/src/plugins/dashboard/tsconfig.json index 96a2757909c12..390fc6f6a0a5e 100644 --- a/src/plugins/dashboard/tsconfig.json +++ b/src/plugins/dashboard/tsconfig.json @@ -26,7 +26,6 @@ { "path": "../screenshot_mode/tsconfig.json" }, { "path": "../ui_actions/tsconfig.json" }, { "path": "../charts/tsconfig.json" }, - { "path": "../discover/tsconfig.json" }, { "path": "../visualizations/tsconfig.json" }, { "path": "../../../x-pack/plugins/spaces/tsconfig.json" } ] diff --git a/src/plugins/data/common/search/expressions/esaggs/request_handler.test.ts b/src/plugins/data/common/search/expressions/esaggs/request_handler.test.ts index e0fbb10c05e3f..e0555fbd24076 100644 --- a/src/plugins/data/common/search/expressions/esaggs/request_handler.test.ts +++ b/src/plugins/data/common/search/expressions/esaggs/request_handler.test.ts @@ -143,6 +143,26 @@ describe('esaggs expression function - public', () => { }); }); + test('calls searchSource.fetch with custom inspector params', async () => { + await handleRequest({ + ...mockParams, + title: 'MyTitle', + description: 'MyDescription', + }).toPromise(); + const searchSource = await mockParams.searchSourceService.create(); + + expect(searchSource.fetch$).toHaveBeenCalledWith({ + abortSignal: mockParams.abortSignal, + sessionId: mockParams.searchSessionId, + inspector: { + title: 'MyTitle', + description: 'MyDescription', + adapter: undefined, + }, + disableShardFailureWarning: false, + }); + }); + test('tabifies response data', async () => { await handleRequest(mockParams).toPromise(); expect(tabifyAggResponse).toHaveBeenCalledWith( diff --git a/src/plugins/data/common/search/expressions/esaggs/request_handler.ts b/src/plugins/data/common/search/expressions/esaggs/request_handler.ts index 03512bcd2e270..1497dd9aa1a37 100644 --- a/src/plugins/data/common/search/expressions/esaggs/request_handler.ts +++ b/src/plugins/data/common/search/expressions/esaggs/request_handler.ts @@ -33,6 +33,8 @@ export interface RequestHandlerParams { disableShardWarnings?: boolean; getNow?: () => Date; executionContext?: KibanaExecutionContext; + title?: string; + description?: string; } export const handleRequest = ({ @@ -49,6 +51,8 @@ export const handleRequest = ({ disableShardWarnings, getNow, executionContext, + title, + description, }: RequestHandlerParams) => { return defer(async () => { const forceNow = getNow?.(); @@ -117,13 +121,17 @@ export const handleRequest = ({ sessionId: searchSessionId, inspector: { adapter: inspectorAdapters.requests, - title: i18n.translate('data.functions.esaggs.inspector.dataRequest.title', { - defaultMessage: 'Data', - }), - description: i18n.translate('data.functions.esaggs.inspector.dataRequest.description', { - defaultMessage: - 'This request queries Elasticsearch to fetch the data for the visualization.', - }), + title: + title ?? + i18n.translate('data.functions.esaggs.inspector.dataRequest.title', { + defaultMessage: 'Data', + }), + description: + description ?? + i18n.translate('data.functions.esaggs.inspector.dataRequest.description', { + defaultMessage: + 'This request queries Elasticsearch to fetch the data for the visualization.', + }), }, executionContext, }) diff --git a/src/plugins/data/server/ui_settings.ts b/src/plugins/data/server/ui_settings.ts index 8d666590b3d30..cfd664e2e53c8 100644 --- a/src/plugins/data/server/ui_settings.ts +++ b/src/plugins/data/server/ui_settings.ts @@ -324,8 +324,8 @@ export function getUiSettings( defaultMessage: 'Time filter refresh interval', }), value: `{ - "pause": false, - "value": 0 + "pause": true, + "value": 60000 }`, type: 'json', description: i18n.translate('data.advancedSettings.timepicker.refreshIntervalDefaultsText', { diff --git a/src/plugins/data_view_editor/public/data_view_editor_service.ts b/src/plugins/data_view_editor/public/data_view_editor_service.ts index 3589f7d491904..4bfd04c912a6c 100644 --- a/src/plugins/data_view_editor/public/data_view_editor_service.ts +++ b/src/plugins/data_view_editor/public/data_view_editor_service.ts @@ -15,6 +15,8 @@ import { from, Observable, Subscription, + map, + distinctUntilChanged, } from 'rxjs'; import { @@ -48,6 +50,29 @@ export interface DataViewEditorServiceConstructorArgs { }; } +interface DataViewEditorState { + matchedIndices: MatchedIndicesSet; + rollupIndicesCaps: RollupIndicesCapsResponse; + isLoadingSourcesInternal: boolean; + loadingTimestampFields: boolean; + timestampFieldOptions: TimestampOption[]; + rollupIndexName?: string | null; +} + +const defaultDataViewEditorState: DataViewEditorState = { + matchedIndices: { ...matchedIndiciesDefault }, + rollupIndicesCaps: {}, + isLoadingSourcesInternal: false, + loadingTimestampFields: false, + timestampFieldOptions: [], + rollupIndexName: undefined, +}; + +export const stateSelectorFactory = + (state$: Observable) => + (selector: (state: S) => R, equalityFn?: (arg0: R, arg1: R) => boolean) => + state$.pipe(map(selector), distinctUntilChanged(equalityFn)); + export class DataViewEditorService { constructor({ services: { http, dataViews }, @@ -68,13 +93,19 @@ export class DataViewEditorService { this.rollupCapsResponse = this.getRollupIndexCaps(); this.dataViewNames$ = from(this.loadDataViewNames(initialName)); + this.state$ = new BehaviorSubject({ + ...defaultDataViewEditorState, + }); + + const stateSelector = stateSelectorFactory(this.state$); + // public observables - this.matchedIndices$ = this.matchedIndicesInternal$.asObservable(); - this.rollupIndicesCaps$ = this.rollupIndicesCapsInternal$.asObservable(); - this.isLoadingSources$ = this.isLoadingSourcesInternal$.asObservable(); - this.loadingTimestampFields$ = this.loadingTimestampFieldsInternal$.asObservable(); - this.timestampFieldOptions$ = this.timestampFieldOptionsInternal$.asObservable(); - this.rollupIndex$ = this.rollupIndexInternal$.asObservable(); + this.matchedIndices$ = stateSelector((state) => state.matchedIndices); + this.rollupIndicesCaps$ = stateSelector((state) => state.rollupIndicesCaps); + this.isLoadingSources$ = stateSelector((state) => state.isLoadingSourcesInternal); + this.loadingTimestampFields$ = stateSelector((state) => state.loadingTimestampFields); + this.timestampFieldOptions$ = stateSelector((state) => state.timestampFieldOptions); + this.rollupIndex$ = stateSelector((state) => state.rollupIndexName); // when list of matched indices is updated always update timestamp fields this.loadTimestampFieldsSub = this.matchedIndices$.subscribe(() => this.loadTimestampFields()); @@ -99,6 +130,7 @@ export class DataViewEditorService { private type = INDEX_PATTERN_TYPE.DEFAULT; // state + private state = { ...defaultDataViewEditorState }; private indexPattern = ''; private allowHidden = false; @@ -109,24 +141,19 @@ export class DataViewEditorService { private matchedIndicesForProviderSub: Subscription; private rollupIndexForProviderSub: Subscription; + private state$: BehaviorSubject; + // used for validating rollup data views - must match one and only one data view - private rollupIndicesCapsInternal$ = new BehaviorSubject({}); rollupIndicesCaps$: Observable; - private isLoadingSourcesInternal$ = new BehaviorSubject(false); isLoadingSources$: Observable; - - private loadingTimestampFieldsInternal$ = new BehaviorSubject(false); loadingTimestampFields$: Observable; - private timestampFieldOptionsInternal$ = new Subject(); timestampFieldOptions$: Observable; // current matched rollup index - private rollupIndexInternal$ = new BehaviorSubject(undefined); rollupIndex$: Observable; // alernates between value and undefined so validation can treat new value as thought its a promise private rollupIndexForProvider$ = new Subject(); - private matchedIndicesInternal$ = new BehaviorSubject(matchedIndiciesDefault); matchedIndices$: Observable; // alernates between value and undefined so validation can treat new value as thought its a promise @@ -137,15 +164,20 @@ export class DataViewEditorService { private currentLoadingTimestampFields = 0; private currentLoadingMatchedIndices = 0; + private updateState = (newState: Partial) => { + this.state = { ...this.state, ...newState }; + this.state$.next(this.state); + }; + private getRollupIndexCaps = async () => { - let response: RollupIndicesCapsResponse = {}; + let rollupIndicesCaps: RollupIndicesCapsResponse = {}; try { - response = await this.http.get('/api/rollup/indices'); + rollupIndicesCaps = await this.http.get('/api/rollup/indices'); } catch (e) { // Silently swallow failure responses such as expired trials } - this.rollupIndicesCapsInternal$.next(response); - return response; + this.updateState({ rollupIndicesCaps }); + return rollupIndicesCaps; }; private getIsRollupIndex = async () => { @@ -165,7 +197,7 @@ export class DataViewEditorService { const indexRequests = []; let newRollupIndexName: string | undefined | null; - this.loadingTimestampFieldsInternal$.next(true); + this.updateState({ loadingTimestampFields: true }); if (query?.endsWith('*')) { const exactMatchedQuery = this.getIndicesCached({ @@ -194,24 +226,19 @@ export class DataViewEditorService { indexRequests )) as MatchedItem[][]; - const matchedIndicesResult = getMatchedIndices( - allSources, - partialMatched, - exactMatched, - allowHidden - ); + const matchedIndices = getMatchedIndices(allSources, partialMatched, exactMatched, allowHidden); // verify we're looking at the current result if (currentLoadingMatchedIndicesIdx === this.currentLoadingMatchedIndices) { if (type === INDEX_PATTERN_TYPE.ROLLUP) { const rollupIndices = exactMatched.filter((index) => isRollupIndex(index.name)); newRollupIndexName = rollupIndices.length === 1 ? rollupIndices[0].name : null; - this.rollupIndexInternal$.next(newRollupIndexName); + this.updateState({ rollupIndexName: newRollupIndexName }); } else { - this.rollupIndexInternal$.next(null); + this.updateState({ rollupIndexName: null }); } - this.matchedIndicesInternal$.next(matchedIndicesResult); + this.updateState({ matchedIndices }); } }; @@ -237,7 +264,7 @@ export class DataViewEditorService { }); await this.loadMatchedIndices(this.indexPattern, this.allowHidden, allSrcs, this.type); - this.isLoadingSourcesInternal$.next(false); + this.updateState({ isLoadingSourcesInternal: false }); }; private loadDataViewNames = async (initialName?: string) => { @@ -297,9 +324,8 @@ export class DataViewEditorService { }; private loadTimestampFields = async () => { - if (this.matchedIndicesInternal$.getValue().exactMatchedIndices.length === 0) { - this.timestampFieldOptionsInternal$.next([]); - this.loadingTimestampFieldsInternal$.next(false); + if (this.state.matchedIndices.exactMatchedIndices.length === 0) { + this.updateState({ timestampFieldOptions: [], loadingTimestampFields: false }); return; } const currentLoadingTimestampFieldsIdx = ++this.currentLoadingTimestampFields; @@ -309,19 +335,18 @@ export class DataViewEditorService { }; if (this.type === INDEX_PATTERN_TYPE.ROLLUP) { getFieldsOptions.type = INDEX_PATTERN_TYPE.ROLLUP; - getFieldsOptions.rollupIndex = this.rollupIndexInternal$.getValue() || ''; + getFieldsOptions.rollupIndex = this.state.rollupIndexName || ''; } - let timestampOptions: TimestampOption[] = []; + let timestampFieldOptions: TimestampOption[] = []; try { - timestampOptions = await this.getTimestampOptionsForWildcardCached( + timestampFieldOptions = await this.getTimestampOptionsForWildcardCached( getFieldsOptions, this.requireTimestampField ); } finally { if (currentLoadingTimestampFieldsIdx === this.currentLoadingTimestampFields) { - this.timestampFieldOptionsInternal$.next(timestampOptions); - this.loadingTimestampFieldsInternal$.next(false); + this.updateState({ timestampFieldOptions, loadingTimestampFields: false }); } } }; diff --git a/src/plugins/discover/kibana.json b/src/plugins/discover/kibana.json index e9d78d844a6e0..238de02475307 100644 --- a/src/plugins/discover/kibana.json +++ b/src/plugins/discover/kibana.json @@ -29,7 +29,8 @@ "usageCollection", "spaces", "triggersActionsUi", - "savedObjectsTaggingOss" + "savedObjectsTaggingOss", + "lens" ], "requiredBundles": ["kibanaUtils", "kibanaReact", "unifiedSearch", "savedSearch"], "extraPublicDirs": ["common"], diff --git a/src/plugins/discover/public/__mocks__/data_view_with_timefield.ts b/src/plugins/discover/public/__mocks__/data_view_with_timefield.ts index 803fb7c6f70db..a481c648aad20 100644 --- a/src/plugins/discover/public/__mocks__/data_view_with_timefield.ts +++ b/src/plugins/discover/public/__mocks__/data_view_with_timefield.ts @@ -18,6 +18,7 @@ const fields = [ }, { name: 'timestamp', + displayName: 'timestamp', type: 'date', scripted: false, filterable: true, @@ -26,12 +27,14 @@ const fields = [ }, { name: 'message', + displayName: 'message', type: 'string', scripted: false, filterable: false, }, { name: 'extension', + displayName: 'extension', type: 'string', scripted: false, filterable: true, @@ -39,6 +42,7 @@ const fields = [ }, { name: 'bytes', + displayName: 'bytes', type: 'number', scripted: false, filterable: true, @@ -46,6 +50,7 @@ const fields = [ }, { name: 'scripted', + displayName: 'scripted', type: 'number', scripted: true, filterable: false, diff --git a/src/plugins/discover/public/__mocks__/data_views.ts b/src/plugins/discover/public/__mocks__/data_views.ts index 7832a4c0f4e39..1bc8d791d53fb 100644 --- a/src/plugins/discover/public/__mocks__/data_views.ts +++ b/src/plugins/discover/public/__mocks__/data_views.ts @@ -11,22 +11,27 @@ import { dataViewMock } from './data_view'; import { dataViewComplexMock } from './data_view_complex'; import { dataViewWithTimefieldMock } from './data_view_with_timefield'; -export const dataViewsMock = { - getCache: async () => { - return [dataViewMock]; - }, - get: async (id: string) => { - if (id === 'the-data-view-id') { - return Promise.resolve(dataViewMock); - } else if (id === 'invalid-data-view-id') { - return Promise.reject('Invald'); - } - }, - updateSavedObject: jest.fn(), - getIdsWithTitle: jest.fn(() => { - return Promise.resolve([dataViewMock, dataViewComplexMock, dataViewWithTimefieldMock]); - }), - createFilter: jest.fn(), - create: jest.fn(), - clearInstanceCache: jest.fn(), -} as unknown as jest.Mocked; +export function createDiscoverDataViewsMock() { + return { + getCache: async () => { + return [dataViewMock]; + }, + get: async (id: string) => { + if (id === 'the-data-view-id') { + return Promise.resolve(dataViewMock); + } else if (id === 'invalid-data-view-id') { + return Promise.reject('Invald'); + } + }, + updateSavedObject: jest.fn(), + getIdsWithTitle: jest.fn(() => { + return Promise.resolve([dataViewMock, dataViewComplexMock, dataViewWithTimefieldMock]); + }), + createFilter: jest.fn(), + create: jest.fn(), + clearInstanceCache: jest.fn(), + getFieldsForIndexPattern: jest.fn((dataView) => dataView.fields), + } as unknown as jest.Mocked; +} + +export const dataViewsMock = createDiscoverDataViewsMock(); diff --git a/src/plugins/discover/public/__mocks__/search_session.ts b/src/plugins/discover/public/__mocks__/search_session.ts index 9763ff7089e0a..abcd5e92a1cbd 100644 --- a/src/plugins/discover/public/__mocks__/search_session.ts +++ b/src/plugins/discover/public/__mocks__/search_session.ts @@ -10,11 +10,12 @@ import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; import { DataPublicPluginStart } from '@kbn/data-plugin/public'; import { DiscoverSearchSessionManager } from '../application/main/services/discover_search_session'; -export function createSearchSessionMock() { - const history = createMemoryHistory(); - const session = dataPluginMock.createStartContract().search.session as jest.Mocked< +export function createSearchSessionMock( + session = dataPluginMock.createStartContract().search.session as jest.Mocked< DataPublicPluginStart['search']['session'] - >; + > +) { + const history = createMemoryHistory(); const searchSessionManager = new DiscoverSearchSessionManager({ history, session, diff --git a/src/plugins/discover/public/__mocks__/services.ts b/src/plugins/discover/public/__mocks__/services.ts index eaae356c03c1a..d21bc4fc115b3 100644 --- a/src/plugins/discover/public/__mocks__/services.ts +++ b/src/plugins/discover/public/__mocks__/services.ts @@ -5,6 +5,7 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ +import { Observable, of } from 'rxjs'; import { EUI_CHARTS_THEME_LIGHT } from '@elastic/eui/dist/eui_charts_theme'; import { DiscoverServices } from '../build_services'; import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; @@ -20,117 +21,138 @@ import { SORT_DEFAULT_ORDER_SETTING, HIDE_ANNOUNCEMENTS, } from '../../common'; -import { UI_SETTINGS } from '@kbn/data-plugin/public'; +import { UI_SETTINGS, calculateBounds } from '@kbn/data-plugin/public'; import { TopNavMenu } from '@kbn/navigation-plugin/public'; import { FORMATS_UI_SETTINGS } from '@kbn/field-formats-plugin/common'; -import { LocalStorageMock } from './local_storage_mock'; +import { chartPluginMock } from '@kbn/charts-plugin/public/mocks'; import { fieldFormatsMock } from '@kbn/field-formats-plugin/common/mocks'; -import { dataViewsMock } from './data_views'; -import { Observable, of } from 'rxjs'; -const dataPlugin = dataPluginMock.createStartContract(); -const expressionsPlugin = expressionsPluginMock.createStartContract(); +import { LocalStorageMock } from './local_storage_mock'; +import { createDiscoverDataViewsMock } from './data_views'; + +export function createDiscoverServicesMock(): DiscoverServices { + const dataPlugin = dataPluginMock.createStartContract(); + const expressionsPlugin = expressionsPluginMock.createStartContract(); -dataPlugin.query.filterManager.getFilters = jest.fn(() => []); -dataPlugin.query.filterManager.getUpdates$ = jest.fn(() => of({}) as unknown as Observable); + dataPlugin.query.filterManager.getFilters = jest.fn(() => []); + dataPlugin.query.filterManager.getUpdates$ = jest.fn(() => of({}) as unknown as Observable); + dataPlugin.query.timefilter.timefilter.createFilter = jest.fn(); + dataPlugin.query.timefilter.timefilter.getAbsoluteTime = jest.fn(() => ({ + from: '2021-08-31T22:00:00.000Z', + to: '2022-09-01T09:16:29.553Z', + })); + dataPlugin.query.timefilter.timefilter.getTime = jest.fn(() => { + return { from: 'now-15m', to: 'now' }; + }); + dataPlugin.query.timefilter.timefilter.calculateBounds = jest.fn(calculateBounds); + dataPlugin.query.getState = jest.fn(() => ({ + query: { query: '', language: 'lucene' }, + filters: [], + })); + dataPlugin.dataViews = createDiscoverDataViewsMock(); -export const discoverServiceMock = { - core: coreMock.createStart(), - chrome: chromeServiceMock.createStartContract(), - history: () => ({ - location: { - search: '', + return { + core: coreMock.createStart(), + charts: chartPluginMock.createSetupContract(), + chrome: chromeServiceMock.createStartContract(), + history: () => ({ + location: { + search: '', + }, + listen: jest.fn(), + }), + data: dataPlugin, + docLinks: docLinksServiceMock.createStartContract(), + capabilities: { + visualize: { + show: true, + }, + discover: { + save: false, + }, + advancedSettings: { + save: true, + }, }, - listen: jest.fn(), - }), - data: dataPlugin, - docLinks: docLinksServiceMock.createStartContract(), - capabilities: { - visualize: { - show: true, + fieldFormats: fieldFormatsMock, + filterManager: dataPlugin.query.filterManager, + inspector: { + open: jest.fn(), }, - discover: { - save: false, + uiSettings: { + get: jest.fn((key: string) => { + if (key === 'fields:popularLimit') { + return 5; + } else if (key === DEFAULT_COLUMNS_SETTING) { + return ['default_column']; + } else if (key === UI_SETTINGS.META_FIELDS) { + return []; + } else if (key === DOC_HIDE_TIME_COLUMN_SETTING) { + return false; + } else if (key === CONTEXT_STEP_SETTING) { + return 5; + } else if (key === SORT_DEFAULT_ORDER_SETTING) { + return 'desc'; + } else if (key === FORMATS_UI_SETTINGS.SHORT_DOTS_ENABLE) { + return false; + } else if (key === SAMPLE_SIZE_SETTING) { + return 250; + } else if (key === SAMPLE_ROWS_PER_PAGE_SETTING) { + return 150; + } else if (key === MAX_DOC_FIELDS_DISPLAYED) { + return 50; + } else if (key === HIDE_ANNOUNCEMENTS) { + return false; + } + }), + isDefault: (key: string) => { + return true; + }, }, - advancedSettings: { - save: true, + http: { + basePath: '/', }, - }, - fieldFormats: fieldFormatsMock, - filterManager: dataPlugin.query.filterManager, - inspector: { - open: jest.fn(), - }, - uiSettings: { - get: jest.fn((key: string) => { - if (key === 'fields:popularLimit') { - return 5; - } else if (key === DEFAULT_COLUMNS_SETTING) { - return ['default_column']; - } else if (key === UI_SETTINGS.META_FIELDS) { - return []; - } else if (key === DOC_HIDE_TIME_COLUMN_SETTING) { - return false; - } else if (key === CONTEXT_STEP_SETTING) { - return 5; - } else if (key === SORT_DEFAULT_ORDER_SETTING) { - return 'desc'; - } else if (key === FORMATS_UI_SETTINGS.SHORT_DOTS_ENABLE) { - return false; - } else if (key === SAMPLE_SIZE_SETTING) { - return 250; - } else if (key === SAMPLE_ROWS_PER_PAGE_SETTING) { - return 150; - } else if (key === MAX_DOC_FIELDS_DISPLAYED) { - return 50; - } else if (key === HIDE_ANNOUNCEMENTS) { - return false; - } - }), - isDefault: (key: string) => { - return true; + dataViewEditor: { + userPermissions: { + editDataView: () => true, + }, + }, + dataViewFieldEditor: { + openEditor: jest.fn(), + userPermissions: { + editIndexPattern: jest.fn(), + }, + }, + navigation: { + ui: { TopNavMenu, AggregateQueryTopNavMenu: TopNavMenu }, }, - }, - http: { - basePath: '/', - }, - dataViewEditor: { - userPermissions: { - editDataView: () => true, + metadata: { + branch: 'test', }, - }, - dataViewFieldEditor: { - openEditor: jest.fn(), - userPermissions: { - editIndexPattern: jest.fn(), + theme: { + useChartsTheme: jest.fn(() => EUI_CHARTS_THEME_LIGHT.theme), + useChartsBaseTheme: jest.fn(() => EUI_CHARTS_THEME_LIGHT.theme), }, - }, - navigation: { - ui: { TopNavMenu, AggregateQueryTopNavMenu: TopNavMenu }, - }, - metadata: { - branch: 'test', - }, - theme: { - useChartsTheme: jest.fn(() => EUI_CHARTS_THEME_LIGHT.theme), - useChartsBaseTheme: jest.fn(() => EUI_CHARTS_THEME_LIGHT.theme), - }, - storage: new LocalStorageMock({}) as unknown as Storage, - addBasePath: jest.fn(), - toastNotifications: { - addInfo: jest.fn(), - addWarning: jest.fn(), - addDanger: jest.fn(), - addSuccess: jest.fn(), - }, - expressions: expressionsPlugin, - savedObjectsTagging: {}, - dataViews: dataViewsMock, - timefilter: { createFilter: jest.fn() }, - locator: { - useUrl: jest.fn(() => ''), - navigate: jest.fn(), - getUrl: jest.fn(() => Promise.resolve('')), - }, - contextLocator: { getRedirectUrl: jest.fn(() => '') }, - singleDocLocator: { getRedirectUrl: jest.fn(() => '') }, -} as unknown as DiscoverServices; + storage: new LocalStorageMock({}) as unknown as Storage, + addBasePath: jest.fn(), + toastNotifications: { + addInfo: jest.fn(), + addWarning: jest.fn(), + addDanger: jest.fn(), + addSuccess: jest.fn(), + }, + expressions: expressionsPlugin, + savedObjectsTagging: {}, + dataViews: dataPlugin.dataViews, + timefilter: dataPlugin.query.timefilter.timefilter, + lens: { EmbeddableComponent: jest.fn(() => null) }, + locator: { + useUrl: jest.fn(() => ''), + navigate: jest.fn(), + getUrl: jest.fn(() => Promise.resolve('')), + }, + contextLocator: { getRedirectUrl: jest.fn(() => '') }, + singleDocLocator: { getRedirectUrl: jest.fn(() => '') }, + } as unknown as DiscoverServices; +} + +export const discoverServiceMock = createDiscoverServicesMock(); diff --git a/src/plugins/discover/public/application/main/components/layout/__stories__/get_layout_props.ts b/src/plugins/discover/public/application/main/components/layout/__stories__/get_layout_props.ts index 56c0f349615e0..334e899b04aee 100644 --- a/src/plugins/discover/public/application/main/components/layout/__stories__/get_layout_props.ts +++ b/src/plugins/discover/public/application/main/components/layout/__stories__/get_layout_props.ts @@ -11,11 +11,9 @@ import { SearchSource } from '@kbn/data-plugin/common'; import { BehaviorSubject, Subject } from 'rxjs'; import { RequestAdapter } from '@kbn/inspector-plugin/common'; import { action } from '@storybook/addon-actions'; -import type { SearchResponse } from '@elastic/elasticsearch/lib/api/types'; import { FetchStatus } from '../../../../types'; import { AvailableFields$, - DataCharts$, DataDocuments$, DataMain$, DataTotalHits$, @@ -47,11 +45,6 @@ const documentObservables = { fetchStatus: FetchStatus.COMPLETE, result: Number(esHits.length), }) as DataTotalHits$, - - charts$: new BehaviorSubject({ - fetchStatus: FetchStatus.COMPLETE, - response: {} as unknown as SearchResponse, - }) as DataCharts$, }; const plainRecordObservables = { @@ -77,11 +70,6 @@ const plainRecordObservables = { fetchStatus: FetchStatus.COMPLETE, recordRawType: RecordRawType.PLAIN, }) as DataTotalHits$, - - charts$: new BehaviorSubject({ - fetchStatus: FetchStatus.COMPLETE, - recordRawType: RecordRawType.PLAIN, - }) as DataCharts$, }; const getCommonProps = (dataView: DataView) => { diff --git a/src/plugins/discover/public/application/main/components/layout/discover_histogram_layout.test.tsx b/src/plugins/discover/public/application/main/components/layout/discover_histogram_layout.test.tsx new file mode 100644 index 0000000000000..5f2b0f9e434d7 --- /dev/null +++ b/src/plugins/discover/public/application/main/components/layout/discover_histogram_layout.test.tsx @@ -0,0 +1,220 @@ +/* + * Copyright 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 { Subject, BehaviorSubject, of } from 'rxjs'; +import { mountWithIntl } from '@kbn/test-jest-helpers'; +import { esHits } from '../../../../__mocks__/es_hits'; +import { dataViewMock } from '../../../../__mocks__/data_view'; +import { savedSearchMock } from '../../../../__mocks__/saved_search'; +import { GetStateReturn } from '../../services/discover_state'; +import { + AvailableFields$, + DataDocuments$, + DataMain$, + DataTotalHits$, + RecordRawType, +} from '../../hooks/use_saved_search'; +import { discoverServiceMock } from '../../../../__mocks__/services'; +import { FetchStatus } from '../../../types'; +import { KibanaContextProvider, KibanaThemeProvider } from '@kbn/kibana-react-plugin/public'; +import { buildDataTableRecord } from '../../../../utils/build_data_record'; +import { DiscoverHistogramLayout, DiscoverHistogramLayoutProps } from './discover_histogram_layout'; +import { SavedSearch, VIEW_MODE } from '@kbn/saved-search-plugin/public'; +import { CoreTheme } from '@kbn/core/public'; +import { act } from 'react-dom/test-utils'; +import { setTimeout } from 'timers/promises'; +import { Storage } from '@kbn/kibana-utils-plugin/public'; +import { LocalStorageMock } from '../../../../__mocks__/local_storage_mock'; +import { HISTOGRAM_HEIGHT_KEY } from './use_discover_histogram'; +import { createSearchSessionMock } from '../../../../__mocks__/search_session'; +import { RequestAdapter } from '@kbn/inspector-plugin/public'; +import { searchSourceInstanceMock } from '@kbn/data-plugin/common/search/search_source/mocks'; +import { UnifiedHistogramLayout } from '@kbn/unified-histogram-plugin/public'; +import { getSessionServiceMock } from '@kbn/data-plugin/public/search/session/mocks'; +import { ResetSearchButton } from './reset_search_button'; + +const mountComponent = async ({ + isPlainRecord = false, + hideChart = false, + isTimeBased = true, + storage, + savedSearch = savedSearchMock, + resetSavedSearch = jest.fn(), +}: { + isPlainRecord?: boolean; + hideChart?: boolean; + isTimeBased?: boolean; + storage?: Storage; + savedSearch?: SavedSearch; + resetSavedSearch?(): void; +} = {}) => { + let services = discoverServiceMock; + services.data.query.timefilter.timefilter.getAbsoluteTime = () => { + return { from: '2020-05-14T11:05:13.590', to: '2020-05-14T11:20:13.590' }; + }; + + (services.data.query.queryString.getDefaultQuery as jest.Mock).mockReturnValue({ + language: 'kuery', + query: '', + }); + (searchSourceInstanceMock.fetch$ as jest.Mock).mockImplementation( + jest.fn().mockReturnValue(of({ rawResponse: { hits: { total: 2 } } })) + ); + + if (storage) { + services = { ...services, storage }; + } + + const main$ = new BehaviorSubject({ + fetchStatus: FetchStatus.COMPLETE, + recordRawType: isPlainRecord ? RecordRawType.PLAIN : RecordRawType.DOCUMENT, + foundDocuments: true, + }) as DataMain$; + + const documents$ = new BehaviorSubject({ + fetchStatus: FetchStatus.COMPLETE, + result: esHits.map((esHit) => buildDataTableRecord(esHit, dataViewMock)), + }) as DataDocuments$; + + const availableFields$ = new BehaviorSubject({ + fetchStatus: FetchStatus.COMPLETE, + fields: [] as string[], + }) as AvailableFields$; + + const totalHits$ = new BehaviorSubject({ + fetchStatus: FetchStatus.COMPLETE, + result: Number(esHits.length), + }) as DataTotalHits$; + + const savedSearchData$ = { + main$, + documents$, + totalHits$, + availableFields$, + }; + + const session = getSessionServiceMock(); + + session.getSession$.mockReturnValue(new BehaviorSubject('123')); + + const props: DiscoverHistogramLayoutProps = { + isPlainRecord, + dataView: dataViewMock, + navigateTo: jest.fn(), + setExpandedDoc: jest.fn(), + savedSearch, + savedSearchData$, + savedSearchRefetch$: new Subject(), + state: { columns: [], hideChart }, + stateContainer: { + setAppState: () => {}, + appStateContainer: { + getState: () => ({ + interval: 'auto', + }), + }, + } as unknown as GetStateReturn, + onFieldEdited: jest.fn(), + columns: [], + viewMode: VIEW_MODE.DOCUMENT_LEVEL, + onAddFilter: jest.fn(), + resetSavedSearch, + isTimeBased, + resizeRef: { current: null }, + searchSessionManager: createSearchSessionMock(session).searchSessionManager, + inspectorAdapters: { requests: new RequestAdapter() }, + }; + + const coreTheme$ = new BehaviorSubject({ darkMode: false }); + + const component = mountWithIntl( + + + + + + ); + + // DiscoverMainContent uses UnifiedHistogramLayout which + // is lazy loaded, so we need to wait for it to be loaded + await act(() => setTimeout(0)); + component.update(); + + return component; +}; + +describe('Discover histogram layout component', () => { + describe('topPanelHeight persistence', () => { + it('should try to get the initial topPanelHeight for UnifiedHistogramLayout from storage', async () => { + const storage = new LocalStorageMock({}) as unknown as Storage; + const originalGet = storage.get; + storage.get = jest.fn().mockImplementation(originalGet); + await mountComponent({ storage }); + expect(storage.get).toHaveBeenCalledWith(HISTOGRAM_HEIGHT_KEY); + }); + + it('should pass undefined to UnifiedHistogramLayout if no value is found in storage', async () => { + const storage = new LocalStorageMock({}) as unknown as Storage; + const originalGet = storage.get; + storage.get = jest.fn().mockImplementation(originalGet); + const component = await mountComponent({ storage }); + expect(storage.get).toHaveBeenCalledWith(HISTOGRAM_HEIGHT_KEY); + expect(storage.get).toHaveReturnedWith(null); + expect(component.find(UnifiedHistogramLayout).prop('topPanelHeight')).toBe(undefined); + }); + + it('should pass the stored topPanelHeight to UnifiedHistogramLayout if a value is found in storage', async () => { + const storage = new LocalStorageMock({}) as unknown as Storage; + const topPanelHeight = 123; + storage.get = jest.fn().mockImplementation(() => topPanelHeight); + const component = await mountComponent({ storage }); + expect(storage.get).toHaveBeenCalledWith(HISTOGRAM_HEIGHT_KEY); + expect(storage.get).toHaveReturnedWith(topPanelHeight); + expect(component.find(UnifiedHistogramLayout).prop('topPanelHeight')).toBe(topPanelHeight); + }); + + it('should update the topPanelHeight in storage and pass the new value to UnifiedHistogramLayout when the topPanelHeight changes', async () => { + const storage = new LocalStorageMock({}) as unknown as Storage; + const originalSet = storage.set; + storage.set = jest.fn().mockImplementation(originalSet); + const component = await mountComponent({ storage }); + const newTopPanelHeight = 123; + expect(component.find(UnifiedHistogramLayout).prop('topPanelHeight')).not.toBe( + newTopPanelHeight + ); + act(() => { + component.find(UnifiedHistogramLayout).prop('onTopPanelHeightChange')!(newTopPanelHeight); + }); + component.update(); + expect(storage.set).toHaveBeenCalledWith(HISTOGRAM_HEIGHT_KEY, newTopPanelHeight); + expect(component.find(UnifiedHistogramLayout).prop('topPanelHeight')).toBe(newTopPanelHeight); + }); + }); + + describe('reset search button', () => { + it('renders the button when there is a saved search', async () => { + const component = await mountComponent(); + expect(component.find(ResetSearchButton).exists()).toBe(true); + }); + + it('does not render the button when there is no saved search', async () => { + const component = await mountComponent({ + savedSearch: { ...savedSearchMock, id: undefined }, + }); + expect(component.find(ResetSearchButton).exists()).toBe(false); + }); + + it('should call resetSavedSearch when clicked', async () => { + const resetSavedSearch = jest.fn(); + const component = await mountComponent({ resetSavedSearch }); + component.find(ResetSearchButton).find('button').simulate('click'); + expect(resetSavedSearch).toHaveBeenCalled(); + }); + }); +}); diff --git a/src/plugins/discover/public/application/main/components/layout/discover_histogram_layout.tsx b/src/plugins/discover/public/application/main/components/layout/discover_histogram_layout.tsx new file mode 100644 index 0000000000000..e6225a26ffea1 --- /dev/null +++ b/src/plugins/discover/public/application/main/components/layout/discover_histogram_layout.tsx @@ -0,0 +1,87 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 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, { RefObject } from 'react'; +import { UnifiedHistogramLayout } from '@kbn/unified-histogram-plugin/public'; +import { css } from '@emotion/react'; +import { useDiscoverServices } from '../../../../hooks/use_discover_services'; +import { useDiscoverHistogram } from './use_discover_histogram'; +import type { DiscoverSearchSessionManager } from '../../services/discover_search_session'; +import type { InspectorAdapters } from '../../hooks/use_inspector'; +import { type DiscoverMainContentProps, DiscoverMainContent } from './discover_main_content'; +import { ResetSearchButton } from './reset_search_button'; + +export interface DiscoverHistogramLayoutProps extends DiscoverMainContentProps { + resetSavedSearch: () => void; + isTimeBased: boolean; + resizeRef: RefObject; + inspectorAdapters: InspectorAdapters; + searchSessionManager: DiscoverSearchSessionManager; +} + +export const DiscoverHistogramLayout = ({ + isPlainRecord, + dataView, + resetSavedSearch, + savedSearch, + savedSearchData$, + state, + stateContainer, + isTimeBased, + resizeRef, + inspectorAdapters, + searchSessionManager, + ...mainContentProps +}: DiscoverHistogramLayoutProps) => { + const services = useDiscoverServices(); + + const commonProps = { + dataView, + isPlainRecord, + stateContainer, + savedSearch, + state, + savedSearchData$, + }; + + const histogramProps = useDiscoverHistogram({ + isTimeBased, + inspectorAdapters, + searchSessionManager, + ...commonProps, + }); + + if (!histogramProps) { + return null; + } + + const histogramLayoutCss = css` + height: 100%; + `; + + return ( + : undefined + } + css={histogramLayoutCss} + {...histogramProps} + > + + + ); +}; diff --git a/src/plugins/discover/public/application/main/components/layout/discover_layout.scss b/src/plugins/discover/public/application/main/components/layout/discover_layout.scss index 70963f50b96a7..a65c22b57b2ab 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_layout.scss +++ b/src/plugins/discover/public/application/main/components/layout/discover_layout.scss @@ -31,6 +31,10 @@ discover-app { overflow: hidden; } +.dscPageBody__sidebar { + position: relative; +} + .dscPageContent__wrapper { padding: $euiSizeS $euiSizeS $euiSizeS 0; overflow: hidden; // Ensures horizontal scroll of table @@ -41,11 +45,9 @@ discover-app { } .dscPageContent { + position: relative; + overflow: hidden; border: $euiBorderThin; -} - -.dscPageContent, -.dscPageContent__inner { height: 100%; } diff --git a/src/plugins/discover/public/application/main/components/layout/discover_layout.test.tsx b/src/plugins/discover/public/application/main/components/layout/discover_layout.test.tsx index 11a5a025afe8f..5b58cda5e0b96 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_layout.test.tsx +++ b/src/plugins/discover/public/application/main/components/layout/discover_layout.test.tsx @@ -7,7 +7,7 @@ */ import React from 'react'; -import { Subject, BehaviorSubject } from 'rxjs'; +import { Subject, BehaviorSubject, of } from 'rxjs'; import { mountWithIntl } from '@kbn/test-jest-helpers'; import type { Query, AggregateQuery } from '@kbn/es-query'; import { setHeaderActionMenuMounter } from '../../../../kibana_services'; @@ -15,20 +15,22 @@ import { DiscoverLayout, SIDEBAR_CLOSED_KEY } from './discover_layout'; import { esHits } from '../../../../__mocks__/es_hits'; import { dataViewMock } from '../../../../__mocks__/data_view'; import { savedSearchMock } from '../../../../__mocks__/saved_search'; -import { createSearchSourceMock } from '@kbn/data-plugin/common/search/search_source/mocks'; +import { + createSearchSourceMock, + searchSourceInstanceMock, +} from '@kbn/data-plugin/common/search/search_source/mocks'; import type { DataView } from '@kbn/data-views-plugin/public'; import { dataViewWithTimefieldMock } from '../../../../__mocks__/data_view_with_timefield'; import { GetStateReturn } from '../../services/discover_state'; import { DiscoverLayoutProps } from './types'; import { AvailableFields$, - DataCharts$, DataDocuments$, DataMain$, DataTotalHits$, RecordRawType, } from '../../hooks/use_saved_search'; -import { discoverServiceMock } from '../../../../__mocks__/services'; +import { createDiscoverServicesMock } from '../../../../__mocks__/services'; import { FetchStatus } from '../../../types'; import { RequestAdapter } from '@kbn/inspector-plugin/common'; import { DiscoverSidebar } from '../sidebar/discover_sidebar'; @@ -37,66 +39,11 @@ import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; import { DiscoverServices } from '../../../../build_services'; import { buildDataTableRecord } from '../../../../utils/build_data_record'; import { DiscoverAppStateProvider } from '../../services/discover_app_state_container'; -import type { UnifiedHistogramChartData } from '@kbn/unified-histogram-plugin/public'; import { getDiscoverStateMock } from '../../../../__mocks__/discover_state.mock'; -import type { SearchResponse } from '@elastic/elasticsearch/lib/api/types'; import { setTimeout } from 'timers/promises'; import { act } from 'react-dom/test-utils'; - -jest.mock('@kbn/unified-histogram-plugin/public', () => { - const originalModule = jest.requireActual('@kbn/unified-histogram-plugin/public'); - - const chartData = { - xAxisOrderedValues: [ - 1623880800000, 1623967200000, 1624053600000, 1624140000000, 1624226400000, 1624312800000, - 1624399200000, 1624485600000, 1624572000000, 1624658400000, 1624744800000, 1624831200000, - 1624917600000, 1625004000000, 1625090400000, - ], - xAxisFormat: { id: 'date', params: { pattern: 'YYYY-MM-DD' } }, - xAxisLabel: 'order_date per day', - yAxisFormat: { id: 'number' }, - ordered: { - date: true, - interval: { - asMilliseconds: jest.fn(), - }, - intervalESUnit: 'd', - intervalESValue: 1, - min: '2021-03-18T08:28:56.411Z', - max: '2021-07-01T07:28:56.411Z', - }, - yAxisLabel: 'Count', - values: [ - { x: 1623880800000, y: 134 }, - { x: 1623967200000, y: 152 }, - { x: 1624053600000, y: 141 }, - { x: 1624140000000, y: 138 }, - { x: 1624226400000, y: 142 }, - { x: 1624312800000, y: 157 }, - { x: 1624399200000, y: 149 }, - { x: 1624485600000, y: 146 }, - { x: 1624572000000, y: 170 }, - { x: 1624658400000, y: 137 }, - { x: 1624744800000, y: 150 }, - { x: 1624831200000, y: 144 }, - { x: 1624917600000, y: 147 }, - { x: 1625004000000, y: 137 }, - { x: 1625090400000, y: 66 }, - ], - } as unknown as UnifiedHistogramChartData; - - return { - ...originalModule, - buildChartData: jest.fn().mockImplementation(() => ({ - chartData, - bucketInterval: { - scaled: true, - description: 'test', - scale: 2, - }, - })), - }; -}); +import { createSearchSessionMock } from '../../../../__mocks__/search_session'; +import { getSessionServiceMock } from '@kbn/data-plugin/public/search/session/mocks'; function getAppStateContainer() { const appStateContainer = getDiscoverStateMock({ isTimeBased: true }).appStateContainer; @@ -118,14 +65,19 @@ async function mountComponent( ) { const searchSourceMock = createSearchSourceMock({}); const services = { - ...discoverServiceMock, + ...createDiscoverServicesMock(), storage: new LocalStorageMock({ [SIDEBAR_CLOSED_KEY]: prevSidebarClosed, }) as unknown as Storage, } as unknown as DiscoverServices; - services.data.query.timefilter.timefilter.getAbsoluteTime = () => { - return { from: '2020-05-14T11:05:13.590', to: '2020-05-14T11:20:13.590' }; - }; + + (services.data.query.queryString.getDefaultQuery as jest.Mock).mockReturnValue({ + language: 'kuery', + query: '', + }); + (searchSourceInstanceMock.fetch$ as jest.Mock).mockImplementation( + jest.fn().mockReturnValue(of({ rawResponse: { hits: { total: 2 } } })) + ); const dataViewList = [dataView]; @@ -150,19 +102,17 @@ async function mountComponent( result: Number(esHits.length), }) as DataTotalHits$; - const charts$ = new BehaviorSubject({ - fetchStatus: FetchStatus.COMPLETE, - response: {} as unknown as SearchResponse, - }) as DataCharts$; - const savedSearchData$ = { main$, documents$, totalHits$, - charts$, availableFields$, }; + const session = getSessionServiceMock(); + + session.getSession$.mockReturnValue(new BehaviorSubject('123')); + const props = { dataView, dataViewList, @@ -175,7 +125,7 @@ async function mountComponent( savedSearchData$, savedSearchRefetch$: new Subject(), searchSource: searchSourceMock, - state: { columns: [], query }, + state: { columns: [], query, hideChart: false, interval: 'auto' }, stateContainer: { setAppState: () => {}, appStateContainer: { @@ -188,6 +138,7 @@ async function mountComponent( persistDataView: jest.fn(), updateAdHocDataViewId: jest.fn(), adHocDataViewList: [], + searchSessionManager: createSearchSessionMock(session).searchSessionManager, savedDataViewList: [], updateDataViewList: jest.fn(), }; @@ -204,12 +155,12 @@ async function mountComponent( // DiscoverMainContent uses UnifiedHistogramLayout which // is lazy loaded, so we need to wait for it to be loaded await act(() => setTimeout(0)); + await component.update(); return component; } -// FLAKY: https://github.com/elastic/kibana/issues/145894 -describe.skip('Discover component', () => { +describe('Discover component', () => { test('selected data view without time field displays no chart toggle', async () => { const container = document.createElement('div'); await mountComponent(dataViewMock, undefined, { attachTo: container }); @@ -224,7 +175,7 @@ describe.skip('Discover component', () => { expect( container.querySelector('[data-test-subj="unifiedHistogramChartOptionsToggle"]') ).not.toBeNull(); - }); + }, 10000); test('sql query displays no chart toggle', async () => { const container = document.createElement('div'); @@ -249,7 +200,7 @@ describe.skip('Discover component', () => { expect( component.find('[data-test-subj="discoverSavedSearchTitle"]').getDOMNode() ).toHaveFocus(); - }); + }, 10000); describe('sidebar', () => { test('should be opened if discover:sidebarClosed was not set', async () => { diff --git a/src/plugins/discover/public/application/main/components/layout/discover_layout.tsx b/src/plugins/discover/public/application/main/components/layout/discover_layout.tsx index 57a0a3c733e71..d8c5445fd5409 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_layout.tsx +++ b/src/plugins/discover/public/application/main/components/layout/discover_layout.tsx @@ -43,7 +43,7 @@ import { VIEW_MODE } from '../../../../components/view_mode_toggle'; import { hasActiveFilter } from './utils'; import { getRawRecordType } from '../../utils/get_raw_record_type'; import { SavedSearchURLConflictCallout } from '../../../../components/saved_search_url_conflict_callout/saved_search_url_conflict_callout'; -import { DiscoverMainContent } from './discover_main_content'; +import { DiscoverHistogramLayout } from './discover_histogram_layout'; /** * Local storage key for sidebar persistence state @@ -72,6 +72,7 @@ export function DiscoverLayout({ persistDataView, updateAdHocDataViewId, adHocDataViewList, + searchSessionManager, savedDataViewList, updateDataViewList, }: DiscoverLayoutProps) { @@ -197,6 +198,75 @@ export function DiscoverLayout({ const resizeRef = useRef(null); + const mainDisplay = useMemo(() => { + if (resultState === 'none') { + return ( + + ); + } + + if (resultState === 'uninitialized') { + return savedSearchRefetch$.next(undefined)} />; + } + + return ( + <> + + {resultState === 'loading' && } + + ); + }, [ + columns, + data, + dataState.error, + dataView, + expandedDoc, + inspectorAdapters, + isPlainRecord, + isTimeBased, + navigateTo, + onAddFilter, + onDisableFilters, + onFieldEdited, + resetSavedSearch, + resultState, + savedSearch, + savedSearchData$, + savedSearchRefetch$, + searchSessionManager, + setExpandedDoc, + state, + stateContainer, + viewMode, + ]); + return (

- + - {resultState === 'none' && ( - - )} - {resultState === 'uninitialized' && ( - savedSearchRefetch$.next(undefined)} /> - )} - {resultState === 'loading' && } - {resultState === 'ready' && ( - - )} + {mainDisplay} diff --git a/src/plugins/discover/public/application/main/components/layout/discover_main_content.test.tsx b/src/plugins/discover/public/application/main/components/layout/discover_main_content.test.tsx index 54e3fa0b19ca5..dd30d6b119fd3 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_main_content.test.tsx +++ b/src/plugins/discover/public/application/main/components/layout/discover_main_content.test.tsx @@ -7,117 +7,49 @@ */ import React from 'react'; -import { Subject, BehaviorSubject } from 'rxjs'; -import { findTestSubject, mountWithIntl } from '@kbn/test-jest-helpers'; +import { Subject, BehaviorSubject, of } from 'rxjs'; +import { mountWithIntl } from '@kbn/test-jest-helpers'; import { esHits } from '../../../../__mocks__/es_hits'; import { dataViewMock } from '../../../../__mocks__/data_view'; -import { savedSearchMock } from '../../../../__mocks__/saved_search'; import { GetStateReturn } from '../../services/discover_state'; +import { savedSearchMock } from '../../../../__mocks__/saved_search'; import { AvailableFields$, - DataCharts$, DataDocuments$, DataMain$, DataTotalHits$, RecordRawType, } from '../../hooks/use_saved_search'; -import { discoverServiceMock } from '../../../../__mocks__/services'; +import { createDiscoverServicesMock } from '../../../../__mocks__/services'; import { FetchStatus } from '../../../types'; import { KibanaContextProvider, KibanaThemeProvider } from '@kbn/kibana-react-plugin/public'; import { buildDataTableRecord } from '../../../../utils/build_data_record'; import { DiscoverMainContent, DiscoverMainContentProps } from './discover_main_content'; -import { SavedSearch, VIEW_MODE } from '@kbn/saved-search-plugin/public'; +import { VIEW_MODE } from '@kbn/saved-search-plugin/public'; import { CoreTheme } from '@kbn/core/public'; import { act } from 'react-dom/test-utils'; import { setTimeout } from 'timers/promises'; import { DocumentViewModeToggle } from '../../../../components/view_mode_toggle'; -import { Storage } from '@kbn/kibana-utils-plugin/public'; -import { LocalStorageMock } from '../../../../__mocks__/local_storage_mock'; -import { - UnifiedHistogramChartData, - UnifiedHistogramLayout, -} from '@kbn/unified-histogram-plugin/public'; -import { HISTOGRAM_HEIGHT_KEY } from './use_discover_histogram'; -import type { SearchResponse } from '@elastic/elasticsearch/lib/api/types'; - -jest.mock('@kbn/unified-histogram-plugin/public', () => { - const originalModule = jest.requireActual('@kbn/unified-histogram-plugin/public'); - - const chartData = { - xAxisOrderedValues: [ - 1623880800000, 1623967200000, 1624053600000, 1624140000000, 1624226400000, 1624312800000, - 1624399200000, 1624485600000, 1624572000000, 1624658400000, 1624744800000, 1624831200000, - 1624917600000, 1625004000000, 1625090400000, - ], - xAxisFormat: { id: 'date', params: { pattern: 'YYYY-MM-DD' } }, - xAxisLabel: 'order_date per day', - yAxisFormat: { id: 'number' }, - ordered: { - date: true, - interval: { - asMilliseconds: jest.fn(), - }, - intervalESUnit: 'd', - intervalESValue: 1, - min: '2021-03-18T08:28:56.411Z', - max: '2021-07-01T07:28:56.411Z', - }, - yAxisLabel: 'Count', - values: [ - { x: 1623880800000, y: 134 }, - { x: 1623967200000, y: 152 }, - { x: 1624053600000, y: 141 }, - { x: 1624140000000, y: 138 }, - { x: 1624226400000, y: 142 }, - { x: 1624312800000, y: 157 }, - { x: 1624399200000, y: 149 }, - { x: 1624485600000, y: 146 }, - { x: 1624572000000, y: 170 }, - { x: 1624658400000, y: 137 }, - { x: 1624744800000, y: 150 }, - { x: 1624831200000, y: 144 }, - { x: 1624917600000, y: 147 }, - { x: 1625004000000, y: 137 }, - { x: 1625090400000, y: 66 }, - ], - } as unknown as UnifiedHistogramChartData; - - return { - ...originalModule, - buildChartData: jest.fn().mockImplementation(() => ({ - chartData, - bucketInterval: { - scaled: true, - description: 'test', - scale: 2, - }, - })), - }; -}); +import { searchSourceInstanceMock } from '@kbn/data-plugin/common/search/search_source/mocks'; +import { DiscoverDocuments } from './discover_documents'; +import { FieldStatisticsTab } from '../field_stats_table'; const mountComponent = async ({ isPlainRecord = false, - hideChart = false, - isTimeBased = true, - storage, - savedSearch = savedSearchMock, - resetSavedSearch = jest.fn(), + viewMode = VIEW_MODE.DOCUMENT_LEVEL, }: { isPlainRecord?: boolean; - hideChart?: boolean; - isTimeBased?: boolean; - storage?: Storage; - savedSearch?: SavedSearch; - resetSavedSearch?: () => void; + viewMode?: VIEW_MODE; } = {}) => { - let services = discoverServiceMock; - services.data.query.timefilter.timefilter.getAbsoluteTime = () => { - return { from: '2020-05-14T11:05:13.590', to: '2020-05-14T11:20:13.590' }; - }; + const services = createDiscoverServicesMock(); - if (storage) { - services = { ...services, storage }; - } + (services.data.query.queryString.getDefaultQuery as jest.Mock).mockReturnValue({ + language: 'kuery', + query: '', + }); + (searchSourceInstanceMock.fetch$ as jest.Mock).mockImplementation( + jest.fn().mockReturnValue(of({ rawResponse: { hits: { total: 2 } } })) + ); const main$ = new BehaviorSubject({ fetchStatus: FetchStatus.COMPLETE, @@ -140,16 +72,10 @@ const mountComponent = async ({ result: Number(esHits.length), }) as DataTotalHits$; - const charts$ = new BehaviorSubject({ - fetchStatus: FetchStatus.COMPLETE, - response: {} as unknown as SearchResponse, - }) as DataCharts$; - const savedSearchData$ = { main$, documents$, totalHits$, - charts$, availableFields$, }; @@ -157,12 +83,11 @@ const mountComponent = async ({ isPlainRecord, dataView: dataViewMock, navigateTo: jest.fn(), - resetSavedSearch, setExpandedDoc: jest.fn(), - savedSearch, + savedSearch: savedSearchMock, savedSearchData$, savedSearchRefetch$: new Subject(), - state: { columns: [], hideChart }, + state: { columns: [], hideChart: false }, stateContainer: { setAppState: () => {}, appStateContainer: { @@ -171,12 +96,10 @@ const mountComponent = async ({ }), }, } as unknown as GetStateReturn, - isTimeBased, - viewMode: VIEW_MODE.DOCUMENT_LEVEL, - onAddFilter: jest.fn(), onFieldEdited: jest.fn(), columns: [], - resizeRef: { current: null }, + viewMode, + onAddFilter: jest.fn(), }; const coreTheme$ = new BehaviorSubject({ darkMode: false }); @@ -192,6 +115,7 @@ const mountComponent = async ({ // DiscoverMainContent uses UnifiedHistogramLayout which // is lazy loaded, so we need to wait for it to be loaded await act(() => setTimeout(0)); + component.update(); return component; }; @@ -200,82 +124,26 @@ describe('Discover main content component', () => { describe('DocumentViewModeToggle', () => { it('should show DocumentViewModeToggle when isPlainRecord is false', async () => { const component = await mountComponent(); - component.update(); expect(component.find(DocumentViewModeToggle).exists()).toBe(true); }); it('should not show DocumentViewModeToggle when isPlainRecord is true', async () => { const component = await mountComponent({ isPlainRecord: true }); - component.update(); expect(component.find(DocumentViewModeToggle).exists()).toBe(false); }); }); - describe('topPanelHeight persistence', () => { - it('should try to get the initial topPanelHeight for UnifiedHistogramLayout from storage', async () => { - const storage = new LocalStorageMock({}) as unknown as Storage; - const originalGet = storage.get; - storage.get = jest.fn().mockImplementation(originalGet); - await mountComponent({ storage }); - expect(storage.get).toHaveBeenCalledWith(HISTOGRAM_HEIGHT_KEY); - }); - - it('should pass undefined to UnifiedHistogramLayout if no value is found in storage', async () => { - const storage = new LocalStorageMock({}) as unknown as Storage; - const originalGet = storage.get; - storage.get = jest.fn().mockImplementation(originalGet); - const component = await mountComponent({ storage }); - expect(storage.get).toHaveBeenCalledWith(HISTOGRAM_HEIGHT_KEY); - expect(storage.get).toHaveReturnedWith(null); - expect(component.find(UnifiedHistogramLayout).prop('topPanelHeight')).toBe(undefined); - }); - - it('should pass the stored topPanelHeight to UnifiedHistogramLayout if a value is found in storage', async () => { - const storage = new LocalStorageMock({}) as unknown as Storage; - const topPanelHeight = 123; - storage.get = jest.fn().mockImplementation(() => topPanelHeight); - const component = await mountComponent({ storage }); - expect(storage.get).toHaveBeenCalledWith(HISTOGRAM_HEIGHT_KEY); - expect(storage.get).toHaveReturnedWith(topPanelHeight); - expect(component.find(UnifiedHistogramLayout).prop('topPanelHeight')).toBe(topPanelHeight); - }); - - it('should update the topPanelHeight in storage and pass the new value to UnifiedHistogramLayout when the topPanelHeight changes', async () => { - const storage = new LocalStorageMock({}) as unknown as Storage; - const originalSet = storage.set; - storage.set = jest.fn().mockImplementation(originalSet); - const component = await mountComponent({ storage }); - const newTopPanelHeight = 123; - expect(component.find(UnifiedHistogramLayout).prop('topPanelHeight')).not.toBe( - newTopPanelHeight - ); - act(() => { - component.find(UnifiedHistogramLayout).prop('onTopPanelHeightChange')!(newTopPanelHeight); - }); - component.update(); - expect(storage.set).toHaveBeenCalledWith(HISTOGRAM_HEIGHT_KEY, newTopPanelHeight); - expect(component.find(UnifiedHistogramLayout).prop('topPanelHeight')).toBe(newTopPanelHeight); - }); - }); - - describe('reset search button', () => { - it('renders the button when there is a saved search', async () => { + describe('Document view', () => { + it('should show DiscoverDocuments when VIEW_MODE is DOCUMENT_LEVEL', async () => { const component = await mountComponent(); - expect(findTestSubject(component, 'resetSavedSearch').length).toBe(1); - }); - - it('does not render the button when there is no saved search', async () => { - const component = await mountComponent({ - savedSearch: { ...savedSearchMock, id: undefined }, - }); - expect(findTestSubject(component, 'resetSavedSearch').length).toBe(0); + expect(component.find(DiscoverDocuments).exists()).toBe(true); + expect(component.find(FieldStatisticsTab).exists()).toBe(false); }); - it('should call resetSavedSearch when clicked', async () => { - const resetSavedSearch = jest.fn(); - const component = await mountComponent({ resetSavedSearch }); - findTestSubject(component, 'resetSavedSearch').simulate('click'); - expect(resetSavedSearch).toHaveBeenCalled(); + it('should show FieldStatisticsTableMemoized when VIEW_MODE is not DOCUMENT_LEVEL', async () => { + const component = await mountComponent({ viewMode: VIEW_MODE.AGGREGATED_LEVEL }); + expect(component.find(DiscoverDocuments).exists()).toBe(false); + expect(component.find(FieldStatisticsTab).exists()).toBe(true); }); }); }); diff --git a/src/plugins/discover/public/application/main/components/layout/discover_main_content.tsx b/src/plugins/discover/public/application/main/components/layout/discover_main_content.tsx index 86428fff1ed91..98b15fe9e5999 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_main_content.tsx +++ b/src/plugins/discover/public/application/main/components/layout/discover_main_content.tsx @@ -6,14 +6,11 @@ * Side Public License, v 1. */ -import { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem, EuiHorizontalRule } from '@elastic/eui'; +import { EuiFlexGroup, EuiFlexItem, EuiHorizontalRule } from '@elastic/eui'; import { SavedSearch } from '@kbn/saved-search-plugin/public'; -import React, { RefObject, useCallback } from 'react'; +import React, { useCallback } from 'react'; import { DataView } from '@kbn/data-views-plugin/common'; import { METRIC_TYPE } from '@kbn/analytics'; -import { UnifiedHistogramLayout } from '@kbn/unified-histogram-plugin/public'; -import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n-react'; import { useDiscoverServices } from '../../../../hooks/use_discover_services'; import { DataTableRecord } from '../../../../types'; import { DocumentViewModeToggle, VIEW_MODE } from '../../../../components/view_mode_toggle'; @@ -23,49 +20,41 @@ import { AppState, GetStateReturn } from '../../services/discover_state'; import { FieldStatisticsTab } from '../field_stats_table'; import { DiscoverDocuments } from './discover_documents'; import { DOCUMENTS_VIEW_CLICK, FIELD_STATISTICS_VIEW_CLICK } from '../field_stats_table/constants'; -import { useDiscoverHistogram } from './use_discover_histogram'; export interface DiscoverMainContentProps { - isPlainRecord: boolean; dataView: DataView; - navigateTo: (url: string) => void; - resetSavedSearch: () => void; - expandedDoc?: DataTableRecord; - setExpandedDoc: (doc?: DataTableRecord) => void; savedSearch: SavedSearch; + isPlainRecord: boolean; + navigateTo: (url: string) => void; savedSearchData$: SavedSearchData; savedSearchRefetch$: DataRefetch$; - state: AppState; - stateContainer: GetStateReturn; - isTimeBased: boolean; + expandedDoc?: DataTableRecord; + setExpandedDoc: (doc?: DataTableRecord) => void; viewMode: VIEW_MODE; onAddFilter: DocViewFilterFn | undefined; onFieldEdited: () => Promise; columns: string[]; - resizeRef: RefObject; + state: AppState; + stateContainer: GetStateReturn; } export const DiscoverMainContent = ({ - isPlainRecord, dataView, + isPlainRecord, navigateTo, - resetSavedSearch, - expandedDoc, - setExpandedDoc, - savedSearch, savedSearchData$, savedSearchRefetch$, - state, - stateContainer, - isTimeBased, + expandedDoc, + setExpandedDoc, viewMode, onAddFilter, onFieldEdited, columns, - resizeRef, + state, + stateContainer, + savedSearch, }: DiscoverMainContentProps) => { - const services = useDiscoverServices(); - const { trackUiMetric } = services; + const { trackUiMetric } = useDiscoverServices(); const setDiscoverViewMode = useCallback( (mode: VIEW_MODE) => { @@ -82,96 +71,45 @@ export const DiscoverMainContent = ({ [trackUiMetric, stateContainer] ); - const { - topPanelHeight, - hits, - chart, - onEditVisualization, - onTopPanelHeightChange, - onChartHiddenChange, - onTimeIntervalChange, - } = useDiscoverHistogram({ - stateContainer, - state, - savedSearchData$, - dataView, - savedSearch, - isTimeBased, - isPlainRecord, - }); - return ( - - - - - - ) : undefined - } - onTopPanelHeightChange={onTopPanelHeightChange} - onEditVisualization={onEditVisualization} - onChartHiddenChange={onChartHiddenChange} - onTimeIntervalChange={onTimeIntervalChange} + - - {!isPlainRecord && ( - - - - - )} - {viewMode === VIEW_MODE.DOCUMENT_LEVEL ? ( - - ) : ( - - )} - - + {!isPlainRecord && ( + + + + + )} + {viewMode === VIEW_MODE.DOCUMENT_LEVEL ? ( + + ) : ( + + )} + ); }; diff --git a/src/plugins/discover/public/application/main/components/layout/reset_search_button.test.tsx b/src/plugins/discover/public/application/main/components/layout/reset_search_button.test.tsx new file mode 100644 index 0000000000000..cde96ff72050f --- /dev/null +++ b/src/plugins/discover/public/application/main/components/layout/reset_search_button.test.tsx @@ -0,0 +1,20 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { mountWithIntl } from '@kbn/test-jest-helpers'; +import React from 'react'; +import { ResetSearchButton } from './reset_search_button'; + +describe('ResetSearchButton', () => { + it('should call resetSavedSearch when the button is clicked', () => { + const resetSavedSearch = jest.fn(); + const component = mountWithIntl(); + component.find('button[data-test-subj="resetSavedSearch"]').simulate('click'); + expect(resetSavedSearch).toHaveBeenCalled(); + }); +}); diff --git a/src/plugins/discover/public/application/main/components/layout/reset_search_button.tsx b/src/plugins/discover/public/application/main/components/layout/reset_search_button.tsx new file mode 100644 index 0000000000000..e9b0cc2417d97 --- /dev/null +++ b/src/plugins/discover/public/application/main/components/layout/reset_search_button.tsx @@ -0,0 +1,35 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React from 'react'; +import { EuiButtonEmpty, EuiFlexItem } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n-react'; +import { css } from '@emotion/react'; + +const resetSearchButtonWrapper = css` + overflow: hidden; +`; + +export const ResetSearchButton = ({ resetSavedSearch }: { resetSavedSearch?: () => void }) => { + return ( + + + + + + ); +}; diff --git a/src/plugins/discover/public/application/main/components/layout/types.ts b/src/plugins/discover/public/application/main/components/layout/types.ts index 2ce822b28d150..24b0a47f6f2a6 100644 --- a/src/plugins/discover/public/application/main/components/layout/types.ts +++ b/src/plugins/discover/public/application/main/components/layout/types.ts @@ -9,16 +9,17 @@ import type { Query, TimeRange, AggregateQuery } from '@kbn/es-query'; import type { DataView } from '@kbn/data-views-plugin/public'; import type { DataViewListItem, ISearchSource } from '@kbn/data-plugin/public'; -import { RequestAdapter } from '@kbn/inspector-plugin/common'; import { SavedSearch } from '@kbn/saved-search-plugin/public'; import { DataTableRecord } from '../../../../types'; import { AppState, GetStateReturn } from '../../services/discover_state'; import { DataRefetch$, SavedSearchData } from '../../hooks/use_saved_search'; +import type { DiscoverSearchSessionManager } from '../../services/discover_search_session'; +import type { InspectorAdapters } from '../../hooks/use_inspector'; export interface DiscoverLayoutProps { dataView: DataView; dataViewList: DataViewListItem[]; - inspectorAdapters: { requests: RequestAdapter }; + inspectorAdapters: InspectorAdapters; navigateTo: (url: string) => void; onChangeDataView: (id: string) => void; onUpdateQuery: ( @@ -38,5 +39,6 @@ export interface DiscoverLayoutProps { updateDataViewList: (dataViews: DataView[]) => Promise; updateAdHocDataViewId: (dataView: DataView) => Promise; adHocDataViewList: DataView[]; + searchSessionManager: DiscoverSearchSessionManager; savedDataViewList: DataViewListItem[]; } diff --git a/src/plugins/discover/public/application/main/components/layout/use_discover_histogram.test.ts b/src/plugins/discover/public/application/main/components/layout/use_discover_histogram.test.ts index 0306c36ce3482..b562ed1f6df07 100644 --- a/src/plugins/discover/public/application/main/components/layout/use_discover_histogram.test.ts +++ b/src/plugins/discover/public/application/main/components/layout/use_discover_histogram.test.ts @@ -6,7 +6,6 @@ * Side Public License, v 1. */ -import type { SearchResponse } from '@elastic/elasticsearch/lib/api/types'; import { buildDataTableRecord } from '../../../../utils/build_data_record'; import { esHits } from '../../../../__mocks__/es_hits'; import { act, renderHook } from '@testing-library/react-hooks'; @@ -14,13 +13,12 @@ import { BehaviorSubject } from 'rxjs'; import { FetchStatus } from '../../../types'; import { AvailableFields$, - DataCharts$, DataDocuments$, DataMain$, DataTotalHits$, RecordRawType, } from '../../hooks/use_saved_search'; -import type { GetStateReturn } from '../../services/discover_state'; +import type { AppState, GetStateReturn } from '../../services/discover_state'; import { savedSearchMock } from '../../../../__mocks__/saved_search'; import type { Storage } from '@kbn/kibana-utils-plugin/public'; import { LocalStorageMock } from '../../../../__mocks__/local_storage_mock'; @@ -33,7 +31,14 @@ import { } from './use_discover_histogram'; import { setTimeout } from 'timers/promises'; import { calculateBounds } from '@kbn/data-plugin/public'; -import { buildChartData } from '@kbn/unified-histogram-plugin/public'; +import { createSearchSessionMock } from '../../../../__mocks__/search_session'; +import { RequestAdapter } from '@kbn/inspector-plugin/public'; +import { getSessionServiceMock } from '@kbn/data-plugin/public/search/session/mocks'; +import { UnifiedHistogramFetchStatus } from '@kbn/unified-histogram-plugin/public'; +import { checkHitCount, sendErrorTo } from '../../hooks/use_saved_search_messages'; +import type { InspectorAdapters } from '../../hooks/use_inspector'; +import type { TypedLensByValueInput } from '@kbn/lens-plugin/public'; +import { DiscoverSearchSessionManager } from '../../services/discover_search_session'; const mockData = dataPluginMock.createStartContract(); @@ -44,6 +49,10 @@ mockData.query.timefilter.timefilter.calculateBounds = (timeRange) => { return calculateBounds(timeRange); }; +const mockLens = { + navigateToPrefilledEditor: jest.fn(), +}; + let mockStorage = new LocalStorageMock({}) as unknown as Storage; let mockCanVisualize = true; @@ -51,7 +60,7 @@ jest.mock('../../../../hooks/use_discover_services', () => { const originalModule = jest.requireActual('../../../../hooks/use_discover_services'); return { ...originalModule, - useDiscoverServices: () => ({ storage: mockStorage, data: mockData }), + useDiscoverServices: () => ({ storage: mockStorage, data: mockData, lens: mockLens }), }; }); @@ -63,39 +72,53 @@ jest.mock('@kbn/unified-field-list-plugin/public', () => { }; }); -const mockBuildChartData = buildChartData as jest.MockedFunction; - -jest.mock('@kbn/unified-histogram-plugin/public', () => { - const originalModule = jest.requireActual('@kbn/unified-histogram-plugin/public'); +jest.mock('../../hooks/use_saved_search_messages', () => { + const originalModule = jest.requireActual('../../hooks/use_saved_search_messages'); return { ...originalModule, - buildChartData: jest.fn(originalModule.buildChartData), + checkHitCount: jest.fn(originalModule.checkHitCount), + sendErrorTo: jest.fn(originalModule.sendErrorTo), }; }); +const mockCheckHitCount = checkHitCount as jest.MockedFunction; + describe('useDiscoverHistogram', () => { const renderUseDiscoverHistogram = async ({ isPlainRecord = false, isTimeBased = true, canVisualize = true, storage = new LocalStorageMock({}) as unknown as Storage, + state = { interval: 'auto', hideChart: false, breakdownField: 'extension' }, stateContainer = {}, + searchSessionManager, + searchSessionId = '123', + inspectorAdapters = { requests: new RequestAdapter() }, + totalHits$ = new BehaviorSubject({ + fetchStatus: FetchStatus.COMPLETE, + result: Number(esHits.length), + }) as DataTotalHits$, + main$ = new BehaviorSubject({ + fetchStatus: FetchStatus.COMPLETE, + recordRawType: isPlainRecord ? RecordRawType.PLAIN : RecordRawType.DOCUMENT, + foundDocuments: true, + }) as DataMain$, }: { isPlainRecord?: boolean; isTimeBased?: boolean; canVisualize?: boolean; storage?: Storage; + state?: AppState; stateContainer?: unknown; + searchSessionManager?: DiscoverSearchSessionManager; + searchSessionId?: string | null; + inspectorAdapters?: InspectorAdapters; + totalHits$?: DataTotalHits$; + main$?: DataMain$; } = {}) => { mockStorage = storage; mockCanVisualize = canVisualize; - const main$ = new BehaviorSubject({ - fetchStatus: FetchStatus.COMPLETE, - recordRawType: isPlainRecord ? RecordRawType.PLAIN : RecordRawType.DOCUMENT, - foundDocuments: true, - }) as DataMain$; - const documents$ = new BehaviorSubject({ fetchStatus: FetchStatus.COMPLETE, result: esHits.map((esHit) => buildDataTableRecord(esHit, dataViewWithTimefieldMock)), @@ -106,148 +129,142 @@ describe('useDiscoverHistogram', () => { fields: [] as string[], }) as AvailableFields$; - const totalHits$ = new BehaviorSubject({ - fetchStatus: FetchStatus.COMPLETE, - result: Number(esHits.length), - }) as DataTotalHits$; - - const charts$ = new BehaviorSubject({ - fetchStatus: FetchStatus.COMPLETE, - response: { - took: 0, - timed_out: false, - _shards: { - total: 1, - successful: 1, - skipped: 0, - failed: 0, - }, - hits: { - total: 29, - max_score: null, - hits: [], - }, - aggregations: { - '2': { - buckets: [ - { - key_as_string: '2022-10-05T16:00:00.000-03:00', - key: 1664996400000, - doc_count: 6, - }, - { - key_as_string: '2022-10-05T16:30:00.000-03:00', - key: 1664998200000, - doc_count: 2, - }, - { - key_as_string: '2022-10-05T17:00:00.000-03:00', - key: 1665000000000, - doc_count: 3, - }, - { - key_as_string: '2022-10-05T17:30:00.000-03:00', - key: 1665001800000, - doc_count: 8, - }, - { - key_as_string: '2022-10-05T18:00:00.000-03:00', - key: 1665003600000, - doc_count: 10, - }, - ], - }, - }, - } as SearchResponse, - }) as DataCharts$; - const savedSearchData$ = { main$, documents$, totalHits$, - charts$, availableFields$, }; - const hook = renderHook(() => { - return useDiscoverHistogram({ - stateContainer: stateContainer as GetStateReturn, - state: { interval: 'auto', hideChart: false }, - savedSearchData$, - dataView: dataViewWithTimefieldMock, - savedSearch: savedSearchMock, - isTimeBased, - isPlainRecord, - }); - }); + if (!searchSessionManager) { + const session = getSessionServiceMock(); + session.getSession$.mockReturnValue(new BehaviorSubject(searchSessionId ?? undefined)); + searchSessionManager = createSearchSessionMock(session).searchSessionManager; + } + + const initialProps = { + stateContainer: stateContainer as GetStateReturn, + state, + savedSearchData$, + dataView: dataViewWithTimefieldMock, + savedSearch: savedSearchMock, + isTimeBased, + isPlainRecord, + inspectorAdapters, + searchSessionManager: searchSessionManager!, + }; + + const hook = renderHook( + (props: Parameters[0]) => useDiscoverHistogram(props), + { initialProps } + ); await act(() => setTimeout(0)); - return hook; + return { hook, initialProps }; }; - const expectedChartData = { - xAxisOrderedValues: [1664996400000, 1664998200000, 1665000000000, 1665001800000, 1665003600000], - xAxisFormat: { id: 'date', params: { pattern: 'HH:mm:ss.SSS' } }, - xAxisLabel: 'timestamp per 0 milliseconds', - yAxisFormat: { id: 'number' }, - ordered: { - date: true, - interval: 'P0D', - intervalESUnit: 'ms', - intervalESValue: 0, - min: '1991-03-29T08:04:00.694Z', - max: '2021-03-29T07:04:00.695Z', - }, - yAxisLabel: 'Count', - values: [ - { x: 1664996400000, y: 6 }, - { x: 1664998200000, y: 2 }, - { x: 1665000000000, y: 3 }, - { x: 1665001800000, y: 8 }, - { x: 1665003600000, y: 10 }, - ], - }; + it('should return undefined if there is no search session', async () => { + const { + hook: { result }, + } = await renderUseDiscoverHistogram({ searchSessionId: null }); + expect(result.current).toBeUndefined(); + }); describe('contexts', () => { it('should output the correct hits context', async () => { - const { result } = await renderUseDiscoverHistogram(); - expect(result.current.hits?.status).toBe(FetchStatus.COMPLETE); - expect(result.current.hits?.total).toEqual(esHits.length); + const { + hook: { result }, + } = await renderUseDiscoverHistogram(); + expect(result.current?.hits?.status).toBe(UnifiedHistogramFetchStatus.complete); + expect(result.current?.hits?.total).toEqual(esHits.length); }); it('should output the correct chart context', async () => { - const { result } = await renderUseDiscoverHistogram(); - expect(result.current.chart?.status).toBe(FetchStatus.COMPLETE); - expect(result.current.chart?.hidden).toBe(false); - expect(result.current.chart?.timeInterval).toBe('auto'); - expect(result.current.chart?.bucketInterval?.toString()).toBe('P0D'); - expect(JSON.stringify(result.current.chart?.data)).toBe(JSON.stringify(expectedChartData)); - expect(result.current.chart?.error).toBeUndefined(); + const { + hook: { result }, + } = await renderUseDiscoverHistogram(); + expect(result.current?.chart?.hidden).toBe(false); + expect(result.current?.chart?.timeInterval).toBe('auto'); + }); + + it('should output the correct breakdown context', async () => { + const { + hook: { result }, + } = await renderUseDiscoverHistogram(); + expect(result.current?.breakdown?.field?.name).toBe('extension'); }); - it('should output undefined for hits and chart if isPlainRecord is true', async () => { - const { result } = await renderUseDiscoverHistogram({ isPlainRecord: true }); - expect(result.current.hits).toBeUndefined(); - expect(result.current.chart).toBeUndefined(); + it('should output the correct request context', async () => { + const requestAdapter = new RequestAdapter(); + const { + hook: { result }, + } = await renderUseDiscoverHistogram({ + searchSessionId: '321', + inspectorAdapters: { requests: requestAdapter }, + }); + expect(result.current?.request.adapter).toBe(requestAdapter); + expect(result.current?.request.searchSessionId).toBe('321'); }); - it('should output undefined for chart if isTimeBased is false', async () => { - const { result } = await renderUseDiscoverHistogram({ isTimeBased: false }); - expect(result.current.hits).not.toBeUndefined(); - expect(result.current.chart).toBeUndefined(); + it('should output undefined for hits and chart and breakdown if isPlainRecord is true', async () => { + const { + hook: { result }, + } = await renderUseDiscoverHistogram({ isPlainRecord: true }); + expect(result.current?.hits).toBeUndefined(); + expect(result.current?.chart).toBeUndefined(); + expect(result.current?.breakdown).toBeUndefined(); + }); + + it('should output undefined for chart and breakdown if isTimeBased is false', async () => { + const { + hook: { result }, + } = await renderUseDiscoverHistogram({ isTimeBased: false }); + expect(result.current?.hits).not.toBeUndefined(); + expect(result.current?.chart).toBeUndefined(); + expect(result.current?.breakdown).toBeUndefined(); + }); + + it('should clear lensRequests when chart is undefined', async () => { + const inspectorAdapters = { + requests: new RequestAdapter(), + lensRequests: new RequestAdapter(), + }; + const { hook, initialProps } = await renderUseDiscoverHistogram({ + inspectorAdapters, + }); + expect(inspectorAdapters.lensRequests).toBeDefined(); + hook.rerender({ ...initialProps, isPlainRecord: true }); + expect(inspectorAdapters.lensRequests).toBeUndefined(); }); }); describe('onEditVisualization', () => { it('returns a callback for onEditVisualization when the data view can be visualized', async () => { - const { result } = await renderUseDiscoverHistogram(); - expect(result.current.onEditVisualization).toBeDefined(); + const { + hook: { result }, + } = await renderUseDiscoverHistogram(); + expect(result.current?.onEditVisualization).toBeDefined(); }); it('returns undefined for onEditVisualization when the data view cannot be visualized', async () => { - const { result } = await renderUseDiscoverHistogram({ canVisualize: false }); - expect(result.current.onEditVisualization).toBeUndefined(); + const { + hook: { result }, + } = await renderUseDiscoverHistogram({ canVisualize: false }); + expect(result.current?.onEditVisualization).toBeUndefined(); + }); + + it('should call lens.navigateToPrefilledEditor when onEditVisualization is called', async () => { + const { + hook: { result }, + } = await renderUseDiscoverHistogram(); + const attributes = { title: 'test' } as TypedLensByValueInput['attributes']; + result.current?.onEditVisualization!(attributes); + expect(mockLens.navigateToPrefilledEditor).toHaveBeenCalledWith({ + id: '', + timeRange: mockData.query.timefilter.timefilter.getTime(), + attributes, + }); }); }); @@ -255,38 +272,104 @@ describe('useDiscoverHistogram', () => { it('should try to get the topPanelHeight from storage', async () => { const storage = new LocalStorageMock({}) as unknown as Storage; storage.get = jest.fn(() => 100); - const { result } = await renderUseDiscoverHistogram({ storage }); + const { + hook: { result }, + } = await renderUseDiscoverHistogram({ storage }); expect(storage.get).toHaveBeenCalledWith(HISTOGRAM_HEIGHT_KEY); - expect(result.current.topPanelHeight).toBe(100); + expect(result.current?.topPanelHeight).toBe(100); }); it('should update topPanelHeight when onTopPanelHeightChange is called', async () => { const storage = new LocalStorageMock({}) as unknown as Storage; storage.get = jest.fn(() => 100); storage.set = jest.fn(); - const { result } = await renderUseDiscoverHistogram({ storage }); - expect(result.current.topPanelHeight).toBe(100); + const { + hook: { result }, + } = await renderUseDiscoverHistogram({ storage }); + expect(result.current?.topPanelHeight).toBe(100); act(() => { - result.current.onTopPanelHeightChange(200); + result.current?.onTopPanelHeightChange(200); }); expect(storage.set).toHaveBeenCalledWith(HISTOGRAM_HEIGHT_KEY, 200); - expect(result.current.topPanelHeight).toBe(200); + expect(result.current?.topPanelHeight).toBe(200); }); }); describe('callbacks', () => { it('should update chartHidden when onChartHiddenChange is called', async () => { + const storage = new LocalStorageMock({}) as unknown as Storage; + storage.set = jest.fn(); + const state = { interval: 'auto', hideChart: false, breakdownField: 'extension' }; + const stateContainer = { + setAppState: jest.fn((newState) => { + Object.assign(state, newState); + }), + }; + const session = getSessionServiceMock(); + const session$ = new BehaviorSubject('123'); + session.getSession$.mockReturnValue(session$); + const inspectorAdapters = { + requests: new RequestAdapter(), + lensRequests: new RequestAdapter(), + }; + const { hook } = await renderUseDiscoverHistogram({ + storage, + state, + stateContainer, + searchSessionManager: createSearchSessionMock(session).searchSessionManager, + inspectorAdapters, + }); + act(() => { + hook.result.current?.onChartHiddenChange(false); + }); + expect(inspectorAdapters.lensRequests).toBeDefined(); + expect(storage.set).toHaveBeenCalledWith(CHART_HIDDEN_KEY, false); + expect(stateContainer.setAppState).toHaveBeenCalledWith({ hideChart: false }); + act(() => { + hook.result.current?.onChartHiddenChange(true); + session$.next('321'); + }); + hook.rerender(); + expect(inspectorAdapters.lensRequests).toBeUndefined(); + expect(storage.set).toHaveBeenCalledWith(CHART_HIDDEN_KEY, true); + expect(stateContainer.setAppState).toHaveBeenCalledWith({ hideChart: true }); + }); + + it('should set lensRequests when onChartLoad is called', async () => { + const lensRequests = new RequestAdapter(); + const inspectorAdapters = { + requests: new RequestAdapter(), + lensRequests: undefined as RequestAdapter | undefined, + }; + const { + hook: { result }, + } = await renderUseDiscoverHistogram({ inspectorAdapters }); + expect(inspectorAdapters.lensRequests).toBeUndefined(); + act(() => { + result.current?.onChartLoad({ complete: true, adapters: { requests: lensRequests } }); + }); + expect(inspectorAdapters.lensRequests).toBeDefined(); + }); + + it('should update chart hidden when onChartHiddenChange is called', async () => { const storage = new LocalStorageMock({}) as unknown as Storage; storage.set = jest.fn(); const stateContainer = { setAppState: jest.fn(), }; - const { result } = await renderUseDiscoverHistogram({ + const inspectorAdapters = { + requests: new RequestAdapter(), + lensRequests: new RequestAdapter(), + }; + const { + hook: { result }, + } = await renderUseDiscoverHistogram({ storage, stateContainer, + inspectorAdapters, }); act(() => { - result.current.onChartHiddenChange(true); + result.current?.onChartHiddenChange(true); }); expect(storage.set).toHaveBeenCalledWith(CHART_HIDDEN_KEY, true); expect(stateContainer.setAppState).toHaveBeenCalledWith({ hideChart: true }); @@ -296,33 +379,99 @@ describe('useDiscoverHistogram', () => { const stateContainer = { setAppState: jest.fn(), }; - const { result } = await renderUseDiscoverHistogram({ + const { + hook: { result }, + } = await renderUseDiscoverHistogram({ stateContainer, }); act(() => { - result.current.onTimeIntervalChange('auto'); + result.current?.onTimeIntervalChange('auto'); }); expect(stateContainer.setAppState).toHaveBeenCalledWith({ interval: 'auto' }); }); - }); - describe('buildChartData', () => { - it('should call buildChartData when isPlainRecord is false and isTimeBased is true', async () => { - mockBuildChartData.mockClear(); - await renderUseDiscoverHistogram(); - expect(mockBuildChartData).toHaveBeenCalled(); + it('should update breakdownField when onBreakdownFieldChange is called', async () => { + const stateContainer = { + setAppState: jest.fn(), + }; + const { + hook: { result }, + } = await renderUseDiscoverHistogram({ + stateContainer, + }); + act(() => { + result.current?.onBreakdownFieldChange( + dataViewWithTimefieldMock.getFieldByName('extension') + ); + }); + expect(stateContainer.setAppState).toHaveBeenCalledWith({ breakdownField: 'extension' }); }); - it('should not call buildChartData when isPlainRecord is true', async () => { - mockBuildChartData.mockClear(); - await renderUseDiscoverHistogram({ isPlainRecord: true }); - expect(mockBuildChartData).not.toHaveBeenCalled(); + it('should update total hits when onTotalHitsChange is called', async () => { + mockCheckHitCount.mockClear(); + const totalHits$ = new BehaviorSubject({ + fetchStatus: FetchStatus.LOADING, + result: undefined, + }) as DataTotalHits$; + const main$ = new BehaviorSubject({ + fetchStatus: FetchStatus.COMPLETE, + recordRawType: RecordRawType.DOCUMENT, + foundDocuments: true, + }) as DataMain$; + const { hook } = await renderUseDiscoverHistogram({ totalHits$, main$ }); + act(() => { + hook.result.current?.onTotalHitsChange(UnifiedHistogramFetchStatus.complete, 100); + }); + hook.rerender(); + expect(hook.result.current?.hits?.status).toBe(UnifiedHistogramFetchStatus.complete); + expect(hook.result.current?.hits?.total).toBe(100); + expect(totalHits$.value).toEqual({ + fetchStatus: FetchStatus.COMPLETE, + result: 100, + }); + expect(mockCheckHitCount).toHaveBeenCalledWith(main$, 100); }); - it('should not call buildChartData when isTimeBased is false', async () => { - mockBuildChartData.mockClear(); - await renderUseDiscoverHistogram({ isTimeBased: false }); - expect(mockBuildChartData).not.toHaveBeenCalled(); + it('should not update total hits when onTotalHitsChange is called with an error', async () => { + mockCheckHitCount.mockClear(); + const totalHits$ = new BehaviorSubject({ + fetchStatus: FetchStatus.UNINITIALIZED, + result: undefined, + }) as DataTotalHits$; + const { hook } = await renderUseDiscoverHistogram({ totalHits$ }); + const error = new Error('test'); + act(() => { + hook.result.current?.onTotalHitsChange(UnifiedHistogramFetchStatus.error, error); + }); + hook.rerender(); + expect(sendErrorTo).toHaveBeenCalledWith(mockData, totalHits$); + expect(hook.result.current?.hits?.status).toBe(UnifiedHistogramFetchStatus.error); + expect(hook.result.current?.hits?.total).toBeUndefined(); + expect(totalHits$.value).toEqual({ + fetchStatus: FetchStatus.ERROR, + error, + }); + expect(mockCheckHitCount).not.toHaveBeenCalled(); + }); + + it('should not update total hits when onTotalHitsChange is called with a loading status while totalHits$ has a partial status', async () => { + mockCheckHitCount.mockClear(); + const totalHits$ = new BehaviorSubject({ + fetchStatus: FetchStatus.PARTIAL, + result: undefined, + }) as DataTotalHits$; + const { hook } = await renderUseDiscoverHistogram({ totalHits$ }); + act(() => { + hook.result.current?.onTotalHitsChange(UnifiedHistogramFetchStatus.loading, undefined); + }); + hook.rerender(); + expect(hook.result.current?.hits?.status).toBe(UnifiedHistogramFetchStatus.partial); + expect(hook.result.current?.hits?.total).toBeUndefined(); + expect(totalHits$.value).toEqual({ + fetchStatus: FetchStatus.PARTIAL, + result: undefined, + }); + expect(mockCheckHitCount).not.toHaveBeenCalled(); }); }); }); diff --git a/src/plugins/discover/public/application/main/components/layout/use_discover_histogram.ts b/src/plugins/discover/public/application/main/components/layout/use_discover_histogram.ts index 91c641a38cb08..2141ab8cd21ef 100644 --- a/src/plugins/discover/public/application/main/components/layout/use_discover_histogram.ts +++ b/src/plugins/discover/public/application/main/components/layout/use_discover_histogram.ts @@ -6,23 +6,30 @@ * Side Public License, v 1. */ -import type { DataView } from '@kbn/data-views-plugin/common'; +import type { DataView, DataViewField } from '@kbn/data-views-plugin/common'; import type { SavedSearch } from '@kbn/saved-search-plugin/public'; -import { - getVisualizeInformation, - triggerVisualizeActions, -} from '@kbn/unified-field-list-plugin/public'; -import { buildChartData } from '@kbn/unified-histogram-plugin/public'; +import { getVisualizeInformation } from '@kbn/unified-field-list-plugin/public'; import { useCallback, useEffect, useMemo, useState } from 'react'; +import { + UnifiedHistogramFetchStatus, + UnifiedHistogramHitsContext, +} from '@kbn/unified-histogram-plugin/public'; +import type { UnifiedHistogramChartLoadEvent } from '@kbn/unified-histogram-plugin/public'; +import useObservable from 'react-use/lib/useObservable'; +import type { TypedLensByValueInput } from '@kbn/lens-plugin/public'; import { getUiActions } from '../../../../kibana_services'; -import { PLUGIN_ID } from '../../../../../common'; import { useDiscoverServices } from '../../../../hooks/use_discover_services'; import { useDataState } from '../../hooks/use_data_state'; import type { SavedSearchData } from '../../hooks/use_saved_search'; import type { AppState, GetStateReturn } from '../../services/discover_state'; +import { FetchStatus } from '../../../types'; +import type { DiscoverSearchSessionManager } from '../../services/discover_search_session'; +import type { InspectorAdapters } from '../../hooks/use_inspector'; +import { checkHitCount, sendErrorTo } from '../../hooks/use_saved_search_messages'; export const CHART_HIDDEN_KEY = 'discover:chartHidden'; export const HISTOGRAM_HEIGHT_KEY = 'discover:histogramHeight'; +export const HISTOGRAM_BREAKDOWN_FIELD_KEY = 'discover:histogramBreakdownField'; export const useDiscoverHistogram = ({ stateContainer, @@ -32,6 +39,8 @@ export const useDiscoverHistogram = ({ savedSearch, isTimeBased, isPlainRecord, + inspectorAdapters, + searchSessionManager, }: { stateContainer: GetStateReturn; state: AppState; @@ -40,8 +49,10 @@ export const useDiscoverHistogram = ({ savedSearch: SavedSearch; isTimeBased: boolean; isPlainRecord: boolean; + inspectorAdapters: InspectorAdapters; + searchSessionManager: DiscoverSearchSessionManager; }) => { - const { storage, data } = useDiscoverServices(); + const { storage, data, lens } = useDiscoverServices(); /** * Visualize @@ -65,18 +76,19 @@ export const useDiscoverHistogram = ({ }); }, [dataView, savedSearch.columns, timeField]); - const onEditVisualization = useCallback(() => { - if (!timeField) { - return; - } - triggerVisualizeActions( - getUiActions(), - timeField, - savedSearch.columns || [], - PLUGIN_ID, - dataView - ); - }, [dataView, savedSearch.columns, timeField]); + const onEditVisualization = useCallback( + (lensAttributes: TypedLensByValueInput['attributes']) => { + if (!timeField) { + return; + } + lens.navigateToPrefilledEditor({ + id: '', + timeRange: data.query.timefilter.timefilter.getTime(), + attributes: lensAttributes, + }); + }, + [data.query.timefilter.timefilter, lens, timeField] + ); /** * Height @@ -96,17 +108,9 @@ export const useDiscoverHistogram = ({ ); /** - * Other callbacks + * Time interval */ - const onChartHiddenChange = useCallback( - (chartHidden: boolean) => { - storage.set(CHART_HIDDEN_KEY, chartHidden); - stateContainer.setAppState({ hideChart: chartHidden }); - }, - [stateContainer, storage] - ); - const onTimeIntervalChange = useCallback( (newInterval: string) => { stateContainer.setAppState({ interval: newInterval }); @@ -115,9 +119,62 @@ export const useDiscoverHistogram = ({ ); /** - * Data + * Request + */ + + // The searchSessionId will be updated whenever a new search + // is started and will trigger a unified histogram refetch + const searchSessionId = useObservable(searchSessionManager.searchSessionId$); + const request = useMemo( + () => ({ + searchSessionId, + adapter: inspectorAdapters.requests, + }), + [inspectorAdapters.requests, searchSessionId] + ); + + /** + * Total hits */ + const [localHitsContext, setLocalHitsContext] = useState(); + + const onTotalHitsChange = useCallback( + (status: UnifiedHistogramFetchStatus, result?: number | Error) => { + if (result instanceof Error) { + // Display the error and set totalHits$ to an error state + sendErrorTo(data, savedSearchData$.totalHits$)(result); + return; + } + + const { fetchStatus, recordRawType } = savedSearchData$.totalHits$.getValue(); + + // If we have a partial result already, we don't want to update the total hits back to loading + if (fetchStatus === FetchStatus.PARTIAL && status === UnifiedHistogramFetchStatus.loading) { + return; + } + + // Set a local copy of the hits context to pass to unified histogram + setLocalHitsContext({ status, total: result }); + + // Sync the totalHits$ observable with the unified histogram state + savedSearchData$.totalHits$.next({ + fetchStatus: status.toString() as FetchStatus, + result, + recordRawType, + }); + + // Check the hits count to set a partial or no results state + if (status === UnifiedHistogramFetchStatus.complete && typeof result === 'number') { + checkHitCount(savedSearchData$.main$, result); + } + }, + [data, savedSearchData$.main$, savedSearchData$.totalHits$] + ); + + // We only rely on the totalHits$ observable if we don't have a local hits context yet, + // since we only want to show the partial results on the first load, or there will be + // a flickering effect as the loading spinner is quickly shown and hidden again on fetches const { fetchStatus: hitsFetchStatus, result: hitsTotal } = useDataState( savedSearchData$.totalHits$ ); @@ -126,59 +183,96 @@ export const useDiscoverHistogram = ({ () => isPlainRecord ? undefined - : { - status: hitsFetchStatus, + : localHitsContext ?? { + status: hitsFetchStatus.toString() as UnifiedHistogramFetchStatus, total: hitsTotal, }, - [hitsFetchStatus, hitsTotal, isPlainRecord] + [hitsFetchStatus, hitsTotal, isPlainRecord, localHitsContext] ); - const { fetchStatus: chartFetchStatus, response, error } = useDataState(savedSearchData$.charts$); + /** + * Chart + */ - const { bucketInterval, chartData } = useMemo( - () => - isPlainRecord || !isTimeBased - ? { bucketInterval: undefined, chartData: undefined } - : buildChartData({ - data, - dataView, - timeInterval: state.interval, - response, - }), - [data, dataView, isPlainRecord, isTimeBased, response, state.interval] + const onChartHiddenChange = useCallback( + (chartHidden: boolean) => { + storage.set(CHART_HIDDEN_KEY, chartHidden); + stateContainer.setAppState({ hideChart: chartHidden }); + }, + [stateContainer, storage] + ); + + const onChartLoad = useCallback( + (event: UnifiedHistogramChartLoadEvent) => { + // We need to store the Lens request adapter in order to inspect its requests + inspectorAdapters.lensRequests = event.adapters.requests; + }, + [inspectorAdapters] ); + const [chartHidden, setChartHidden] = useState(state.hideChart); const chart = useMemo( () => isPlainRecord || !isTimeBased ? undefined : { - status: chartFetchStatus, - hidden: state.hideChart, + hidden: chartHidden, timeInterval: state.interval, - bucketInterval, - data: chartData, - error, }, - [ - bucketInterval, - chartData, - chartFetchStatus, - error, - isPlainRecord, - isTimeBased, - state.hideChart, - state.interval, - ] + [chartHidden, isPlainRecord, isTimeBased, state.interval] + ); + + // Clear the Lens request adapter when the chart is hidden + useEffect(() => { + if (chartHidden || !chart) { + inspectorAdapters.lensRequests = undefined; + } + }, [chart, chartHidden, inspectorAdapters]); + + // state.chartHidden is updated before searchSessionId, which can trigger duplicate + // requests, so instead of using state.chartHidden directly, we update chartHidden + // when searchSessionId changes + useEffect(() => { + setChartHidden(state.hideChart); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [searchSessionId]); + + /** + * Breakdown + */ + + const onBreakdownFieldChange = useCallback( + (breakdownField: DataViewField | undefined) => { + stateContainer.setAppState({ breakdownField: breakdownField?.name }); + }, + [stateContainer] + ); + + const field = useMemo( + () => (state.breakdownField ? dataView.getFieldByName(state.breakdownField) : undefined), + [dataView, state.breakdownField] + ); + + const breakdown = useMemo( + () => (isPlainRecord || !isTimeBased ? undefined : { field }), + [field, isPlainRecord, isTimeBased] ); - return { - topPanelHeight, - hits, - chart, - onEditVisualization: canVisualize ? onEditVisualization : undefined, - onTopPanelHeightChange, - onChartHiddenChange, - onTimeIntervalChange, - }; + // Don't render the unified histogram layout until the first search has been requested + return searchSessionId + ? { + topPanelHeight, + request, + hits, + chart, + breakdown, + onEditVisualization: canVisualize ? onEditVisualization : undefined, + onTopPanelHeightChange, + onChartHiddenChange, + onTimeIntervalChange, + onBreakdownFieldChange, + onTotalHitsChange, + onChartLoad, + } + : undefined; }; diff --git a/src/plugins/discover/public/application/main/components/loading_spinner/loading_spinner.scss b/src/plugins/discover/public/application/main/components/loading_spinner/loading_spinner.scss deleted file mode 100644 index a58897e43b615..0000000000000 --- a/src/plugins/discover/public/application/main/components/loading_spinner/loading_spinner.scss +++ /dev/null @@ -1,4 +0,0 @@ -.dscLoading { - text-align: center; - padding: $euiSizeL 0; -} diff --git a/src/plugins/discover/public/application/main/components/loading_spinner/loading_spinner.tsx b/src/plugins/discover/public/application/main/components/loading_spinner/loading_spinner.tsx index 949880d6c27d0..1879b5267bbf5 100644 --- a/src/plugins/discover/public/application/main/components/loading_spinner/loading_spinner.tsx +++ b/src/plugins/discover/public/application/main/components/loading_spinner/loading_spinner.tsx @@ -6,15 +6,32 @@ * Side Public License, v 1. */ -import './loading_spinner.scss'; - import React from 'react'; -import { EuiLoadingSpinner, EuiTitle, EuiSpacer } from '@elastic/eui'; +import { + EuiLoadingSpinner, + EuiTitle, + EuiSpacer, + useEuiPaddingSize, + useEuiBackgroundColor, +} from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; +import { css } from '@emotion/react'; export function LoadingSpinner() { + const loadingSpinnerCss = css` + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + text-align: center; + padding: ${useEuiPaddingSize('l')} 0; + background-color: ${useEuiBackgroundColor('plain')}; + z-index: 3; + `; + return ( -
+

diff --git a/src/plugins/discover/public/application/main/components/sidebar/__stories__/discover_field_details.stories.tsx b/src/plugins/discover/public/application/main/components/sidebar/__stories__/discover_field_details.stories.tsx deleted file mode 100644 index 9b02ffd15a282..0000000000000 --- a/src/plugins/discover/public/application/main/components/sidebar/__stories__/discover_field_details.stories.tsx +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 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 { storiesOf } from '@storybook/react'; -import React from 'react'; -import { KBN_FIELD_TYPES } from '@kbn/field-types'; -import { DataViewField } from '@kbn/data-views-plugin/public'; -import { DataView } from '@kbn/data-views-plugin/public'; -import { DiscoverFieldDetails } from '../discover_field_details'; -import { fieldSpecMap } from './fields'; -import { numericField as field } from './fields'; -import { Bucket } from '../types'; - -const buckets = [ - { count: 1, display: 'Stewart', percent: 50.0, value: 'Stewart' }, - { count: 1, display: 'Perry', percent: 50.0, value: 'Perry' }, -] as Bucket[]; -const details = { buckets, error: '', exists: 1, total: 2, columns: [] }; - -const fieldFormatInstanceType = {}; -const defaultMap = { - [KBN_FIELD_TYPES.NUMBER]: { id: KBN_FIELD_TYPES.NUMBER, params: {} }, -}; - -const fieldFormat = { - getByFieldType: (fieldType: KBN_FIELD_TYPES) => { - return [fieldFormatInstanceType]; - }, - getDefaultConfig: () => { - return defaultMap.number; - }, - defaultMap, -}; - -const scriptedField = new DataViewField({ - name: 'machine.os', - type: 'string', - esTypes: ['long'], - count: 10, - scripted: true, - searchable: true, - aggregatable: true, - readFromDocValues: true, -}); - -const dataView = new DataView({ - spec: { - id: 'logstash-*', - fields: fieldSpecMap, - title: 'logstash-*', - timeFieldName: '@timestamp', - }, - metaFields: ['_id', '_type', '_source'], - shortDotsEnable: false, - // @ts-expect-error - fieldFormats: fieldFormat, -}); - -storiesOf('components/sidebar/DiscoverFieldDetails', module) - .add('default', () => ( -
- { - alert('On add filter clicked'); - }} - /> -
- )) - .add('scripted', () => ( -
- {}} - /> -
- )) - .add('error', () => ( - {}} - /> - )); diff --git a/src/plugins/discover/public/application/main/components/sidebar/__stories__/fields.ts b/src/plugins/discover/public/application/main/components/sidebar/__stories__/fields.ts deleted file mode 100644 index 04f1cb9eb618b..0000000000000 --- a/src/plugins/discover/public/application/main/components/sidebar/__stories__/fields.ts +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 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 { DataViewField, FieldSpec } from '@kbn/data-views-plugin/public'; - -export const fieldSpecMap: Record = { - 'machine.os': { - name: 'machine.os', - esTypes: ['text'], - type: 'string', - aggregatable: false, - searchable: false, - }, - 'machine.os.raw': { - name: 'machine.os.raw', - type: 'string', - esTypes: ['keyword'], - aggregatable: true, - searchable: true, - }, - 'not.filterable': { - name: 'not.filterable', - type: 'string', - esTypes: ['text'], - aggregatable: true, - searchable: false, - }, - bytes: { - name: 'bytes', - type: 'number', - esTypes: ['long'], - aggregatable: true, - searchable: true, - }, -}; - -export const numericField = new DataViewField({ - name: 'bytes', - type: 'number', - esTypes: ['long'], - count: 10, - scripted: false, - searchable: true, - aggregatable: true, - readFromDocValues: true, -}); diff --git a/src/plugins/discover/public/application/main/components/sidebar/discover_field_bucket.scss b/src/plugins/discover/public/application/main/components/sidebar/deprecated_stats/discover_field_bucket.scss similarity index 100% rename from src/plugins/discover/public/application/main/components/sidebar/discover_field_bucket.scss rename to src/plugins/discover/public/application/main/components/sidebar/deprecated_stats/discover_field_bucket.scss diff --git a/src/plugins/discover/public/application/main/components/sidebar/discover_field_bucket.tsx b/src/plugins/discover/public/application/main/components/sidebar/deprecated_stats/discover_field_bucket.tsx similarity index 100% rename from src/plugins/discover/public/application/main/components/sidebar/discover_field_bucket.tsx rename to src/plugins/discover/public/application/main/components/sidebar/deprecated_stats/discover_field_bucket.tsx diff --git a/src/plugins/discover/public/application/main/components/sidebar/discover_field_details.test.tsx b/src/plugins/discover/public/application/main/components/sidebar/deprecated_stats/discover_field_details.test.tsx similarity index 73% rename from src/plugins/discover/public/application/main/components/sidebar/discover_field_details.test.tsx rename to src/plugins/discover/public/application/main/components/sidebar/deprecated_stats/discover_field_details.test.tsx index 9338bd36ceab2..535459c880988 100644 --- a/src/plugins/discover/public/application/main/components/sidebar/discover_field_details.test.tsx +++ b/src/plugins/discover/public/application/main/components/sidebar/deprecated_stats/discover_field_details.test.tsx @@ -12,7 +12,11 @@ import { mountWithIntl } from '@kbn/test-jest-helpers'; import { DiscoverFieldDetails } from './discover_field_details'; import { DataViewField } from '@kbn/data-views-plugin/public'; -import { stubDataView } from '@kbn/data-views-plugin/common/data_view.stub'; +import { stubDataView, stubLogstashDataView } from '@kbn/data-views-plugin/common/data_view.stub'; +import { BehaviorSubject } from 'rxjs'; +import { FetchStatus } from '../../../../types'; +import { DataDocuments$ } from '../../../hooks/use_saved_search'; +import { getDataTableRecords } from '../../../../../__fixtures__/real_hits'; describe('discover sidebar field details', function () { const onAddFilter = jest.fn(); @@ -21,9 +25,14 @@ describe('discover sidebar field details', function () { details: { buckets: [], error: '', exists: 1, total: 2, columns: [] }, onAddFilter, }; + const hits = getDataTableRecords(stubLogstashDataView); + const documents$ = new BehaviorSubject({ + fetchStatus: FetchStatus.COMPLETE, + result: hits, + }) as DataDocuments$; function mountComponent(field: DataViewField) { - const compProps = { ...defaultProps, field }; + const compProps = { ...defaultProps, field, documents$ }; return mountWithIntl(); } diff --git a/src/plugins/discover/public/application/main/components/sidebar/discover_field_details.tsx b/src/plugins/discover/public/application/main/components/sidebar/deprecated_stats/discover_field_details.tsx similarity index 69% rename from src/plugins/discover/public/application/main/components/sidebar/discover_field_details.tsx rename to src/plugins/discover/public/application/main/components/sidebar/deprecated_stats/discover_field_details.tsx index 69e5c01df07e5..58db010c025c9 100644 --- a/src/plugins/discover/public/application/main/components/sidebar/discover_field_details.tsx +++ b/src/plugins/discover/public/application/main/components/sidebar/deprecated_stats/discover_field_details.tsx @@ -6,28 +6,52 @@ * Side Public License, v 1. */ -import React from 'react'; -import { EuiText, EuiSpacer, EuiLink } from '@elastic/eui'; +import React, { useMemo } from 'react'; +import { i18n } from '@kbn/i18n'; +import { EuiText, EuiSpacer, EuiLink, EuiTitle } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import { DataViewField, DataView } from '@kbn/data-views-plugin/public'; import { DiscoverFieldBucket } from './discover_field_bucket'; import { Bucket, FieldDetails } from './types'; +import { getDetails } from './get_details'; +import { DataDocuments$ } from '../../../hooks/use_saved_search'; +import { FetchStatus } from '../../../../types'; interface DiscoverFieldDetailsProps { + /** + * hits fetched from ES, displayed in the doc table + */ + documents$: DataDocuments$; field: DataViewField; dataView: DataView; - details: FieldDetails; onAddFilter?: (field: DataViewField | string, value: string, type: '+' | '-') => void; } export function DiscoverFieldDetails({ + documents$, field, dataView, - details, onAddFilter, }: DiscoverFieldDetailsProps) { + const details: FieldDetails = useMemo(() => { + const data = documents$.getValue(); + const documents = data.fetchStatus === FetchStatus.COMPLETE ? data.result : undefined; + return getDetails(field, documents, dataView); + }, [field, documents$, dataView]); + + if (!details?.error && !details?.buckets) { + return null; + } + return ( - <> +
+ +
+ {i18n.translate('discover.fieldChooser.discoverField.fieldTopValuesLabel', { + defaultMessage: 'Top 5 values', + })} +
+
{details.error && {details.error}} {!details.error && ( <> @@ -70,6 +94,6 @@ export function DiscoverFieldDetails({ )} - +
); } diff --git a/src/plugins/discover/public/application/main/components/sidebar/lib/field_calculator.js b/src/plugins/discover/public/application/main/components/sidebar/deprecated_stats/field_calculator.js similarity index 100% rename from src/plugins/discover/public/application/main/components/sidebar/lib/field_calculator.js rename to src/plugins/discover/public/application/main/components/sidebar/deprecated_stats/field_calculator.js diff --git a/src/plugins/discover/public/application/main/components/sidebar/lib/field_calculator.test.ts b/src/plugins/discover/public/application/main/components/sidebar/deprecated_stats/field_calculator.test.ts similarity index 100% rename from src/plugins/discover/public/application/main/components/sidebar/lib/field_calculator.test.ts rename to src/plugins/discover/public/application/main/components/sidebar/deprecated_stats/field_calculator.test.ts diff --git a/src/plugins/discover/public/application/main/components/sidebar/lib/get_details.ts b/src/plugins/discover/public/application/main/components/sidebar/deprecated_stats/get_details.ts similarity index 100% rename from src/plugins/discover/public/application/main/components/sidebar/lib/get_details.ts rename to src/plugins/discover/public/application/main/components/sidebar/deprecated_stats/get_details.ts diff --git a/src/plugins/discover/public/application/main/components/sidebar/string_progress_bar.tsx b/src/plugins/discover/public/application/main/components/sidebar/deprecated_stats/string_progress_bar.tsx similarity index 100% rename from src/plugins/discover/public/application/main/components/sidebar/string_progress_bar.tsx rename to src/plugins/discover/public/application/main/components/sidebar/deprecated_stats/string_progress_bar.tsx diff --git a/src/plugins/discover/public/application/main/components/sidebar/types.ts b/src/plugins/discover/public/application/main/components/sidebar/deprecated_stats/types.ts similarity index 86% rename from src/plugins/discover/public/application/main/components/sidebar/types.ts rename to src/plugins/discover/public/application/main/components/sidebar/deprecated_stats/types.ts index 45921f676f144..1f7d40418fe7b 100644 --- a/src/plugins/discover/public/application/main/components/sidebar/types.ts +++ b/src/plugins/discover/public/application/main/components/sidebar/deprecated_stats/types.ts @@ -6,12 +6,6 @@ * Side Public License, v 1. */ -export interface IndexPatternRef { - id: string; - title: string; - name?: string; -} - export interface FieldDetails { error: string; exists: number; diff --git a/src/plugins/discover/public/application/main/components/sidebar/discover_field.test.tsx b/src/plugins/discover/public/application/main/components/sidebar/discover_field.test.tsx index c147289af983c..82e3e462dbd3a 100644 --- a/src/plugins/discover/public/application/main/components/sidebar/discover_field.test.tsx +++ b/src/plugins/discover/public/application/main/components/sidebar/discover_field.test.tsx @@ -9,18 +9,22 @@ import { act } from 'react-dom/test-utils'; import { EuiPopover, EuiProgress, EuiButtonIcon } from '@elastic/eui'; import React from 'react'; +import { BehaviorSubject } from 'rxjs'; import { findTestSubject } from '@elastic/eui/lib/test'; import { mountWithIntl } from '@kbn/test-jest-helpers'; -import { chartPluginMock } from '@kbn/charts-plugin/public/mocks'; -import { dataViewPluginMocks } from '@kbn/data-views-plugin/public/mocks'; -import { fieldFormatsServiceMock } from '@kbn/field-formats-plugin/public/mocks'; -import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; import { DiscoverField, DiscoverFieldProps } from './discover_field'; import { DataViewField } from '@kbn/data-views-plugin/public'; import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; import { stubDataView } from '@kbn/data-views-plugin/common/data_view.stub'; import { DiscoverAppStateProvider } from '../../services/discover_app_state_container'; import { getDiscoverStateMock } from '../../../../__mocks__/discover_state.mock'; +import { FetchStatus } from '../../../types'; +import { DataDocuments$ } from '../../hooks/use_saved_search'; +import { getDataTableRecords } from '../../../../__fixtures__/real_hits'; +import * as DetailsUtil from './deprecated_stats/get_details'; +import { createDiscoverServicesMock } from '../../../../__mocks__/services'; + +jest.spyOn(DetailsUtil, 'getDetails'); jest.mock('@kbn/unified-field-list-plugin/public/services/field_stats', () => ({ loadFieldStats: jest.fn().mockResolvedValue({ @@ -42,8 +46,6 @@ jest.mock('@kbn/unified-field-list-plugin/public/services/field_stats', () => ({ }), })); -const dataServiceMock = dataPluginMock.createStartContract(); - jest.mock('../../../../kibana_services', () => ({ getUiActions: jest.fn(() => { return { @@ -80,10 +82,16 @@ async function getComponent({ const dataView = stubDataView; dataView.toSpec = () => ({}); + const hits = getDataTableRecords(dataView); + const documents$ = new BehaviorSubject({ + fetchStatus: FetchStatus.COMPLETE, + result: hits, + }) as DataDocuments$; + const props: DiscoverFieldProps = { + documents$, dataView: stubDataView, field: finalField, - getDetails: jest.fn(() => ({ buckets: [], error: '', exists: 1, total: 2 })), ...(onAddFilterExists && { onAddFilter: jest.fn() }), onAddField: jest.fn(), onEditField: jest.fn(), @@ -93,11 +101,7 @@ async function getComponent({ contextualFields: [], }; const services = { - history: () => ({ - location: { - search: '', - }, - }), + ...createDiscoverServicesMock(), capabilities: { visualize: { show: true, @@ -113,29 +117,6 @@ async function getComponent({ } }, }, - data: { - ...dataServiceMock, - query: { - ...dataServiceMock.query, - timefilter: { - ...dataServiceMock.query.timefilter, - timefilter: { - ...dataServiceMock.query.timefilter.timefilter, - getAbsoluteTime: () => ({ - from: '2021-08-31T22:00:00.000Z', - to: '2022-09-01T09:16:29.553Z', - }), - }, - }, - getState: () => ({ - query: { query: '', language: 'lucene' }, - filters: [], - }), - }, - }, - dataViews: dataViewPluginMocks.createStartContract(), - fieldFormats: fieldFormatsServiceMock.createStartContract(), - charts: chartPluginMock.createSetupContract(), }; const appStateContainer = getDiscoverStateMock({ isTimeBased: true }).appStateContainer; appStateContainer.set({ @@ -156,6 +137,10 @@ async function getComponent({ } describe('discover sidebar field', function () { + beforeEach(() => { + (DetailsUtil.getDetails as jest.Mock).mockClear(); + }); + it('should allow selecting fields', async function () { const { comp, props } = await getComponent({}); findTestSubject(comp, 'fieldToggle-bytes').simulate('click'); @@ -166,14 +151,15 @@ describe('discover sidebar field', function () { findTestSubject(comp, 'fieldToggle-bytes').simulate('click'); expect(props.onRemoveField).toHaveBeenCalledWith('bytes'); }); - it('should trigger getDetails', async function () { + it('should trigger getDetails for showing the deprecated field stats', async function () { const { comp, props } = await getComponent({ selected: true, showFieldStats: true, showLegacyFieldTopValues: true, }); findTestSubject(comp, 'field-bytes-showDetails').simulate('click'); - expect(props.getDetails).toHaveBeenCalledWith(props.field); + expect(DetailsUtil.getDetails).toHaveBeenCalledTimes(1); + expect(findTestSubject(comp, `discoverFieldDetails-${props.field.name}`).exists()).toBeTruthy(); }); it('should not allow clicking on _source', async function () { const field = new DataViewField({ @@ -184,13 +170,13 @@ describe('discover sidebar field', function () { aggregatable: true, readFromDocValues: true, }); - const { comp, props } = await getComponent({ + const { comp } = await getComponent({ selected: true, field, showLegacyFieldTopValues: true, }); findTestSubject(comp, 'field-_source-showDetails').simulate('click'); - expect(props.getDetails).not.toHaveBeenCalled(); + expect(DetailsUtil.getDetails).not.toHaveBeenCalledWith(); }); it('displays warning for conflicting fields', async function () { const field = new DataViewField({ @@ -209,16 +195,16 @@ describe('discover sidebar field', function () { expect(dscField.find('.kbnFieldButton__infoIcon').length).toEqual(1); }); it('should not execute getDetails when rendered, since it can be expensive', async function () { - const { props } = await getComponent({}); - expect(props.getDetails).toHaveBeenCalledTimes(0); + await getComponent({}); + expect(DetailsUtil.getDetails).toHaveBeenCalledTimes(0); }); it('should execute getDetails when show details is requested', async function () { - const { props, comp } = await getComponent({ + const { comp } = await getComponent({ showFieldStats: true, showLegacyFieldTopValues: true, }); findTestSubject(comp, 'field-bytes-showDetails').simulate('click'); - expect(props.getDetails).toHaveBeenCalledTimes(1); + expect(DetailsUtil.getDetails).toHaveBeenCalledTimes(1); }); it('should not return the popover if onAddFilter is not provided', async function () { const field = new DataViewField({ diff --git a/src/plugins/discover/public/application/main/components/sidebar/discover_field.tsx b/src/plugins/discover/public/application/main/components/sidebar/discover_field.tsx index 5513483b2b03c..18cbabf97e058 100644 --- a/src/plugins/discover/public/application/main/components/sidebar/discover_field.tsx +++ b/src/plugins/discover/public/application/main/components/sidebar/discover_field.tsx @@ -9,7 +9,14 @@ import './discover_field.scss'; import React, { useState, useCallback, memo, useMemo } from 'react'; -import { EuiButtonIcon, EuiToolTip, EuiTitle, EuiIcon, EuiSpacer } from '@elastic/eui'; +import { + EuiButtonIcon, + EuiToolTip, + EuiTitle, + EuiIcon, + EuiSpacer, + EuiHighlight, +} from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { UiCounterMetricType } from '@kbn/analytics'; import classNames from 'classnames'; @@ -23,12 +30,12 @@ import { } from '@kbn/unified-field-list-plugin/public'; import { DiscoverFieldStats } from './discover_field_stats'; import { getTypeForFieldIcon } from '../../../../utils/get_type_for_field_icon'; -import { DiscoverFieldDetails } from './discover_field_details'; -import { FieldDetails } from './types'; +import { DiscoverFieldDetails } from './deprecated_stats/discover_field_details'; import { getFieldTypeName } from '../../../../utils/get_field_type_name'; import { useDiscoverServices } from '../../../../hooks/use_discover_services'; import { SHOW_LEGACY_FIELD_TOP_VALUES, PLUGIN_ID } from '../../../../../common'; import { getUiActions } from '../../../../kibana_services'; +import { type DataDocuments$ } from '../../hooks/use_saved_search'; function wrapOnDot(str?: string) { // u200B is a non-width white-space character, which allows @@ -64,24 +71,31 @@ const DiscoverFieldTypeIcon: React.FC<{ field: DataViewField }> = memo(({ field ); }); -const FieldName: React.FC<{ field: DataViewField }> = memo(({ field }) => { - const title = - field.displayName !== field.name - ? i18n.translate('discover.field.title', { - defaultMessage: '{fieldName} ({fieldDisplayName})', - values: { - fieldName: field.name, - fieldDisplayName: field.displayName, - }, - }) - : field.displayName; +const FieldName: React.FC<{ field: DataViewField; highlight?: string }> = memo( + ({ field, highlight }) => { + const title = + field.displayName !== field.name + ? i18n.translate('discover.field.title', { + defaultMessage: '{fieldName} ({fieldDisplayName})', + values: { + fieldName: field.name, + fieldDisplayName: field.displayName, + }, + }) + : field.displayName; - return ( - - {wrapOnDot(field.displayName)} - - ); -}); + return ( + + {wrapOnDot(field.displayName)} + + ); + } +); interface ActionButtonProps { field: DataViewField; @@ -128,6 +142,7 @@ const ActionButton: React.FC = memo( } else { return ( ; toggleDisplay: (field: DataViewField) => void; alwaysShowActionButton: boolean; - isDocumentRecord: boolean; } const MultiFields: React.FC = memo( - ({ multiFields, toggleDisplay, alwaysShowActionButton, isDocumentRecord }) => ( + ({ multiFields, toggleDisplay, alwaysShowActionButton }) => (
@@ -184,7 +198,7 @@ const MultiFields: React.FC = memo( className="dscSidebarItem dscSidebarItem--multi" isActive={false} dataTestSubj={`field-${entry.field.name}-showDetails`} - fieldIcon={isDocumentRecord && } + fieldIcon={} fieldAction={ = memo( ); export interface DiscoverFieldProps { + /** + * hits fetched from ES, displayed in the doc table + */ + documents$: DataDocuments$; /** * Determines whether add/remove button is displayed not only when focused */ @@ -227,10 +245,6 @@ export interface DiscoverFieldProps { * @param fieldName */ onRemoveField: (fieldName: string) => void; - /** - * Retrieve details data for the field - */ - getDetails: (field: DataViewField) => FieldDetails; /** * Determines whether the field is selected */ @@ -264,16 +278,22 @@ export interface DiscoverFieldProps { * Columns */ contextualFields: string[]; + + /** + * Search by field name + */ + highlight?: string; } function DiscoverFieldComponent({ + documents$, alwaysShowActionButton = false, field, + highlight, dataView, onAddField, onRemoveField, onAddFilter, - getDetails, selected, trackUiMetric, multiFields, @@ -345,7 +365,7 @@ function DiscoverFieldComponent({ size="s" className="dscSidebarItem" dataTestSubj={`field-${field.name}-showDetails`} - fieldIcon={isDocumentRecord && } + fieldIcon={} fieldAction={ } + fieldIcon={} fieldAction={ } - fieldName={} + fieldName={} fieldInfoIcon={field.type === 'conflict' && } /> ); @@ -389,24 +409,15 @@ function DiscoverFieldComponent({ return ( <> - {showLegacyFieldStats ? ( + {showLegacyFieldStats ? ( // TODO: Deprecate and remove after ~v8.7 <> {showFieldStats && ( - <> - -
- {i18n.translate('discover.fieldChooser.discoverField.fieldTopValuesLabel', { - defaultMessage: 'Top 5 values', - })} -
-
- - + )} ) : ( @@ -425,7 +436,6 @@ function DiscoverFieldComponent({ multiFields={multiFields} alwaysShowActionButton={alwaysShowActionButton} toggleDisplay={toggleDisplay} - isDocumentRecord={isDocumentRecord} /> )} diff --git a/src/plugins/discover/public/application/main/components/sidebar/discover_field_search.test.tsx b/src/plugins/discover/public/application/main/components/sidebar/discover_field_search.test.tsx index 55ad5eadaf81d..eafe3fec1eeaf 100644 --- a/src/plugins/discover/public/application/main/components/sidebar/discover_field_search.test.tsx +++ b/src/plugins/discover/public/application/main/components/sidebar/discover_field_search.test.tsx @@ -44,6 +44,7 @@ describe('DiscoverFieldSearch', () => { const input = findTestSubject(component, 'fieldFilterSearchInput'); input.simulate('change', { target: { value: 'new filter' } }); expect(defaultProps.onChange).toBeCalledTimes(1); + expect(defaultProps.onChange).toHaveBeenCalledWith('name', 'new filter'); }); test('change in active filters should change facet selection and call onChange', () => { @@ -97,30 +98,17 @@ describe('DiscoverFieldSearch', () => { expect(badge.text()).toEqual('1'); }); - test('change in missing fields switch should not change filter count', () => { - const component = mountComponent(); - const btn = findTestSubject(component, 'toggleFieldFilterButton'); - btn.simulate('click'); - const badge = btn.find('.euiNotificationBadge').last(); - expect(badge.text()).toEqual('0'); - const missingSwitch = findTestSubject(component, 'missingSwitch'); - missingSwitch.simulate('change', { target: { value: false } }); - expect(badge.text()).toEqual('0'); - }); - test('change in filters triggers onChange', () => { const onChange = jest.fn(); const component = mountComponent({ ...defaultProps, ...{ onChange } }); const btn = findTestSubject(component, 'toggleFieldFilterButton'); btn.simulate('click'); const aggregtableButtonGroup = findButtonGroup(component, 'aggregatable'); - const missingSwitch = findTestSubject(component, 'missingSwitch'); act(() => { // @ts-expect-error (aggregtableButtonGroup.props() as EuiButtonGroupProps).onChange('aggregatable-true', null); }); - missingSwitch.simulate('click'); - expect(onChange).toBeCalledTimes(2); + expect(onChange).toBeCalledTimes(1); }); test('change in type filters triggers onChange with appropriate value', () => { diff --git a/src/plugins/discover/public/application/main/components/sidebar/discover_field_search.tsx b/src/plugins/discover/public/application/main/components/sidebar/discover_field_search.tsx index 59ba2833d94f5..8d7103f70efe9 100644 --- a/src/plugins/discover/public/application/main/components/sidebar/discover_field_search.tsx +++ b/src/plugins/discover/public/application/main/components/sidebar/discover_field_search.tsx @@ -17,11 +17,8 @@ import { EuiFlexGroup, EuiFlexItem, EuiPopover, - EuiPopoverFooter, EuiPopoverTitle, EuiSelect, - EuiSwitch, - EuiSwitchEvent, EuiForm, EuiFormRow, EuiButtonGroup, @@ -43,7 +40,6 @@ export interface State { searchable: string; aggregatable: string; type: string; - missing: boolean; [index: string]: string | boolean; } @@ -68,6 +64,11 @@ export interface Props { * is text base lang mode */ isPlainRecord: boolean; + + /** + * For a11y + */ + fieldSearchDescriptionId?: string; } interface FieldTypeTableItem { @@ -86,6 +87,7 @@ export function DiscoverFieldSearch({ types, presentFieldTypes, isPlainRecord, + fieldSearchDescriptionId, }: Props) { const searchPlaceholder = i18n.translate('discover.fieldChooser.searchPlaceHolder', { defaultMessage: 'Search field names', @@ -112,7 +114,6 @@ export function DiscoverFieldSearch({ searchable: 'any', aggregatable: 'any', type: 'any', - missing: true, }); const { docLinks } = useDiscoverServices(); @@ -191,7 +192,7 @@ export function DiscoverFieldSearch({ }; const isFilterActive = (name: string, filterValue: string | boolean) => { - return name !== 'missing' && filterValue !== 'any'; + return filterValue !== 'any'; }; const handleValueChange = (name: string, filterValue: string | boolean) => { @@ -214,11 +215,6 @@ export function DiscoverFieldSearch({ setActiveFiltersCount(activeFiltersCount + diff); }; - const handleMissingChange = (e: EuiSwitchEvent) => { - const missingValue = e.target.checked; - handleValueChange('missing', missingValue); - }; - const buttonContent = ( { - return ( - - - - ); - }; - const selectionPanel = (
@@ -353,10 +334,11 @@ export function DiscoverFieldSearch({ onChange('name', event.currentTarget.value)} + onChange={(event) => onChange('name', event.target.value)} placeholder={searchPlaceholder} value={value} /> @@ -384,7 +366,6 @@ export function DiscoverFieldSearch({ })} {selectionPanel} - {footer()} = React.memo( ({ field, dataView, multiFields, onAddFilter }) => { const services = useDiscoverServices(); - const dateRange = services.data?.query?.timefilter.timefilter.getAbsoluteTime(); const querySubscriberResult = useQuerySubscriber({ data: services.data, }); @@ -38,7 +38,7 @@ export const DiscoverFieldStats: React.FC = React.memo( [field, multiFields] ); - if (!dateRange || !querySubscriberResult.query || !querySubscriberResult.filters) { + if (!hasQuerySubscriberData(querySubscriberResult)) { return null; } @@ -47,8 +47,8 @@ export const DiscoverFieldStats: React.FC = React.memo( services={services} query={querySubscriberResult.query} filters={querySubscriberResult.filters} - fromDate={dateRange.from} - toDate={dateRange.to} + fromDate={querySubscriberResult.fromDate} + toDate={querySubscriberResult.toDate} dataViewOrDataViewId={dataView} field={fieldForStats} data-test-subj="dscFieldStats" diff --git a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar.scss b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar.scss index 4a0f048947706..d7190b61e33f3 100644 --- a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar.scss +++ b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar.scss @@ -31,20 +31,6 @@ align-items: center; } -.dscFieldList { - padding: 0 $euiSizeXS $euiSizeXS; -} - -.dscFieldListHeader { - padding: $euiSizeS $euiSizeS 0 $euiSizeS; - background-color: lightOrDarkTheme(tint($euiColorPrimary, 90%), $euiColorLightShade); -} - -.dscFieldList--popular { - padding-bottom: $euiSizeS; - background-color: lightOrDarkTheme(tint($euiColorPrimary, 90%), $euiColorLightShade); -} - .dscSidebarItem { &:hover, &:focus-within, diff --git a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar.test.tsx b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar.test.tsx index 0e7e3b22ac3b3..ad59bad82aeb8 100644 --- a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar.test.tsx +++ b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar.test.tsx @@ -6,30 +6,38 @@ * Side Public License, v 1. */ import { ReactWrapper } from 'enzyme'; +import { act } from 'react-dom/test-utils'; import { findTestSubject } from '@elastic/eui/lib/test'; import { Action } from '@kbn/ui-actions-plugin/public'; import { getDataTableRecords } from '../../../../__fixtures__/real_hits'; import { mountWithIntl } from '@kbn/test-jest-helpers'; import React from 'react'; -import { DiscoverSidebarProps } from './discover_sidebar'; +import { + DiscoverSidebarComponent as DiscoverSidebar, + DiscoverSidebarProps, +} from './discover_sidebar'; import { DataViewListItem } from '@kbn/data-views-plugin/public'; - +import type { AggregateQuery, Query } from '@kbn/es-query'; import { getDefaultFieldFilter } from './lib/field_filter'; -import { DiscoverSidebarComponent as DiscoverSidebar } from './discover_sidebar'; -import { discoverServiceMock as mockDiscoverServices } from '../../../../__mocks__/services'; +import { createDiscoverServicesMock } from '../../../../__mocks__/services'; import { stubLogstashDataView } from '@kbn/data-plugin/common/stubs'; import { VIEW_MODE } from '../../../../components/view_mode_toggle'; import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; import { BehaviorSubject } from 'rxjs'; import { FetchStatus } from '../../../types'; -import { AvailableFields$ } from '../../hooks/use_saved_search'; +import { AvailableFields$, DataDocuments$ } from '../../hooks/use_saved_search'; import { getDiscoverStateMock } from '../../../../__mocks__/discover_state.mock'; import { DiscoverAppStateProvider } from '../../services/discover_app_state_container'; +import * as ExistingFieldsHookApi from '@kbn/unified-field-list-plugin/public/hooks/use_existing_fields'; +import { ExistenceFetchStatus } from '@kbn/unified-field-list-plugin/public'; +import { getDataViewFieldList } from './lib/get_data_view_field_list'; const mockGetActions = jest.fn>>, [string, { fieldName: string }]>( () => Promise.resolve([]) ); +jest.spyOn(ExistingFieldsHookApi, 'useExistingFieldsReader'); + jest.mock('../../../../kibana_services', () => ({ getUiActions: () => ({ getTriggerCompatibleActions: mockGetActions, @@ -41,12 +49,6 @@ function getCompProps(): DiscoverSidebarProps { dataView.toSpec = jest.fn(() => ({})); const hits = getDataTableRecords(dataView); - const dataViewList = [ - { id: '0', title: 'b' } as DataViewListItem, - { id: '1', title: 'a' } as DataViewListItem, - { id: '2', title: 'c' } as DataViewListItem, - ]; - const fieldCounts: Record = {}; for (const hit of hits) { @@ -54,16 +56,36 @@ function getCompProps(): DiscoverSidebarProps { fieldCounts[key] = (fieldCounts[key] || 0) + 1; } } + + const allFields = getDataViewFieldList(dataView, fieldCounts, false); + + (ExistingFieldsHookApi.useExistingFieldsReader as jest.Mock).mockClear(); + (ExistingFieldsHookApi.useExistingFieldsReader as jest.Mock).mockImplementation(() => ({ + hasFieldData: (dataViewId: string, fieldName: string) => { + return dataViewId === dataView.id && Object.keys(fieldCounts).includes(fieldName); + }, + getFieldsExistenceStatus: (dataViewId: string) => { + return dataViewId === dataView.id + ? ExistenceFetchStatus.succeeded + : ExistenceFetchStatus.unknown; + }, + isFieldsExistenceInfoUnavailable: (dataViewId: string) => dataViewId !== dataView.id, + })); + const availableFields$ = new BehaviorSubject({ fetchStatus: FetchStatus.COMPLETE, fields: [] as string[], }) as AvailableFields$; + const documents$ = new BehaviorSubject({ + fetchStatus: FetchStatus.COMPLETE, + result: hits, + }) as DataDocuments$; + return { columns: ['extension'], - fieldCounts, - documents: hits, - dataViewList, + allFields, + dataViewList: [dataView as DataViewListItem], onChangeDataView: jest.fn(), onAddFilter: jest.fn(), onAddField: jest.fn(), @@ -77,37 +99,38 @@ function getCompProps(): DiscoverSidebarProps { viewMode: VIEW_MODE.DOCUMENT_LEVEL, createNewDataView: jest.fn(), onDataViewCreated: jest.fn(), + documents$, availableFields$, useNewFieldsApi: true, + showFieldList: true, + isAffectedByGlobalFilter: false, }; } -function getAppStateContainer() { +function getAppStateContainer({ query }: { query?: Query | AggregateQuery }) { const appStateContainer = getDiscoverStateMock({ isTimeBased: true }).appStateContainer; appStateContainer.set({ - query: { query: '', language: 'lucene' }, + query: query ?? { query: '', language: 'lucene' }, filters: [], }); return appStateContainer; } -describe('discover sidebar', function () { - let props: DiscoverSidebarProps; +async function mountComponent( + props: DiscoverSidebarProps, + appStateParams: { query?: Query | AggregateQuery } = {} +): Promise> { let comp: ReactWrapper; + const mockedServices = createDiscoverServicesMock(); + mockedServices.data.dataViews.getIdsWithTitle = jest.fn(async () => props.dataViewList); + mockedServices.data.dataViews.get = jest.fn().mockImplementation(async (id) => { + return [props.selectedDataView].find((d) => d!.id === id); + }); - beforeAll(async () => { - props = getCompProps(); - mockDiscoverServices.data.dataViews.getIdsWithTitle = jest - .fn() - .mockReturnValue(props.dataViewList); - mockDiscoverServices.data.dataViews.get = jest.fn().mockImplementation((id) => { - const dataView = props.dataViewList.find((d) => d.id === id); - return { ...dataView, isPersisted: () => true }; - }); - + await act(async () => { comp = await mountWithIntl( - - + + @@ -117,24 +140,50 @@ describe('discover sidebar', function () { await comp.update(); }); - it('should have Selected Fields and Available Fields with Popular Fields sections', function () { - const popular = findTestSubject(comp, 'fieldList-popular'); - const selected = findTestSubject(comp, 'fieldList-selected'); - const unpopular = findTestSubject(comp, 'fieldList-unpopular'); - expect(popular.children().length).toBe(1); - expect(unpopular.children().length).toBe(6); - expect(selected.children().length).toBe(1); + await comp!.update(); + + return comp!; +} + +describe('discover sidebar', function () { + let props: DiscoverSidebarProps; + + beforeEach(async () => { + props = getCompProps(); + }); + + it('should hide field list', async function () { + const comp = await mountComponent({ + ...props, + showFieldList: false, + }); + expect(findTestSubject(comp, 'fieldListGroupedFieldGroups').exists()).toBe(false); + }); + it('should have Selected Fields and Available Fields with Popular Fields sections', async function () { + const comp = await mountComponent(props); + const popularFieldsCount = findTestSubject(comp, 'fieldListGroupedPopularFields-count'); + const selectedFieldsCount = findTestSubject(comp, 'fieldListGroupedSelectedFields-count'); + const availableFieldsCount = findTestSubject(comp, 'fieldListGroupedAvailableFields-count'); + expect(popularFieldsCount.text()).toBe('4'); + expect(availableFieldsCount.text()).toBe('3'); + expect(selectedFieldsCount.text()).toBe('1'); + expect(findTestSubject(comp, 'fieldListGroupedFieldGroups').exists()).toBe(true); }); - it('should allow selecting fields', function () { - findTestSubject(comp, 'fieldToggle-bytes').simulate('click'); + it('should allow selecting fields', async function () { + const comp = await mountComponent(props); + const availableFields = findTestSubject(comp, 'fieldListGroupedAvailableFields'); + findTestSubject(availableFields, 'fieldToggle-bytes').simulate('click'); expect(props.onAddField).toHaveBeenCalledWith('bytes'); }); - it('should allow deselecting fields', function () { - findTestSubject(comp, 'fieldToggle-extension').simulate('click'); + it('should allow deselecting fields', async function () { + const comp = await mountComponent(props); + const availableFields = findTestSubject(comp, 'fieldListGroupedAvailableFields'); + findTestSubject(availableFields, 'fieldToggle-extension').simulate('click'); expect(props.onRemoveField).toHaveBeenCalledWith('extension'); }); - it('should render "Add a field" button', () => { + it('should render "Add a field" button', async () => { + const comp = await mountComponent(props); const addFieldButton = findTestSubject(comp, 'dataView-add-field_btn'); expect(addFieldButton.length).toBe(1); addFieldButton.simulate('click'); @@ -142,8 +191,11 @@ describe('discover sidebar', function () { }); it('should render "Edit field" button', async () => { - findTestSubject(comp, 'field-bytes').simulate('click'); - await new Promise((resolve) => setTimeout(resolve, 0)); + const comp = await mountComponent(props); + const availableFields = findTestSubject(comp, 'fieldListGroupedAvailableFields'); + await act(async () => { + findTestSubject(availableFields, 'field-bytes').simulate('click'); + }); await comp.update(); const editFieldButton = findTestSubject(comp, 'discoverFieldListPanelEdit-bytes'); expect(editFieldButton.length).toBe(1); @@ -151,29 +203,27 @@ describe('discover sidebar', function () { expect(props.editField).toHaveBeenCalledWith('bytes'); }); - it('should not render Add/Edit field buttons in viewer mode', () => { - const compInViewerMode = mountWithIntl( - - - - - - ); + it('should not render Add/Edit field buttons in viewer mode', async () => { + const compInViewerMode = await mountComponent({ + ...getCompProps(), + editField: undefined, + }); const addFieldButton = findTestSubject(compInViewerMode, 'dataView-add-field_btn'); expect(addFieldButton.length).toBe(0); - findTestSubject(comp, 'field-bytes').simulate('click'); + const availableFields = findTestSubject(compInViewerMode, 'fieldListGroupedAvailableFields'); + await act(async () => { + findTestSubject(availableFields, 'field-bytes').simulate('click'); + }); const editFieldButton = findTestSubject(compInViewerMode, 'discoverFieldListPanelEdit-bytes'); expect(editFieldButton.length).toBe(0); }); it('should render buttons in data view picker correctly', async () => { - const compWithPicker = mountWithIntl( - - - - - - ); + const propsWithPicker = { + ...getCompProps(), + showDataViewPicker: true, + }; + const compWithPicker = await mountComponent(propsWithPicker); // open data view picker findTestSubject(compWithPicker, 'dataView-switch-link').simulate('click'); expect(findTestSubject(compWithPicker, 'changeDataViewPopover').length).toBe(1); @@ -184,27 +234,21 @@ describe('discover sidebar', function () { ); expect(addFieldButtonInDataViewPicker.length).toBe(1); addFieldButtonInDataViewPicker.simulate('click'); - expect(props.editField).toHaveBeenCalledWith(); + expect(propsWithPicker.editField).toHaveBeenCalledWith(); // click "Create a data view" const createDataViewButton = findTestSubject(compWithPicker, 'dataview-create-new'); expect(createDataViewButton.length).toBe(1); createDataViewButton.simulate('click'); - expect(props.createNewDataView).toHaveBeenCalled(); + expect(propsWithPicker.createNewDataView).toHaveBeenCalled(); }); it('should not render buttons in data view picker when in viewer mode', async () => { - const compWithPickerInViewerMode = mountWithIntl( - - - - - - ); + const compWithPickerInViewerMode = await mountComponent({ + ...getCompProps(), + showDataViewPicker: true, + editField: undefined, + createNewDataView: undefined, + }); // open data view picker findTestSubject(compWithPickerInViewerMode, 'dataView-switch-link').simulate('click'); expect(findTestSubject(compWithPickerInViewerMode, 'changeDataViewPopover').length).toBe(1); @@ -218,14 +262,10 @@ describe('discover sidebar', function () { expect(createDataViewButton.length).toBe(0); }); - it('should render the Visualize in Lens button in text based languages mode', () => { - const compInViewerMode = mountWithIntl( - - - - - - ); + it('should render the Visualize in Lens button in text based languages mode', async () => { + const compInViewerMode = await mountComponent(getCompProps(), { + query: { sql: 'SELECT * FROM test' }, + }); const visualizeField = findTestSubject(compInViewerMode, 'textBased-visualize'); expect(visualizeField.length).toBe(1); }); diff --git a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar.tsx b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar.tsx index 4735b75b66e14..109f11615335f 100644 --- a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar.tsx +++ b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar.tsx @@ -7,49 +7,48 @@ */ import './discover_sidebar.scss'; -import { throttle } from 'lodash'; -import React, { useCallback, useEffect, useState, useMemo, useRef, memo } from 'react'; +import React, { memo, useCallback, useEffect, useMemo, useState } from 'react'; import { i18n } from '@kbn/i18n'; import { - EuiAccordion, - EuiFlexItem, + EuiButton, EuiFlexGroup, - EuiText, - EuiTitle, - EuiSpacer, - EuiNotificationBadge, + EuiFlexItem, EuiPageSideBar_Deprecated as EuiPageSideBar, - useResizeObserver, - EuiButton, + htmlIdGenerator, } from '@elastic/eui'; import { isOfAggregateQueryType } from '@kbn/es-query'; -import useShallowCompareEffect from 'react-use/lib/useShallowCompareEffect'; -import { isEqual } from 'lodash'; -import { FormattedMessage } from '@kbn/i18n-react'; import { DataViewPicker } from '@kbn/unified-search-plugin/public'; -import { DataViewField, getFieldSubtypeMulti } from '@kbn/data-views-plugin/public'; -import { triggerVisualizeActionsTextBasedLanguages } from '@kbn/unified-field-list-plugin/public'; +import { type DataViewField, getFieldSubtypeMulti } from '@kbn/data-views-plugin/public'; +import { + FieldListGrouped, + FieldListGroupedProps, + FieldsGroupNames, + GroupedFieldsParams, + triggerVisualizeActionsTextBasedLanguages, + useExistingFieldsReader, + useGroupedFields, +} from '@kbn/unified-field-list-plugin/public'; import { useAppStateSelector } from '../../services/discover_app_state_container'; import { useDiscoverServices } from '../../../../hooks/use_discover_services'; import { DiscoverField } from './discover_field'; import { DiscoverFieldSearch } from './discover_field_search'; import { FIELDS_LIMIT_SETTING, PLUGIN_ID } from '../../../../../common'; -import { groupFields } from './lib/group_fields'; -import { getDetails } from './lib/get_details'; -import { FieldFilterState, getDefaultFieldFilter, setFieldFilterProp } from './lib/field_filter'; -import { getDataViewFieldList } from './lib/get_data_view_field_list'; +import { + getSelectedFields, + shouldShowField, + type SelectedFieldsResult, + INITIAL_SELECTED_FIELDS_RESULT, +} from './lib/group_fields'; +import { doesFieldMatchFilters, FieldFilterState, setFieldFilterProp } from './lib/field_filter'; import { DiscoverSidebarResponsiveProps } from './discover_sidebar_responsive'; import { VIEW_MODE } from '../../../../components/view_mode_toggle'; -import { DISCOVER_TOUR_STEP_ANCHOR_IDS } from '../../../../components/discover_tour'; -import type { DataTableRecord } from '../../../../types'; import { getUiActions } from '../../../../kibana_services'; +import { getRawRecordType } from '../../utils/get_raw_record_type'; +import { RecordRawType } from '../../hooks/use_saved_search'; -/** - * Default number of available fields displayed and added on scroll - */ -const FIELDS_PER_PAGE = 50; +const fieldSearchDescriptionId = htmlIdGenerator()(); -export interface DiscoverSidebarProps extends Omit { +export interface DiscoverSidebarProps extends DiscoverSidebarResponsiveProps { /** * Current state of the field filter, filtering fields by name, type, ... */ @@ -84,27 +83,37 @@ export interface DiscoverSidebarProps extends Omit void; /** - * a statistics of the distribution of fields in the given hits + * All fields: fields from data view and unmapped fields */ - fieldCounts?: Record; - /** - * hits fetched from ES, displayed in the doc table - */ - documents?: DataTableRecord[]; + allFields: DataViewField[] | null; + /** * Discover view mode */ viewMode: VIEW_MODE; + /** + * Show data view picker (for mobile view) + */ showDataViewPicker?: boolean; + + /** + * Whether to render the field list or not (we don't show it unless documents are loaded) + */ + showFieldList?: boolean; + + /** + * Whether filters are applied + */ + isAffectedByGlobalFilter: boolean; } export function DiscoverSidebarComponent({ alwaysShowActionButtons = false, columns, - fieldCounts, fieldFilter, - documents, + documents$, + allFields, onAddField, onAddFilter, onRemoveField, @@ -120,108 +129,28 @@ export function DiscoverSidebarComponent({ viewMode, createNewDataView, showDataViewPicker, + showFieldList, + isAffectedByGlobalFilter, }: DiscoverSidebarProps) { - const { uiSettings, dataViewFieldEditor } = useDiscoverServices(); - const [fields, setFields] = useState(null); - const [scrollContainer, setScrollContainer] = useState(null); - const [fieldsToRender, setFieldsToRender] = useState(FIELDS_PER_PAGE); - const [fieldsPerPage, setFieldsPerPage] = useState(FIELDS_PER_PAGE); - const availableFieldsContainer = useRef(null); - const isPlainRecord = !onAddFilter; + const { uiSettings, dataViewFieldEditor, dataViews } = useDiscoverServices(); + const isPlainRecord = useAppStateSelector( + (state) => getRawRecordType(state.query) === RecordRawType.PLAIN + ); const query = useAppStateSelector((state) => state.query); - useEffect(() => { - if (documents) { - const newFields = getDataViewFieldList(selectedDataView, fieldCounts); - setFields(newFields); - } - }, [selectedDataView, fieldCounts, documents]); - - const scrollDimensions = useResizeObserver(scrollContainer); - const onChangeFieldSearch = useCallback( - (field: string, value: string | boolean | undefined) => { - const newState = setFieldFilterProp(fieldFilter, field, value); + (filterName: string, value: string | boolean | undefined) => { + const newState = setFieldFilterProp(fieldFilter, filterName, value); setFieldFilter(newState); - setFieldsToRender(fieldsPerPage); }, - [fieldFilter, setFieldFilter, setFieldsToRender, fieldsPerPage] - ); - - const getDetailsByField = useCallback( - (ipField: DataViewField) => getDetails(ipField, documents, selectedDataView), - [documents, selectedDataView] + [fieldFilter, setFieldFilter] ); - const popularLimit = useMemo(() => uiSettings.get(FIELDS_LIMIT_SETTING), [uiSettings]); - - const { - selected: selectedFields, - popular: popularFields, - unpopular: unpopularFields, - } = useMemo( - () => groupFields(fields, columns, popularLimit, fieldCounts, fieldFilter, useNewFieldsApi), - [fields, columns, popularLimit, fieldCounts, fieldFilter, useNewFieldsApi] - ); - - /** - * Popular fields are not displayed in text based lang mode - */ - const restFields = useMemo( - () => (isPlainRecord ? [...popularFields, ...unpopularFields] : unpopularFields), - [isPlainRecord, popularFields, unpopularFields] - ); - - const paginate = useCallback(() => { - const newFieldsToRender = fieldsToRender + Math.round(fieldsPerPage * 0.5); - setFieldsToRender(Math.max(fieldsPerPage, Math.min(newFieldsToRender, restFields.length))); - }, [setFieldsToRender, fieldsToRender, restFields, fieldsPerPage]); - - useEffect(() => { - if (scrollContainer && restFields.length && availableFieldsContainer.current) { - const { clientHeight, scrollHeight } = scrollContainer; - const isScrollable = scrollHeight > clientHeight; // there is no scrolling currently - const allFieldsRendered = fieldsToRender >= restFields.length; - - if (!isScrollable && !allFieldsRendered) { - // Not all available fields were rendered with the given fieldsPerPage number - // and no scrolling is available due to the a high zoom out factor of the browser - // In this case the fieldsPerPage needs to be adapted - const fieldsRenderedHeight = availableFieldsContainer.current.clientHeight; - const avgHeightPerItem = Math.round(fieldsRenderedHeight / fieldsToRender); - const newFieldsPerPage = - (avgHeightPerItem > 0 ? Math.round(clientHeight / avgHeightPerItem) : 0) + 10; - if (newFieldsPerPage >= FIELDS_PER_PAGE && newFieldsPerPage !== fieldsPerPage) { - setFieldsPerPage(newFieldsPerPage); - setFieldsToRender(newFieldsPerPage); - } - } - } - }, [ - fieldsPerPage, - scrollContainer, - restFields, - fieldsToRender, - setFieldsPerPage, - setFieldsToRender, - scrollDimensions, - ]); - - const lazyScroll = useCallback(() => { - if (scrollContainer) { - const { scrollTop, clientHeight, scrollHeight } = scrollContainer; - const nearBottom = scrollTop + clientHeight > scrollHeight * 0.9; - if (nearBottom && restFields) { - paginate(); - } - } - }, [paginate, scrollContainer, restFields]); - const { fieldTypes, presentFieldTypes } = useMemo(() => { const result = ['any']; const dataViewFieldTypes = new Set(); - if (Array.isArray(fields)) { - for (const field of fields) { + if (Array.isArray(allFields)) { + for (const field of allFields) { if (field.type !== '_source') { // If it's a string type, we want to distinguish between keyword and text // For this purpose we need the ES type @@ -242,37 +171,36 @@ export function DiscoverSidebarComponent({ } } return { fieldTypes: result, presentFieldTypes: Array.from(dataViewFieldTypes) }; - }, [fields]); + }, [allFields]); const showFieldStats = useMemo(() => viewMode === VIEW_MODE.DOCUMENT_LEVEL, [viewMode]); + const [selectedFieldsState, setSelectedFieldsState] = useState( + INITIAL_SELECTED_FIELDS_RESULT + ); + const [multiFieldsMap, setMultiFieldsMap] = useState< + Map> | undefined + >(undefined); - const calculateMultiFields = () => { - if (!useNewFieldsApi || !fields) { - return undefined; - } - const map = new Map>(); - fields.forEach((field) => { - const subTypeMulti = getFieldSubtypeMulti(field); - const parent = subTypeMulti?.multi.parent; - if (!parent) { - return; - } - const multiField = { - field, - isSelected: selectedFields.includes(field), - }; - const value = map.get(parent) ?? []; - value.push(multiField); - map.set(parent, value); - }); - return map; - }; - - const [multiFields, setMultiFields] = useState(() => calculateMultiFields()); + useEffect(() => { + const result = getSelectedFields(selectedDataView, columns); + setSelectedFieldsState(result); + }, [selectedDataView, columns, setSelectedFieldsState]); - useShallowCompareEffect(() => { - setMultiFields(calculateMultiFields()); - }, [fields, selectedFields, useNewFieldsApi]); + useEffect(() => { + if (isPlainRecord || !useNewFieldsApi) { + setMultiFieldsMap(undefined); // we don't have to calculate multifields in this case + } else { + setMultiFieldsMap( + calculateMultiFields(allFields, selectedFieldsState.selectedFieldsMap, useNewFieldsApi) + ); + } + }, [ + selectedFieldsState.selectedFieldsMap, + allFields, + useNewFieldsApi, + setMultiFieldsMap, + isPlainRecord, + ]); const deleteField = useMemo( () => @@ -305,15 +233,6 @@ export function DiscoverSidebarComponent({ ] ); - const getPaginated = useCallback( - (list) => { - return list.slice(0, fieldsToRender); - }, - [fieldsToRender] - ); - - const filterChanged = useMemo(() => isEqual(fieldFilter, getDefaultFieldFilter()), [fieldFilter]); - const visualizeAggregateQuery = useCallback(() => { const aggregateQuery = query && isOfAggregateQueryType(query) ? query : undefined; triggerVisualizeActionsTextBasedLanguages( @@ -325,6 +244,89 @@ export function DiscoverSidebarComponent({ ); }, [columns, selectedDataView, query]); + const popularFieldsLimit = useMemo(() => uiSettings.get(FIELDS_LIMIT_SETTING), [uiSettings]); + const onFilterField: GroupedFieldsParams['onFilterField'] = useCallback( + (field) => { + return doesFieldMatchFilters(field, fieldFilter); + }, + [fieldFilter] + ); + const onSupportedFieldFilter: GroupedFieldsParams['onSupportedFieldFilter'] = + useCallback( + (field) => { + return shouldShowField(field, isPlainRecord); + }, + [isPlainRecord] + ); + const onOverrideFieldGroupDetails: GroupedFieldsParams['onOverrideFieldGroupDetails'] = + useCallback((groupName) => { + if (groupName === FieldsGroupNames.AvailableFields) { + return { + helpText: i18n.translate('discover.fieldChooser.availableFieldsTooltip', { + defaultMessage: 'Fields available for display in the table.', + }), + }; + } + }, []); + const fieldsExistenceReader = useExistingFieldsReader(); + const fieldListGroupedProps = useGroupedFields({ + dataViewId: (!isPlainRecord && selectedDataView?.id) || null, // passing `null` for text-based queries + fieldsExistenceReader: !isPlainRecord ? fieldsExistenceReader : undefined, + allFields, + popularFieldsLimit: !isPlainRecord ? popularFieldsLimit : 0, + sortedSelectedFields: selectedFieldsState.selectedFields, + isAffectedByGlobalFilter, + services: { + dataViews, + }, + onFilterField, + onSupportedFieldFilter, + onOverrideFieldGroupDetails, + }); + + const renderFieldItem: FieldListGroupedProps['renderFieldItem'] = useCallback( + ({ field, groupName }) => ( +
  • + +
  • + ), + [ + alwaysShowActionButtons, + selectedDataView, + onAddField, + onRemoveField, + onAddFilter, + documents$, + trackUiMetric, + multiFieldsMap, + editField, + deleteField, + showFieldStats, + columns, + selectedFieldsState.selectedFieldsMap, + fieldFilter.name, + ] + ); + if (!selectedDataView) { return null; } @@ -367,169 +369,18 @@ export function DiscoverSidebarComponent({ types={fieldTypes} presentFieldTypes={presentFieldTypes} isPlainRecord={isPlainRecord} + fieldSearchDescriptionId={fieldSearchDescriptionId} />
    - -
    { - if (documents && el && !el.dataset.dynamicScroll) { - el.dataset.dynamicScroll = 'true'; - setScrollContainer(el); - } - }} - onScroll={throttle(lazyScroll, 100)} - className="eui-yScroll" - > - {Array.isArray(fields) && fields.length > 0 && ( -
    - {selectedFields && - selectedFields.length > 0 && - selectedFields[0].displayName !== '_source' ? ( - <> - - - - - - } - extraAction={ - - {selectedFields.length} - - } - > - -
      - {selectedFields.map((field: DataViewField) => { - return ( -
    • - -
    • - ); - })} -
    -
    - {' '} - - ) : null} - - - - - - } - extraAction={ - - {restFields.length} - - } - > - - {!isPlainRecord && popularFields.length > 0 && ( - <> - - - -
      - {popularFields.map((field: DataViewField) => { - return ( -
    • - -
    • - ); - })} -
    - - )} -
      - {getPaginated(restFields).map((field: DataViewField) => { - return ( -
    • - -
    • - ); - })} -
    -
    -
    - )} -
    + + {showFieldList && ( + + )} {!!editField && ( @@ -565,3 +416,29 @@ export function DiscoverSidebarComponent({ } export const DiscoverSidebar = memo(DiscoverSidebarComponent); + +function calculateMultiFields( + allFields: DataViewField[] | null, + selectedFieldsMap: SelectedFieldsResult['selectedFieldsMap'] | undefined, + useNewFieldsApi: boolean +) { + if (!useNewFieldsApi || !allFields) { + return undefined; + } + const map = new Map>(); + allFields.forEach((field) => { + const subTypeMulti = getFieldSubtypeMulti(field); + const parent = subTypeMulti?.multi.parent; + if (!parent) { + return; + } + const multiField = { + field, + isSelected: Boolean(selectedFieldsMap?.[field.name]), + }; + const value = map.get(parent) ?? []; + value.push(multiField); + map.set(parent, value); + }); + return map; +} diff --git a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.test.tsx b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.test.tsx index 7f2134a758018..720f3da27ad18 100644 --- a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.test.tsx +++ b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.test.tsx @@ -9,7 +9,8 @@ import { BehaviorSubject } from 'rxjs'; import { ReactWrapper } from 'enzyme'; import { findTestSubject } from '@elastic/eui/lib/test'; -import { getDataTableRecords } from '../../../../__fixtures__/real_hits'; +import { EuiProgress } from '@elastic/eui'; +import { getDataTableRecords, realHits } from '../../../../__fixtures__/real_hits'; import { act } from 'react-dom/test-utils'; import { mountWithIntl } from '@kbn/test-jest-helpers'; import React from 'react'; @@ -24,12 +25,14 @@ import { AvailableFields$, DataDocuments$, RecordRawType } from '../../hooks/use import { stubLogstashDataView } from '@kbn/data-plugin/common/stubs'; import { VIEW_MODE } from '../../../../components/view_mode_toggle'; import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; -import { chartPluginMock } from '@kbn/charts-plugin/public/mocks'; -import { dataViewPluginMocks } from '@kbn/data-views-plugin/public/mocks'; -import { fieldFormatsServiceMock } from '@kbn/field-formats-plugin/public/mocks'; -import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; import { getDiscoverStateMock } from '../../../../__mocks__/discover_state.mock'; import { DiscoverAppStateProvider } from '../../services/discover_app_state_container'; +import * as ExistingFieldsServiceApi from '@kbn/unified-field-list-plugin/public/services/field_existing/load_field_existing'; +import { resetExistingFieldsCache } from '@kbn/unified-field-list-plugin/public/hooks/use_existing_fields'; +import { createDiscoverServicesMock } from '../../../../__mocks__/services'; +import type { AggregateQuery, Query } from '@kbn/es-query'; +import { buildDataTableRecord } from '../../../../utils/build_data_record'; +import { type DataTableRecord } from '../../../../types'; jest.mock('@kbn/unified-field-list-plugin/public/services/field_stats', () => ({ loadFieldStats: jest.fn().mockResolvedValue({ @@ -67,59 +70,30 @@ jest.mock('@kbn/unified-field-list-plugin/public/services/field_stats', () => ({ }), })); -const dataServiceMock = dataPluginMock.createStartContract(); - -const mockServices = { - history: () => ({ - location: { - search: '', - }, - }), - capabilities: { - visualize: { - show: true, - }, - discover: { - save: false, - }, - }, - uiSettings: { - get: (key: string) => { - if (key === 'fields:popularLimit') { - return 5; - } - }, - }, - docLinks: { links: { discover: { fieldTypeHelp: '' } } }, - dataViewEditor: { - userPermissions: { - editDataView: jest.fn(() => true), - }, - }, - data: { - ...dataServiceMock, - query: { - ...dataServiceMock.query, - timefilter: { - ...dataServiceMock.query.timefilter, - timefilter: { - ...dataServiceMock.query.timefilter.timefilter, - getAbsoluteTime: () => ({ - from: '2021-08-31T22:00:00.000Z', - to: '2022-09-01T09:16:29.553Z', - }), - }, +function createMockServices() { + const mockServices = { + ...createDiscoverServicesMock(), + capabilities: { + visualize: { + show: true, + }, + discover: { + save: false, }, getState: () => ({ query: { query: '', language: 'lucene' }, filters: [], }), }, - }, - dataViews: dataViewPluginMocks.createStartContract(), - fieldFormats: fieldFormatsServiceMock.createStartContract(), - charts: chartPluginMock.createSetupContract(), -} as unknown as DiscoverServices; + docLinks: { links: { discover: { fieldTypeHelp: '' } } }, + dataViewEditor: { + userPermissions: { + editDataView: jest.fn(() => true), + }, + }, + } as unknown as DiscoverServices; + return mockServices; +} const mockfieldCounts: Record = {}; const mockCalcFieldCounts = jest.fn(() => { @@ -138,17 +112,13 @@ jest.mock('../../utils/calc_field_counts', () => ({ calcFieldCounts: () => mockCalcFieldCounts(), })); -function getCompProps(): DiscoverSidebarResponsiveProps { +jest.spyOn(ExistingFieldsServiceApi, 'loadFieldExisting'); + +function getCompProps(options?: { hits?: DataTableRecord[] }): DiscoverSidebarResponsiveProps { const dataView = stubLogstashDataView; dataView.toSpec = jest.fn(() => ({})); - const hits = getDataTableRecords(dataView); - - const dataViewList = [ - { id: '0', title: 'b' } as DataViewListItem, - { id: '1', title: 'a' } as DataViewListItem, - { id: '2', title: 'c' } as DataViewListItem, - ]; + const hits = options?.hits ?? getDataTableRecords(dataView); for (const hit of hits) { for (const key of Object.keys(hit.flattened)) { @@ -166,7 +136,7 @@ function getCompProps(): DiscoverSidebarResponsiveProps { fetchStatus: FetchStatus.COMPLETE, fields: [] as string[], }) as AvailableFields$, - dataViewList, + dataViewList: [dataView as DataViewListItem], onChangeDataView: jest.fn(), onAddFilter: jest.fn(), onAddField: jest.fn(), @@ -180,52 +150,220 @@ function getCompProps(): DiscoverSidebarResponsiveProps { }; } +function getAppStateContainer({ query }: { query?: Query | AggregateQuery }) { + const appStateContainer = getDiscoverStateMock({ isTimeBased: true }).appStateContainer; + appStateContainer.set({ + query: query ?? { query: '', language: 'lucene' }, + filters: [], + }); + return appStateContainer; +} + +async function mountComponent( + props: DiscoverSidebarResponsiveProps, + appStateParams: { query?: Query | AggregateQuery } = {}, + services?: DiscoverServices +): Promise> { + let comp: ReactWrapper; + const mockedServices = services ?? createMockServices(); + mockedServices.data.dataViews.getIdsWithTitle = jest.fn(async () => props.dataViewList); + mockedServices.data.dataViews.get = jest.fn().mockImplementation(async (id) => { + return [props.selectedDataView].find((d) => d!.id === id); + }); + + await act(async () => { + comp = await mountWithIntl( + + + + + + ); + // wait for lazy modules + await new Promise((resolve) => setTimeout(resolve, 0)); + await comp.update(); + }); + + await comp!.update(); + + return comp!; +} + describe('discover responsive sidebar', function () { let props: DiscoverSidebarResponsiveProps; - let comp: ReactWrapper; - beforeAll(async () => { + beforeEach(async () => { + (ExistingFieldsServiceApi.loadFieldExisting as jest.Mock).mockImplementation(async () => ({ + indexPatternTitle: 'test', + existingFieldNames: Object.keys(mockfieldCounts), + })); props = getCompProps(); + }); + + afterEach(() => { + mockCalcFieldCounts.mockClear(); + (ExistingFieldsServiceApi.loadFieldExisting as jest.Mock).mockClear(); + resetExistingFieldsCache(); + }); + + it('should have loading indicators during fields existence loading', async function () { + let resolveFunction: (arg: unknown) => void; + (ExistingFieldsServiceApi.loadFieldExisting as jest.Mock).mockReset(); + (ExistingFieldsServiceApi.loadFieldExisting as jest.Mock).mockImplementation(() => { + return new Promise((resolve) => { + resolveFunction = resolve; + }); + }); + + const compLoadingExistence = await mountComponent(props); + + expect( + findTestSubject(compLoadingExistence, 'fieldListGroupedAvailableFields-countLoading').exists() + ).toBe(true); + expect( + findTestSubject(compLoadingExistence, 'fieldListGroupedAvailableFields-count').exists() + ).toBe(false); + + expect(compLoadingExistence.find(EuiProgress).exists()).toBe(true); + await act(async () => { - const appStateContainer = getDiscoverStateMock({ isTimeBased: true }).appStateContainer; - appStateContainer.set({ - query: { query: '', language: 'lucene' }, - filters: [], + resolveFunction!({ + indexPatternTitle: 'test-loaded', + existingFieldNames: Object.keys(mockfieldCounts), }); + await compLoadingExistence.update(); + }); - comp = await mountWithIntl( - - - - - - ); - // wait for lazy modules - await new Promise((resolve) => setTimeout(resolve, 0)); - await comp.update(); + await act(async () => { + await compLoadingExistence.update(); }); + + expect( + findTestSubject(compLoadingExistence, 'fieldListGroupedAvailableFields-countLoading').exists() + ).toBe(false); + expect( + findTestSubject(compLoadingExistence, 'fieldListGroupedAvailableFields-count').exists() + ).toBe(true); + + expect(compLoadingExistence.find(EuiProgress).exists()).toBe(false); + + expect(ExistingFieldsServiceApi.loadFieldExisting).toHaveBeenCalledTimes(1); }); - it('should have Selected Fields and Available Fields with Popular Fields sections', function () { - const popular = findTestSubject(comp, 'fieldList-popular'); - const selected = findTestSubject(comp, 'fieldList-selected'); - const unpopular = findTestSubject(comp, 'fieldList-unpopular'); - expect(popular.children().length).toBe(1); - expect(unpopular.children().length).toBe(6); - expect(selected.children().length).toBe(1); + it('should have Selected Fields, Available Fields, Popular and Meta Fields sections', async function () { + const comp = await mountComponent(props); + const popularFieldsCount = findTestSubject(comp, 'fieldListGroupedPopularFields-count'); + const selectedFieldsCount = findTestSubject(comp, 'fieldListGroupedSelectedFields-count'); + const availableFieldsCount = findTestSubject(comp, 'fieldListGroupedAvailableFields-count'); + const emptyFieldsCount = findTestSubject(comp, 'fieldListGroupedEmptyFields-count'); + const metaFieldsCount = findTestSubject(comp, 'fieldListGroupedMetaFields-count'); + const unmappedFieldsCount = findTestSubject(comp, 'fieldListGroupedUnmappedFields-count'); + + expect(selectedFieldsCount.text()).toBe('1'); + expect(popularFieldsCount.text()).toBe('4'); + expect(availableFieldsCount.text()).toBe('3'); + expect(emptyFieldsCount.text()).toBe('20'); + expect(metaFieldsCount.text()).toBe('2'); + expect(unmappedFieldsCount.exists()).toBe(false); expect(mockCalcFieldCounts.mock.calls.length).toBe(1); + + expect(props.availableFields$.getValue()).toEqual({ + fetchStatus: 'complete', + fields: ['extension'], + }); + + expect(findTestSubject(comp, 'fieldListGrouped__ariaDescription').text()).toBe( + '1 selected field. 4 popular fields. 3 available fields. 20 empty fields. 2 meta fields.' + ); + + expect(ExistingFieldsServiceApi.loadFieldExisting).toHaveBeenCalledTimes(1); + }); + + it('should not have selected fields if no columns selected', async function () { + const propsWithoutColumns = { + ...props, + columns: [], + }; + const compWithoutSelected = await mountComponent(propsWithoutColumns); + const popularFieldsCount = findTestSubject( + compWithoutSelected, + 'fieldListGroupedPopularFields-count' + ); + const selectedFieldsCount = findTestSubject( + compWithoutSelected, + 'fieldListGroupedSelectedFields-count' + ); + const availableFieldsCount = findTestSubject( + compWithoutSelected, + 'fieldListGroupedAvailableFields-count' + ); + const emptyFieldsCount = findTestSubject( + compWithoutSelected, + 'fieldListGroupedEmptyFields-count' + ); + const metaFieldsCount = findTestSubject( + compWithoutSelected, + 'fieldListGroupedMetaFields-count' + ); + const unmappedFieldsCount = findTestSubject( + compWithoutSelected, + 'fieldListGroupedUnmappedFields-count' + ); + + expect(selectedFieldsCount.exists()).toBe(false); + expect(popularFieldsCount.text()).toBe('4'); + expect(availableFieldsCount.text()).toBe('3'); + expect(emptyFieldsCount.text()).toBe('20'); + expect(metaFieldsCount.text()).toBe('2'); + expect(unmappedFieldsCount.exists()).toBe(false); + + expect(propsWithoutColumns.availableFields$.getValue()).toEqual({ + fetchStatus: 'complete', + fields: ['bytes', 'extension', '_id', 'phpmemory'], + }); + + expect(findTestSubject(compWithoutSelected, 'fieldListGrouped__ariaDescription').text()).toBe( + '4 popular fields. 3 available fields. 20 empty fields. 2 meta fields.' + ); + }); + + it('should not calculate counts if documents are not fetched yet', async function () { + const propsWithoutDocuments: DiscoverSidebarResponsiveProps = { + ...props, + documents$: new BehaviorSubject({ + fetchStatus: FetchStatus.UNINITIALIZED, + result: undefined, + }) as DataDocuments$, + }; + const compWithoutDocuments = await mountComponent(propsWithoutDocuments); + const availableFieldsCount = findTestSubject( + compWithoutDocuments, + 'fieldListGroupedAvailableFields-count' + ); + + expect(availableFieldsCount.exists()).toBe(false); + + expect(mockCalcFieldCounts.mock.calls.length).toBe(0); + expect(ExistingFieldsServiceApi.loadFieldExisting).not.toHaveBeenCalled(); }); - it('should allow selecting fields', function () { - findTestSubject(comp, 'fieldToggle-bytes').simulate('click'); + + it('should allow selecting fields', async function () { + const comp = await mountComponent(props); + const availableFields = findTestSubject(comp, 'fieldListGroupedAvailableFields'); + findTestSubject(availableFields, 'fieldToggle-bytes').simulate('click'); expect(props.onAddField).toHaveBeenCalledWith('bytes'); }); - it('should allow deselecting fields', function () { - findTestSubject(comp, 'fieldToggle-extension').simulate('click'); + it('should allow deselecting fields', async function () { + const comp = await mountComponent(props); + const selectedFields = findTestSubject(comp, 'fieldListGroupedSelectedFields'); + findTestSubject(selectedFields, 'fieldToggle-extension').simulate('click'); expect(props.onRemoveField).toHaveBeenCalledWith('extension'); }); it('should allow adding filters', async function () { + const comp = await mountComponent(props); + const availableFields = findTestSubject(comp, 'fieldListGroupedAvailableFields'); await act(async () => { - const button = findTestSubject(comp, 'field-extension-showDetails'); + const button = findTestSubject(availableFields, 'field-extension-showDetails'); await button.simulate('click'); await comp.update(); }); @@ -235,8 +373,10 @@ describe('discover responsive sidebar', function () { expect(props.onAddFilter).toHaveBeenCalled(); }); it('should allow adding "exist" filter', async function () { + const comp = await mountComponent(props); + const availableFields = findTestSubject(comp, 'fieldListGroupedAvailableFields'); await act(async () => { - const button = findTestSubject(comp, 'field-extension-showDetails'); + const button = findTestSubject(availableFields, 'field-extension-showDetails'); await button.simulate('click'); await comp.update(); }); @@ -245,27 +385,38 @@ describe('discover responsive sidebar', function () { findTestSubject(comp, 'discoverFieldListPanelAddExistFilter-extension').simulate('click'); expect(props.onAddFilter).toHaveBeenCalledWith('_exists_', 'extension', '+'); }); - it('should allow filtering by string, and calcFieldCount should just be executed once', function () { - expect(findTestSubject(comp, 'fieldList-unpopular').children().length).toBe(6); - act(() => { - findTestSubject(comp, 'fieldFilterSearchInput').simulate('change', { - target: { value: 'abc' }, + it('should allow filtering by string, and calcFieldCount should just be executed once', async function () { + const comp = await mountComponent(props); + + expect(findTestSubject(comp, 'fieldListGroupedAvailableFields-count').text()).toBe('3'); + expect(findTestSubject(comp, 'fieldListGrouped__ariaDescription').text()).toBe( + '1 selected field. 4 popular fields. 3 available fields. 20 empty fields. 2 meta fields.' + ); + + await act(async () => { + await findTestSubject(comp, 'fieldFilterSearchInput').simulate('change', { + target: { value: 'bytes' }, }); }); - comp.update(); - expect(findTestSubject(comp, 'fieldList-unpopular').children().length).toBe(4); + + expect(findTestSubject(comp, 'fieldListGroupedAvailableFields-count').text()).toBe('1'); + expect(findTestSubject(comp, 'fieldListGrouped__ariaDescription').text()).toBe( + '1 popular field. 1 available field. 0 empty fields. 0 meta fields.' + ); expect(mockCalcFieldCounts.mock.calls.length).toBe(1); }); - it('should show "Add a field" button to create a runtime field', () => { - expect(mockServices.dataViewEditor.userPermissions.editDataView).toHaveBeenCalled(); + it('should show "Add a field" button to create a runtime field', async () => { + const services = createMockServices(); + const comp = await mountComponent(props, {}, services); + expect(services.dataViewEditor.userPermissions.editDataView).toHaveBeenCalled(); expect(findTestSubject(comp, 'dataView-add-field_btn').length).toBe(1); }); - it('should not show "Add a field" button on the sql mode', () => { - const initialProps = getCompProps(); + it('should render correctly in the sql mode', async () => { const propsWithTextBasedMode = { - ...initialProps, + ...props, + columns: ['extension', 'bytes'], onAddFilter: undefined, documents$: new BehaviorSubject({ fetchStatus: FetchStatus.COMPLETE, @@ -273,46 +424,75 @@ describe('discover responsive sidebar', function () { result: getDataTableRecords(stubLogstashDataView), }) as DataDocuments$, }; - const appStateContainer = getDiscoverStateMock({ isTimeBased: true }).appStateContainer; - appStateContainer.set({ + const compInViewerMode = await mountComponent(propsWithTextBasedMode, { query: { sql: 'SELECT * FROM `index`' }, }); - const compInViewerMode = mountWithIntl( - - - - - - ); expect(findTestSubject(compInViewerMode, 'indexPattern-add-field_btn').length).toBe(0); + + const popularFieldsCount = findTestSubject( + compInViewerMode, + 'fieldListGroupedPopularFields-count' + ); + const selectedFieldsCount = findTestSubject( + compInViewerMode, + 'fieldListGroupedSelectedFields-count' + ); + const availableFieldsCount = findTestSubject( + compInViewerMode, + 'fieldListGroupedAvailableFields-count' + ); + const emptyFieldsCount = findTestSubject(compInViewerMode, 'fieldListGroupedEmptyFields-count'); + const metaFieldsCount = findTestSubject(compInViewerMode, 'fieldListGroupedMetaFields-count'); + const unmappedFieldsCount = findTestSubject( + compInViewerMode, + 'fieldListGroupedUnmappedFields-count' + ); + + expect(selectedFieldsCount.text()).toBe('2'); + expect(popularFieldsCount.exists()).toBe(false); + expect(availableFieldsCount.text()).toBe('4'); + expect(emptyFieldsCount.exists()).toBe(false); + expect(metaFieldsCount.exists()).toBe(false); + expect(unmappedFieldsCount.exists()).toBe(false); + + expect(mockCalcFieldCounts.mock.calls.length).toBe(1); + + expect(findTestSubject(compInViewerMode, 'fieldListGrouped__ariaDescription').text()).toBe( + '2 selected fields. 4 available fields.' + ); }); - it('should not show "Add a field" button in viewer mode', () => { - const mockedServicesInViewerMode = { - ...mockServices, - dataViewEditor: { - ...mockServices.dataViewEditor, - userPermissions: { - ...mockServices.dataViewEditor.userPermissions, - editDataView: jest.fn(() => false), - }, - }, - }; - const appStateContainer = getDiscoverStateMock({ isTimeBased: true }).appStateContainer; - appStateContainer.set({ - query: { query: '', language: 'lucene' }, - filters: [], + it('should render correctly unmapped fields', async () => { + const propsWithUnmappedField = getCompProps({ + hits: [ + buildDataTableRecord(realHits[0], stubLogstashDataView), + buildDataTableRecord( + { + _index: 'logstash-2014.09.09', + _id: '1945', + _score: 1, + _source: { + extension: 'gif', + bytes: 10617.2, + test_unmapped: 'show me too', + }, + }, + stubLogstashDataView + ), + ], }); - const compInViewerMode = mountWithIntl( - - - - - + const compWithUnmapped = await mountComponent(propsWithUnmappedField); + + expect(findTestSubject(compWithUnmapped, 'fieldListGrouped__ariaDescription').text()).toBe( + '1 selected field. 4 popular fields. 3 available fields. 1 unmapped field. 20 empty fields. 2 meta fields.' ); - expect( - mockedServicesInViewerMode.dataViewEditor.userPermissions.editDataView - ).toHaveBeenCalled(); + }); + + it('should not show "Add a field" button in viewer mode', async () => { + const services = createMockServices(); + services.dataViewEditor.userPermissions.editDataView = jest.fn(() => false); + const compInViewerMode = await mountComponent(props, {}, services); + expect(services.dataViewEditor.userPermissions.editDataView).toHaveBeenCalled(); expect(findTestSubject(compInViewerMode, 'dataView-add-field_btn').length).toBe(0); }); }); diff --git a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.tsx b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.tsx index 73271a0260709..13e1287022f3d 100644 --- a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.tsx +++ b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.tsx @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import React, { useCallback, useEffect, useMemo, useReducer, useRef, useState } from 'react'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import { UiCounterMetricType } from '@kbn/analytics'; @@ -19,20 +19,31 @@ import { EuiIcon, EuiLink, EuiPortal, + EuiProgress, EuiShowFor, EuiTitle, } from '@elastic/eui'; import type { DataView, DataViewField, DataViewListItem } from '@kbn/data-views-plugin/public'; +import { + useExistingFieldsFetcher, + useQuerySubscriber, +} from '@kbn/unified-field-list-plugin/public'; import { useDiscoverServices } from '../../../../hooks/use_discover_services'; import { getDefaultFieldFilter } from './lib/field_filter'; import { DiscoverSidebar } from './discover_sidebar'; import { AvailableFields$, DataDocuments$, RecordRawType } from '../../hooks/use_saved_search'; -import { calcFieldCounts } from '../../utils/calc_field_counts'; import { VIEW_MODE } from '../../../../components/view_mode_toggle'; import { FetchStatus } from '../../../types'; import { DISCOVER_TOUR_STEP_ANCHOR_IDS } from '../../../../components/discover_tour'; import { getRawRecordType } from '../../utils/get_raw_record_type'; import { useAppStateSelector } from '../../services/discover_app_state_container'; +import { + discoverSidebarReducer, + getInitialState, + DiscoverSidebarReducerActionType, + DiscoverSidebarReducerStatus, +} from './lib/sidebar_reducer'; +import { calcFieldCounts } from '../../utils/calc_field_counts'; export interface DiscoverSidebarResponsiveProps { /** @@ -111,38 +122,94 @@ export interface DiscoverSidebarResponsiveProps { */ export function DiscoverSidebarResponsive(props: DiscoverSidebarResponsiveProps) { const services = useDiscoverServices(); + const { data, dataViews, core } = services; const isPlainRecord = useAppStateSelector( (state) => getRawRecordType(state.query) === RecordRawType.PLAIN ); const { selectedDataView, onFieldEdited, onDataViewCreated } = props; const [fieldFilter, setFieldFilter] = useState(getDefaultFieldFilter()); const [isFlyoutVisible, setIsFlyoutVisible] = useState(false); - /** - * fieldCounts are used to determine which fields are actually used in the given set of documents - */ - const fieldCounts = useRef | null>(null); - if (fieldCounts.current === null) { - fieldCounts.current = calcFieldCounts(props.documents$.getValue().result!, selectedDataView); - } + const [sidebarState, dispatchSidebarStateAction] = useReducer( + discoverSidebarReducer, + selectedDataView, + getInitialState + ); + const selectedDataViewRef = useRef(selectedDataView); + const showFieldList = sidebarState.status !== DiscoverSidebarReducerStatus.INITIAL; - const [documentState, setDocumentState] = useState(props.documents$.getValue()); useEffect(() => { - const subscription = props.documents$.subscribe((next) => { - if (next.fetchStatus !== documentState.fetchStatus) { - if (next.result) { - fieldCounts.current = calcFieldCounts(next.result, selectedDataView!); - } - setDocumentState({ ...documentState, ...next }); + const subscription = props.documents$.subscribe((documentState) => { + const isPlainRecordType = documentState.recordRawType === RecordRawType.PLAIN; + + switch (documentState?.fetchStatus) { + case FetchStatus.UNINITIALIZED: + dispatchSidebarStateAction({ + type: DiscoverSidebarReducerActionType.RESET, + payload: { + dataView: selectedDataViewRef.current, + }, + }); + break; + case FetchStatus.LOADING: + dispatchSidebarStateAction({ + type: DiscoverSidebarReducerActionType.DOCUMENTS_LOADING, + payload: { + isPlainRecord: isPlainRecordType, + }, + }); + break; + case FetchStatus.COMPLETE: + dispatchSidebarStateAction({ + type: DiscoverSidebarReducerActionType.DOCUMENTS_LOADED, + payload: { + dataView: selectedDataViewRef.current, + fieldCounts: calcFieldCounts(documentState.result), + isPlainRecord: isPlainRecordType, + }, + }); + break; + default: + break; } }); return () => subscription.unsubscribe(); - }, [props.documents$, selectedDataView, documentState, setDocumentState]); + }, [props.documents$, dispatchSidebarStateAction, selectedDataViewRef]); useEffect(() => { - // when data view changes fieldCounts needs to be cleaned up to prevent displaying - // fields of the previous data view - fieldCounts.current = {}; - }, [selectedDataView]); + if (selectedDataView !== selectedDataViewRef.current) { + dispatchSidebarStateAction({ + type: DiscoverSidebarReducerActionType.DATA_VIEW_SWITCHED, + payload: { + dataView: selectedDataView, + }, + }); + selectedDataViewRef.current = selectedDataView; + } + }, [selectedDataView, dispatchSidebarStateAction, selectedDataViewRef]); + + const querySubscriberResult = useQuerySubscriber({ data }); + const isAffectedByGlobalFilter = Boolean(querySubscriberResult.filters?.length); + const { isProcessing, refetchFieldsExistenceInfo } = useExistingFieldsFetcher({ + disableAutoFetching: true, + dataViews: !isPlainRecord && sidebarState.dataView ? [sidebarState.dataView] : [], + query: querySubscriberResult.query, + filters: querySubscriberResult.filters, + fromDate: querySubscriberResult.fromDate, + toDate: querySubscriberResult.toDate, + services: { + data, + dataViews, + core, + }, + }); + + useEffect(() => { + if (sidebarState.status === DiscoverSidebarReducerStatus.COMPLETED) { + refetchFieldsExistenceInfo(); + } + // refetching only if status changes + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [sidebarState.status]); const closeFieldEditor = useRef<() => void | undefined>(); const closeDataViewEditor = useRef<() => void | undefined>(); @@ -180,30 +247,18 @@ export function DiscoverSidebarResponsive(props: DiscoverSidebarResponsiveProps) const canEditDataView = Boolean(dataViewEditor?.userPermissions.editDataView()) || !selectedDataView?.isPersisted(); - useEffect( - () => { - // For an external embeddable like the Field stats - // it is useful to know what fields are populated in the docs fetched - // or what fields are selected by the user - - const fieldCnts = fieldCounts.current ?? {}; + useEffect(() => { + // For an external embeddable like the Field stats + // it is useful to know what fields are populated in the docs fetched + // or what fields are selected by the user - const availableFields = props.columns.length > 0 ? props.columns : Object.keys(fieldCnts); - availableFields$.next({ - fetchStatus: FetchStatus.COMPLETE, - fields: availableFields, - }); - }, - // Using columns.length here instead of columns to avoid array reference changing - // eslint-disable-next-line react-hooks/exhaustive-deps - [ - selectedDataView, - availableFields$, - fieldCounts.current, - documentState.result, - props.columns.length, - ] - ); + const availableFields = + props.columns.length > 0 ? props.columns : Object.keys(sidebarState.fieldCounts || {}); + availableFields$.next({ + fetchStatus: FetchStatus.COMPLETE, + fields: availableFields, + }); + }, [selectedDataView, sidebarState.fieldCounts, props.columns, availableFields$]); const editField = useMemo( () => @@ -259,14 +314,17 @@ export function DiscoverSidebarResponsive(props: DiscoverSidebarResponsiveProps) <> {!props.isClosed && ( + {isProcessing && } )} @@ -322,8 +380,8 @@ export function DiscoverSidebarResponsive(props: DiscoverSidebarResponsiveProps) diff --git a/src/plugins/discover/public/application/main/components/sidebar/lib/field_filter.test.ts b/src/plugins/discover/public/application/main/components/sidebar/lib/field_filter.test.ts index 7020dfcc418eb..1d46ea17d5a06 100644 --- a/src/plugins/discover/public/application/main/components/sidebar/lib/field_filter.test.ts +++ b/src/plugins/discover/public/application/main/components/sidebar/lib/field_filter.test.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { getDefaultFieldFilter, setFieldFilterProp, isFieldFiltered } from './field_filter'; +import { getDefaultFieldFilter, setFieldFilterProp, doesFieldMatchFilters } from './field_filter'; import { DataViewField } from '@kbn/data-views-plugin/public'; describe('field_filter', function () { @@ -14,7 +14,6 @@ describe('field_filter', function () { expect(getDefaultFieldFilter()).toMatchInlineSnapshot(` Object { "aggregatable": null, - "missing": true, "name": "", "searchable": null, "type": "any", @@ -25,7 +24,6 @@ describe('field_filter', function () { const state = getDefaultFieldFilter(); const targetState = { aggregatable: true, - missing: true, name: 'test', searchable: true, type: 'string', @@ -36,7 +34,6 @@ describe('field_filter', function () { expect(actualState).toMatchInlineSnapshot(` Object { "aggregatable": true, - "missing": true, "name": "test", "searchable": true, "type": "string", @@ -78,9 +75,7 @@ describe('field_filter', function () { { filter: { type: 'string' }, result: ['extension'] }, ].forEach((test) => { const filtered = fieldList - .filter((field) => - isFieldFiltered(field, { ...defaultState, ...test.filter }, { bytes: 1, extension: 1 }) - ) + .filter((field) => doesFieldMatchFilters(field, { ...defaultState, ...test.filter })) .map((field) => field.name); expect(filtered).toEqual(test.result); diff --git a/src/plugins/discover/public/application/main/components/sidebar/lib/field_filter.ts b/src/plugins/discover/public/application/main/components/sidebar/lib/field_filter.ts index 0ca0cea75ad5c..1f2ab0b9b64cd 100644 --- a/src/plugins/discover/public/application/main/components/sidebar/lib/field_filter.ts +++ b/src/plugins/discover/public/application/main/components/sidebar/lib/field_filter.ts @@ -9,7 +9,6 @@ import { DataViewField } from '@kbn/data-views-plugin/public'; export interface FieldFilterState { - missing: boolean; type: string; name: string; aggregatable: null | boolean; @@ -18,7 +17,6 @@ export interface FieldFilterState { export function getDefaultFieldFilter(): FieldFilterState { return { - missing: true, type: 'any', name: '', aggregatable: null, @@ -32,9 +30,7 @@ export function setFieldFilterProp( value: string | boolean | null | undefined ): FieldFilterState { const newState = { ...state }; - if (name === 'missing') { - newState.missing = Boolean(value); - } else if (name === 'aggregatable') { + if (name === 'aggregatable') { newState.aggregatable = typeof value !== 'boolean' ? null : value; } else if (name === 'searchable') { newState.searchable = typeof value !== 'boolean' ? null : value; @@ -46,25 +42,18 @@ export function setFieldFilterProp( return newState; } -export function isFieldFiltered( +export function doesFieldMatchFilters( field: DataViewField, - filterState: FieldFilterState, - fieldCounts: Record + filterState: FieldFilterState ): boolean { const matchFilter = filterState.type === 'any' || field.type === filterState.type; const isAggregatable = filterState.aggregatable === null || field.aggregatable === filterState.aggregatable; const isSearchable = filterState.searchable === null || field.searchable === filterState.searchable; - const scriptedOrMissing = - !filterState.missing || - field.type === '_source' || - field.type === 'unknown_selected' || - field.scripted || - fieldCounts[field.name] > 0; const needle = filterState.name ? filterState.name.toLowerCase() : ''; const haystack = `${field.name}${field.displayName || ''}`.toLowerCase(); const matchName = !filterState.name || haystack.indexOf(needle) !== -1; - return matchFilter && isAggregatable && isSearchable && scriptedOrMissing && matchName; + return matchFilter && isAggregatable && isSearchable && matchName; } diff --git a/src/plugins/discover/public/application/main/components/sidebar/lib/get_data_view_field_list.ts b/src/plugins/discover/public/application/main/components/sidebar/lib/get_data_view_field_list.ts index 224015a10537e..5d055d94184ed 100644 --- a/src/plugins/discover/public/application/main/components/sidebar/lib/get_data_view_field_list.ts +++ b/src/plugins/discover/public/application/main/components/sidebar/lib/get_data_view_field_list.ts @@ -7,18 +7,37 @@ */ import { difference } from 'lodash'; -import { DataView, DataViewField } from '@kbn/data-views-plugin/public'; +import type { DataView, DataViewField } from '@kbn/data-views-plugin/public'; +import { fieldWildcardFilter } from '@kbn/kibana-utils-plugin/public'; import { isNestedFieldParent } from '../../../utils/nested_fields'; -export function getDataViewFieldList(dataView?: DataView, fieldCounts?: Record) { - if (!dataView || !fieldCounts) return []; +export function getDataViewFieldList( + dataView: DataView | undefined | null, + fieldCounts: Record | undefined | null, + isPlainRecord: boolean +): DataViewField[] | null { + if (isPlainRecord && !fieldCounts) { + // still loading data + return null; + } - const fieldNamesInDocs = Object.keys(fieldCounts); - const fieldNamesInDataView = dataView.fields.getAll().map((fld) => fld.name); + const currentFieldCounts = fieldCounts || {}; + const sourceFiltersValues = dataView?.getSourceFiltering?.()?.excludes; + let dataViewFields: DataViewField[] = dataView?.fields.getAll() || []; + + if (sourceFiltersValues) { + const filter = fieldWildcardFilter(sourceFiltersValues, dataView.metaFields); + dataViewFields = dataViewFields.filter((field) => { + return filter(field.name) || currentFieldCounts[field.name]; // don't filter out a field which was present in hits (ex. for text-based queries, selected fields) + }); + } + + const fieldNamesInDocs = Object.keys(currentFieldCounts); + const fieldNamesInDataView = dataViewFields.map((fld) => fld.name); const unknownFields: DataViewField[] = []; difference(fieldNamesInDocs, fieldNamesInDataView).forEach((unknownFieldName) => { - if (isNestedFieldParent(unknownFieldName, dataView)) { + if (dataView && isNestedFieldParent(unknownFieldName, dataView)) { unknownFields.push({ displayName: String(unknownFieldName), name: String(unknownFieldName), @@ -33,5 +52,10 @@ export function getDataViewFieldList(dataView?: DataView, fieldCounts?: Record currentFieldCounts[field.name]) + : dataViewFields), + ...unknownFields, + ]; } diff --git a/src/plugins/discover/public/application/main/components/sidebar/lib/group_fields.test.ts b/src/plugins/discover/public/application/main/components/sidebar/lib/group_fields.test.ts index 10d9d4face166..7dee06ec512bc 100644 --- a/src/plugins/discover/public/application/main/components/sidebar/lib/group_fields.test.ts +++ b/src/plugins/discover/public/application/main/components/sidebar/lib/group_fields.test.ts @@ -6,271 +6,106 @@ * Side Public License, v 1. */ -import { groupFields } from './group_fields'; -import { getDefaultFieldFilter } from './field_filter'; -import { DataViewField } from '@kbn/data-views-plugin/public'; - -const fields = [ - { - name: 'category', - type: 'string', - esTypes: ['text'], - count: 1, - scripted: false, - searchable: true, - aggregatable: true, - readFromDocValues: true, - }, - { - name: 'currency', - type: 'string', - esTypes: ['keyword'], - count: 0, - scripted: false, - searchable: true, - aggregatable: true, - readFromDocValues: true, - }, - { - name: 'customer_birth_date', - type: 'date', - esTypes: ['date'], - count: 0, - scripted: false, - searchable: true, - aggregatable: true, - readFromDocValues: true, - }, -]; - -const fieldCounts = { - category: 1, - currency: 1, - customer_birth_date: 1, - unknown_field: 1, -}; +import { type DataViewField } from '@kbn/data-plugin/common'; +import { stubLogstashDataView as dataView } from '@kbn/data-views-plugin/common/data_view.stub'; +import { getSelectedFields, shouldShowField, INITIAL_SELECTED_FIELDS_RESULT } from './group_fields'; describe('group_fields', function () { - it('should group fields in selected, popular, unpopular group', function () { - const fieldFilterState = getDefaultFieldFilter(); - - const actual = groupFields( - fields as DataViewField[], - ['currency'], - 5, - fieldCounts, - fieldFilterState, - false - ); + it('should pick fields as unknown_selected if they are unknown', function () { + const actual = getSelectedFields(dataView, ['currency']); expect(actual).toMatchInlineSnapshot(` Object { - "popular": Array [ + "selectedFields": Array [ Object { - "aggregatable": true, - "count": 1, - "esTypes": Array [ - "text", - ], - "name": "category", - "readFromDocValues": true, - "scripted": false, - "searchable": true, - "type": "string", - }, - ], - "selected": Array [ - Object { - "aggregatable": true, - "count": 0, - "esTypes": Array [ - "keyword", - ], + "displayName": "currency", "name": "currency", - "readFromDocValues": true, - "scripted": false, - "searchable": true, - "type": "string", - }, - ], - "unpopular": Array [ - Object { - "aggregatable": true, - "count": 0, - "esTypes": Array [ - "date", - ], - "name": "customer_birth_date", - "readFromDocValues": true, - "scripted": false, - "searchable": true, - "type": "date", + "type": "unknown_selected", }, ], + "selectedFieldsMap": Object { + "currency": true, + }, } `); }); - it('should group fields in selected, popular, unpopular group if they contain multifields', function () { - const category = { - name: 'category', - type: 'string', - esTypes: ['text'], - count: 1, - scripted: false, - searchable: true, - aggregatable: true, - readFromDocValues: true, - }; - const currency = { - name: 'currency', - displayName: 'currency', - kbnFieldType: { - esTypes: ['string', 'text', 'keyword', '_type', '_id'], - filterable: true, - name: 'string', - sortable: true, - }, - spec: { - esTypes: ['text'], - name: 'category', - }, - scripted: false, - searchable: true, - aggregatable: true, - readFromDocValues: true, - }; - const currencyKeyword = { - name: 'currency.keyword', - displayName: 'currency.keyword', - type: 'string', - esTypes: ['keyword'], - kbnFieldType: { - esTypes: ['string', 'text', 'keyword', '_type', '_id'], - filterable: true, - name: 'string', - sortable: true, - }, - spec: { - aggregatable: true, - esTypes: ['keyword'], - name: 'category.keyword', - readFromDocValues: true, - searchable: true, - shortDotsEnable: false, - subType: { - multi: { - parent: 'currency', - }, - }, - }, - scripted: false, - searchable: true, - aggregatable: true, - readFromDocValues: false, - }; - const fieldsToGroup = [category, currency, currencyKeyword] as DataViewField[]; - const fieldFilterState = getDefaultFieldFilter(); - - const actual = groupFields(fieldsToGroup, ['currency'], 5, fieldCounts, fieldFilterState, true); + it('should work correctly if no columns selected', function () { + expect(getSelectedFields(dataView, [])).toBe(INITIAL_SELECTED_FIELDS_RESULT); + expect(getSelectedFields(dataView, ['_source'])).toBe(INITIAL_SELECTED_FIELDS_RESULT); + }); - expect(actual.popular).toEqual([category]); - expect(actual.selected).toEqual([currency]); - expect(actual.unpopular).toEqual([]); + it('should pick fields into selected group', function () { + const actual = getSelectedFields(dataView, ['bytes', '@timestamp']); + expect(actual.selectedFields.map((field) => field.name)).toEqual(['bytes', '@timestamp']); + expect(actual.selectedFieldsMap).toStrictEqual({ + bytes: true, + '@timestamp': true, + }); }); - it('should sort selected fields by columns order ', function () { - const fieldFilterState = getDefaultFieldFilter(); + it('should pick fields into selected group if they contain multifields', function () { + const actual = getSelectedFields(dataView, ['machine.os', 'machine.os.raw']); + expect(actual.selectedFields.map((field) => field.name)).toEqual([ + 'machine.os', + 'machine.os.raw', + ]); + expect(actual.selectedFieldsMap).toStrictEqual({ + 'machine.os': true, + 'machine.os.raw': true, + }); + }); - const actual1 = groupFields( - fields as DataViewField[], - ['customer_birth_date', 'currency', 'unknown'], - 5, - fieldCounts, - fieldFilterState, - false - ); - expect(actual1.selected.map((field) => field.name)).toEqual([ - 'customer_birth_date', - 'currency', + it('should sort selected fields by columns order', function () { + const actual1 = getSelectedFields(dataView, ['bytes', 'extension.keyword', 'unknown']); + expect(actual1.selectedFields.map((field) => field.name)).toEqual([ + 'bytes', + 'extension.keyword', 'unknown', ]); + expect(actual1.selectedFieldsMap).toStrictEqual({ + bytes: true, + 'extension.keyword': true, + unknown: true, + }); - const actual2 = groupFields( - fields as DataViewField[], - ['currency', 'customer_birth_date', 'unknown'], - 5, - fieldCounts, - fieldFilterState, - false - ); - expect(actual2.selected.map((field) => field.name)).toEqual([ - 'currency', - 'customer_birth_date', + const actual2 = getSelectedFields(dataView, ['extension', 'bytes', 'unknown']); + expect(actual2.selectedFields.map((field) => field.name)).toEqual([ + 'extension', + 'bytes', 'unknown', ]); + expect(actual2.selectedFieldsMap).toStrictEqual({ + extension: true, + bytes: true, + unknown: true, + }); }); - it('should filter fields by a given name', function () { - const fieldFilterState = { ...getDefaultFieldFilter(), ...{ name: 'curr' } }; + it('should show any fields if for text-based searches', function () { + expect(shouldShowField(dataView.getFieldByName('bytes'), true)).toBe(true); + expect(shouldShowField({ type: 'unknown', name: 'unknown' } as DataViewField, true)).toBe(true); + expect(shouldShowField({ type: '_source', name: 'source' } as DataViewField, true)).toBe(false); + }); - const actual1 = groupFields( - fields as DataViewField[], - ['customer_birth_date', 'currency', 'unknown'], - 5, - fieldCounts, - fieldFilterState, + it('should show fields excluding subfields when searched from source', function () { + expect(shouldShowField(dataView.getFieldByName('extension'), false)).toBe(true); + expect(shouldShowField(dataView.getFieldByName('extension.keyword'), false)).toBe(false); + expect(shouldShowField({ type: 'unknown', name: 'unknown' } as DataViewField, false)).toBe( + true + ); + expect(shouldShowField({ type: '_source', name: 'source' } as DataViewField, false)).toBe( false ); - expect(actual1.selected.map((field) => field.name)).toEqual(['currency']); }); - it('excludes unmapped fields if showUnmappedFields set to false', function () { - const fieldFilterState = getDefaultFieldFilter(); - const fieldsWithUnmappedField = [...fields]; - fieldsWithUnmappedField.push({ - name: 'unknown_field', - type: 'unknown', - esTypes: ['unknown'], - count: 1, - scripted: false, - searchable: true, - aggregatable: true, - readFromDocValues: true, - }); - - const actual = groupFields( - fieldsWithUnmappedField as DataViewField[], - ['customer_birth_date', 'currency'], - 5, - fieldCounts, - fieldFilterState, + it('should show fields excluding subfields when fields api is used', function () { + expect(shouldShowField(dataView.getFieldByName('extension'), false)).toBe(true); + expect(shouldShowField(dataView.getFieldByName('extension.keyword'), false)).toBe(false); + expect(shouldShowField({ type: 'unknown', name: 'unknown' } as DataViewField, false)).toBe( true ); - expect(actual.unpopular).toEqual([]); - }); - - it('includes unmapped fields when reading from source', function () { - const fieldFilterState = getDefaultFieldFilter(); - const fieldsWithUnmappedField = [...fields]; - fieldsWithUnmappedField.push({ - name: 'unknown_field', - type: 'unknown', - esTypes: ['unknown'], - count: 0, - scripted: false, - searchable: false, - aggregatable: false, - readFromDocValues: false, - }); - - const actual = groupFields( - fieldsWithUnmappedField as DataViewField[], - ['customer_birth_date', 'currency'], - 5, - fieldCounts, - fieldFilterState, + expect(shouldShowField({ type: '_source', name: 'source' } as DataViewField, false)).toBe( false ); - expect(actual.unpopular.map((field) => field.name)).toEqual(['unknown_field']); }); }); diff --git a/src/plugins/discover/public/application/main/components/sidebar/lib/group_fields.tsx b/src/plugins/discover/public/application/main/components/sidebar/lib/group_fields.tsx index 0d7d535538c44..eaae1c90d3833 100644 --- a/src/plugins/discover/public/application/main/components/sidebar/lib/group_fields.tsx +++ b/src/plugins/discover/public/application/main/components/sidebar/lib/group_fields.tsx @@ -6,90 +6,66 @@ * Side Public License, v 1. */ -import { DataViewField, getFieldSubtypeMulti } from '@kbn/data-views-plugin/public'; -import { FieldFilterState, isFieldFiltered } from './field_filter'; +import { uniqBy } from 'lodash'; +import { + type DataViewField, + type DataView, + getFieldSubtypeMulti, +} from '@kbn/data-views-plugin/public'; -interface GroupedFields { - selected: DataViewField[]; - popular: DataViewField[]; - unpopular: DataViewField[]; +export function shouldShowField(field: DataViewField | undefined, isPlainRecord: boolean): boolean { + if (!field?.type || field.type === '_source') { + return false; + } + if (isPlainRecord) { + // exclude only `_source` for plain records + return true; + } + // exclude subfields + return !getFieldSubtypeMulti(field?.spec); } -/** - * group the fields into selected, popular and unpopular, filter by fieldFilterState - */ -export function groupFields( - fields: DataViewField[] | null, - columns: string[], - popularLimit: number, - fieldCounts: Record | undefined, - fieldFilterState: FieldFilterState, - useNewFieldsApi: boolean -): GroupedFields { - const showUnmappedFields = useNewFieldsApi; - const result: GroupedFields = { - selected: [], - popular: [], - unpopular: [], - }; - if (!Array.isArray(fields) || !Array.isArray(columns) || typeof fieldCounts !== 'object') { - return result; - } +// to avoid rerenderings for empty state +export const INITIAL_SELECTED_FIELDS_RESULT = { + selectedFields: [], + selectedFieldsMap: {}, +}; - const popular = fields - .filter((field) => !columns.includes(field.name) && field.count) - .sort((a: DataViewField, b: DataViewField) => (b.count || 0) - (a.count || 0)) - .map((field) => field.name) - .slice(0, popularLimit); +export interface SelectedFieldsResult { + selectedFields: DataViewField[]; + selectedFieldsMap: Record; +} - const compareFn = (a: DataViewField, b: DataViewField) => { - if (!a.displayName) { - return 0; - } - return a.displayName.localeCompare(b.displayName || ''); +export function getSelectedFields( + dataView: DataView | undefined, + columns: string[] +): SelectedFieldsResult { + const result: SelectedFieldsResult = { + selectedFields: [], + selectedFieldsMap: {}, }; - const fieldsSorted = fields.sort(compareFn); - - for (const field of fieldsSorted) { - if (!isFieldFiltered(field, fieldFilterState, fieldCounts)) { - continue; - } - - const subTypeMulti = getFieldSubtypeMulti(field?.spec); - const isSubfield = useNewFieldsApi && subTypeMulti; - if (columns.includes(field.name)) { - result.selected.push(field); - } else if (popular.includes(field.name) && field.type !== '_source') { - if (!isSubfield) { - result.popular.push(field); - } - } else if (field.type !== '_source') { - // do not show unmapped fields unless explicitly specified - // do not add subfields to this list - if (useNewFieldsApi && (field.type !== 'unknown' || showUnmappedFields) && !isSubfield) { - result.unpopular.push(field); - } else if (!useNewFieldsApi) { - result.unpopular.push(field); - } - } + if (!Array.isArray(columns) || !columns.length) { + return INITIAL_SELECTED_FIELDS_RESULT; } + // add selected columns, that are not part of the data view, to be removable for (const column of columns) { - const tmpField = { - name: column, - displayName: column, - type: 'unknown_selected', - } as DataViewField; - if ( - !result.selected.find((field) => field.name === column) && - isFieldFiltered(tmpField, fieldFilterState, fieldCounts) - ) { - result.selected.push(tmpField); - } + const selectedField = + dataView?.getFieldByName?.(column) || + ({ + name: column, + displayName: column, + type: 'unknown_selected', + } as DataViewField); + result.selectedFields.push(selectedField); + result.selectedFieldsMap[selectedField.name] = true; + } + + result.selectedFields = uniqBy(result.selectedFields, 'name'); + + if (result.selectedFields.length === 1 && result.selectedFields[0].name === '_source') { + return INITIAL_SELECTED_FIELDS_RESULT; } - result.selected.sort((a, b) => { - return columns.indexOf(a.name) - columns.indexOf(b.name); - }); return result; } diff --git a/src/plugins/discover/public/application/main/components/sidebar/lib/sidebar_reducer.test.ts b/src/plugins/discover/public/application/main/components/sidebar/lib/sidebar_reducer.test.ts new file mode 100644 index 0000000000000..131f9c358317f --- /dev/null +++ b/src/plugins/discover/public/application/main/components/sidebar/lib/sidebar_reducer.test.ts @@ -0,0 +1,220 @@ +/* + * Copyright 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 { + stubDataViewWithoutTimeField, + stubLogstashDataView as dataView, +} from '@kbn/data-views-plugin/common/data_view.stub'; +import { + discoverSidebarReducer, + DiscoverSidebarReducerActionType, + DiscoverSidebarReducerState, + DiscoverSidebarReducerStatus, + getInitialState, +} from './sidebar_reducer'; +import { DataViewField } from '@kbn/data-views-plugin/common'; + +describe('sidebar reducer', function () { + it('should set an initial state', function () { + expect(getInitialState(dataView)).toEqual( + expect.objectContaining({ + dataView, + allFields: null, + fieldCounts: null, + status: DiscoverSidebarReducerStatus.INITIAL, + }) + ); + }); + + it('should handle "documents loading" action', function () { + const state: DiscoverSidebarReducerState = { + ...getInitialState(dataView), + allFields: [dataView.fields[0]], + }; + const resultForDocuments = discoverSidebarReducer(state, { + type: DiscoverSidebarReducerActionType.DOCUMENTS_LOADING, + payload: { + isPlainRecord: false, + }, + }); + expect(resultForDocuments).toEqual( + expect.objectContaining({ + dataView, + allFields: state.allFields, + fieldCounts: null, + status: DiscoverSidebarReducerStatus.PROCESSING, + }) + ); + const resultForTextBasedQuery = discoverSidebarReducer(state, { + type: DiscoverSidebarReducerActionType.DOCUMENTS_LOADING, + payload: { + isPlainRecord: true, + }, + }); + expect(resultForTextBasedQuery).toEqual( + expect.objectContaining({ + dataView, + allFields: null, + fieldCounts: null, + status: DiscoverSidebarReducerStatus.PROCESSING, + }) + ); + }); + + it('should handle "documents loaded" action', function () { + const dataViewFieldName = stubDataViewWithoutTimeField.fields[0].name; + const unmappedFieldName = 'field1'; + const fieldCounts = { [unmappedFieldName]: 1, [dataViewFieldName]: 1 }; + const state: DiscoverSidebarReducerState = getInitialState(dataView); + const resultForDocuments = discoverSidebarReducer(state, { + type: DiscoverSidebarReducerActionType.DOCUMENTS_LOADED, + payload: { + isPlainRecord: false, + dataView: stubDataViewWithoutTimeField, + fieldCounts, + }, + }); + expect(resultForDocuments).toStrictEqual({ + dataView: stubDataViewWithoutTimeField, + allFields: [ + ...stubDataViewWithoutTimeField.fields, + // merging in unmapped fields + { + displayName: unmappedFieldName, + name: unmappedFieldName, + type: 'unknown', + } as DataViewField, + ], + fieldCounts, + status: DiscoverSidebarReducerStatus.COMPLETED, + }); + + const resultForTextBasedQuery = discoverSidebarReducer(state, { + type: DiscoverSidebarReducerActionType.DOCUMENTS_LOADED, + payload: { + isPlainRecord: true, + dataView: stubDataViewWithoutTimeField, + fieldCounts, + }, + }); + expect(resultForTextBasedQuery).toStrictEqual({ + dataView: stubDataViewWithoutTimeField, + allFields: [ + stubDataViewWithoutTimeField.fields.find((field) => field.name === dataViewFieldName), + // merging in unmapped fields + { + displayName: 'field1', + name: 'field1', + type: 'unknown', + } as DataViewField, + ], + fieldCounts, + status: DiscoverSidebarReducerStatus.COMPLETED, + }); + + const resultForTextBasedQueryWhileLoading = discoverSidebarReducer(state, { + type: DiscoverSidebarReducerActionType.DOCUMENTS_LOADED, + payload: { + isPlainRecord: true, + dataView: stubDataViewWithoutTimeField, + fieldCounts: null, + }, + }); + expect(resultForTextBasedQueryWhileLoading).toStrictEqual({ + dataView: stubDataViewWithoutTimeField, + allFields: null, + fieldCounts: null, + status: DiscoverSidebarReducerStatus.PROCESSING, + }); + }); + + it('should handle "data view switched" action', function () { + const state: DiscoverSidebarReducerState = getInitialState(dataView); + const resultForTheSameDataView = discoverSidebarReducer(state, { + type: DiscoverSidebarReducerActionType.DATA_VIEW_SWITCHED, + payload: { + dataView: state.dataView, + }, + }); + expect(resultForTheSameDataView).toBe(state); + + const resultForAnotherDataView = discoverSidebarReducer(state, { + type: DiscoverSidebarReducerActionType.DATA_VIEW_SWITCHED, + payload: { + dataView: stubDataViewWithoutTimeField, + }, + }); + expect(resultForAnotherDataView).toStrictEqual({ + dataView: stubDataViewWithoutTimeField, + allFields: null, + fieldCounts: null, + status: DiscoverSidebarReducerStatus.INITIAL, + }); + + const resultForAnotherDataViewAfterProcessing = discoverSidebarReducer( + { + ...state, + status: DiscoverSidebarReducerStatus.PROCESSING, + }, + { + type: DiscoverSidebarReducerActionType.DATA_VIEW_SWITCHED, + payload: { + dataView: stubDataViewWithoutTimeField, + }, + } + ); + expect(resultForAnotherDataViewAfterProcessing).toStrictEqual({ + dataView: stubDataViewWithoutTimeField, + allFields: null, + fieldCounts: null, + status: DiscoverSidebarReducerStatus.PROCESSING, + }); + + const resultForAnotherDataViewAfterCompleted = discoverSidebarReducer( + { + ...state, + status: DiscoverSidebarReducerStatus.COMPLETED, + }, + { + type: DiscoverSidebarReducerActionType.DATA_VIEW_SWITCHED, + payload: { + dataView: stubDataViewWithoutTimeField, + }, + } + ); + expect(resultForAnotherDataViewAfterCompleted).toStrictEqual({ + dataView: stubDataViewWithoutTimeField, + allFields: null, + fieldCounts: null, + status: DiscoverSidebarReducerStatus.INITIAL, + }); + }); + + it('should handle "reset" action', function () { + const state: DiscoverSidebarReducerState = { + ...getInitialState(dataView), + allFields: [dataView.fields[0]], + fieldCounts: {}, + status: DiscoverSidebarReducerStatus.COMPLETED, + }; + const resultForDocuments = discoverSidebarReducer(state, { + type: DiscoverSidebarReducerActionType.RESET, + payload: { + dataView: stubDataViewWithoutTimeField, + }, + }); + expect(resultForDocuments).toEqual( + expect.objectContaining({ + dataView: stubDataViewWithoutTimeField, + allFields: null, + fieldCounts: null, + status: DiscoverSidebarReducerStatus.INITIAL, + }) + ); + }); +}); diff --git a/src/plugins/discover/public/application/main/components/sidebar/lib/sidebar_reducer.ts b/src/plugins/discover/public/application/main/components/sidebar/lib/sidebar_reducer.ts new file mode 100644 index 0000000000000..0c579275029b1 --- /dev/null +++ b/src/plugins/discover/public/application/main/components/sidebar/lib/sidebar_reducer.ts @@ -0,0 +1,115 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { type DataView, type DataViewField } from '@kbn/data-views-plugin/common'; +import { getDataViewFieldList } from './get_data_view_field_list'; + +export enum DiscoverSidebarReducerActionType { + RESET = 'RESET', + DATA_VIEW_SWITCHED = 'DATA_VIEW_SWITCHED', + DOCUMENTS_LOADED = 'DOCUMENTS_LOADED', + DOCUMENTS_LOADING = 'DOCUMENTS_LOADING', +} + +type DiscoverSidebarReducerAction = + | { + type: DiscoverSidebarReducerActionType.RESET; + payload: { + dataView: DataView | null | undefined; + }; + } + | { + type: DiscoverSidebarReducerActionType.DATA_VIEW_SWITCHED; + payload: { + dataView: DataView | null | undefined; + }; + } + | { + type: DiscoverSidebarReducerActionType.DOCUMENTS_LOADING; + payload: { + isPlainRecord: boolean; + }; + } + | { + type: DiscoverSidebarReducerActionType.DOCUMENTS_LOADED; + payload: { + fieldCounts: DiscoverSidebarReducerState['fieldCounts']; + isPlainRecord: boolean; + dataView: DataView | null | undefined; + }; + }; + +export enum DiscoverSidebarReducerStatus { + INITIAL = 'INITIAL', + PROCESSING = 'PROCESSING', + COMPLETED = 'COMPLETED', +} + +export interface DiscoverSidebarReducerState { + dataView: DataView | null | undefined; + allFields: DataViewField[] | null; + fieldCounts: Record | null; + status: DiscoverSidebarReducerStatus; +} + +export function getInitialState(dataView?: DataView | null): DiscoverSidebarReducerState { + return { + dataView, + allFields: null, + fieldCounts: null, + status: DiscoverSidebarReducerStatus.INITIAL, + }; +} + +export function discoverSidebarReducer( + state: DiscoverSidebarReducerState, + action: DiscoverSidebarReducerAction +): DiscoverSidebarReducerState { + switch (action.type) { + case DiscoverSidebarReducerActionType.RESET: + return getInitialState(action.payload.dataView); + case DiscoverSidebarReducerActionType.DATA_VIEW_SWITCHED: + return state.dataView === action.payload.dataView + ? state // already updated in `DOCUMENTS_LOADED` + : { + ...state, + dataView: action.payload.dataView, + fieldCounts: null, + allFields: null, + status: + state.status === DiscoverSidebarReducerStatus.COMPLETED + ? DiscoverSidebarReducerStatus.INITIAL + : state.status, + }; + case DiscoverSidebarReducerActionType.DOCUMENTS_LOADING: + return { + ...state, + fieldCounts: null, + allFields: action.payload.isPlainRecord ? null : state.allFields, + status: DiscoverSidebarReducerStatus.PROCESSING, + }; + case DiscoverSidebarReducerActionType.DOCUMENTS_LOADED: + const mappedAndUnmappedFields = getDataViewFieldList( + action.payload.dataView, + action.payload.fieldCounts, + action.payload.isPlainRecord + ); + return { + ...state, + dataView: action.payload.dataView, + fieldCounts: action.payload.fieldCounts, + allFields: mappedAndUnmappedFields, + status: + mappedAndUnmappedFields === null + ? DiscoverSidebarReducerStatus.PROCESSING + : DiscoverSidebarReducerStatus.COMPLETED, + }; + } + + return state; +} diff --git a/src/plugins/discover/public/application/main/components/top_nav/open_search_panel.tsx b/src/plugins/discover/public/application/main/components/top_nav/open_search_panel.tsx index 81572cf1ebb53..665ed87323188 100644 --- a/src/plugins/discover/public/application/main/components/top_nav/open_search_panel.tsx +++ b/src/plugins/discover/public/application/main/components/top_nav/open_search_panel.tsx @@ -7,7 +7,7 @@ */ import React from 'react'; -import rison from 'rison-node'; +import rison from '@kbn/rison'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import { diff --git a/src/plugins/discover/public/application/main/discover_main_app.test.tsx b/src/plugins/discover/public/application/main/discover_main_app.test.tsx index 599eaa57aea3d..c487d78836564 100644 --- a/src/plugins/discover/public/application/main/discover_main_app.test.tsx +++ b/src/plugins/discover/public/application/main/discover_main_app.test.tsx @@ -6,6 +6,7 @@ * Side Public License, v 1. */ import React from 'react'; +import { act } from 'react-dom/test-utils'; import { mountWithIntl } from '@kbn/test-jest-helpers'; import { DataViewListItem } from '@kbn/data-views-plugin/public'; import { dataViewMock } from '../../__mocks__/data_view'; @@ -23,7 +24,7 @@ setHeaderActionMenuMounter(jest.fn()); setUrlTracker(urlTrackerMock); describe('DiscoverMainApp', () => { - test('renders', () => { + test('renders', async () => { const dataViewList = [dataViewMock].map((ip) => { return { ...ip, ...{ attributes: { title: ip.title } } }; }) as unknown as DataViewListItem[]; @@ -35,15 +36,21 @@ describe('DiscoverMainApp', () => { initialEntries: ['/'], }); - const component = mountWithIntl( - - - - - - ); + await act(async () => { + const component = await mountWithIntl( + + + + + + ); - expect(component.find(DiscoverTopNav).exists()).toBe(true); - expect(component.find(DiscoverTopNav).prop('dataView')).toEqual(dataViewMock); + // wait for lazy modules + await new Promise((resolve) => setTimeout(resolve, 0)); + await component.update(); + + expect(component.find(DiscoverTopNav).exists()).toBe(true); + expect(component.find(DiscoverTopNav).prop('dataView')).toEqual(dataViewMock); + }); }); }); diff --git a/src/plugins/discover/public/application/main/discover_main_app.tsx b/src/plugins/discover/public/application/main/discover_main_app.tsx index 8ae4bbea6e269..06fe8031829f9 100644 --- a/src/plugins/discover/public/application/main/discover_main_app.tsx +++ b/src/plugins/discover/public/application/main/discover_main_app.tsx @@ -64,6 +64,7 @@ export function DiscoverMainApp(props: DiscoverMainProps) { stateContainer, adHocDataViewList, savedDataViewList, + searchSessionManager, } = useDiscoverState({ services, history: usedHistory, @@ -125,6 +126,7 @@ export function DiscoverMainApp(props: DiscoverMainProps) { updateDataViewList={updateDataViewList} adHocDataViewList={adHocDataViewList} savedDataViewList={savedDataViewList} + searchSessionManager={searchSessionManager} /> ); diff --git a/src/plugins/discover/public/application/main/hooks/use_discover_state.ts b/src/plugins/discover/public/application/main/hooks/use_discover_state.ts index 8d40b20fbc9cd..df61c909c6a8e 100644 --- a/src/plugins/discover/public/application/main/hooks/use_discover_state.ts +++ b/src/plugins/discover/public/application/main/hooks/use_discover_state.ts @@ -194,10 +194,12 @@ export function useDiscoverState({ */ useEffect(() => { const unsubscribe = appStateContainer.subscribe(async (nextState) => { - const { hideChart, interval, sort, index } = state; - // chart was hidden, now it should be displayed, so data is needed - const chartDisplayChanged = nextState.hideChart !== hideChart && hideChart; + const { hideChart, interval, breakdownField, sort, index } = state; + // Cast to boolean to avoid false positives when comparing + // undefined and false, which would trigger a refetch + const chartDisplayChanged = Boolean(nextState.hideChart) !== Boolean(hideChart); const chartIntervalChanged = nextState.interval !== interval; + const breakdownFieldChanged = nextState.breakdownField !== breakdownField; const docTableSortChanged = !isEqual(nextState.sort, sort); const dataViewChanged = !isEqual(nextState.index, index); // NOTE: this is also called when navigating from discover app to context app @@ -230,9 +232,15 @@ export function useDiscoverState({ reset(); } - if (chartDisplayChanged || chartIntervalChanged || docTableSortChanged) { + if ( + chartDisplayChanged || + chartIntervalChanged || + breakdownFieldChanged || + docTableSortChanged + ) { refetch$.next(undefined); } + setState(nextState); }); return () => unsubscribe(); @@ -326,5 +334,6 @@ export function useDiscoverState({ persistDataView, updateAdHocDataViewId, updateDataViewList, + searchSessionManager, }; } diff --git a/src/plugins/discover/public/application/main/hooks/use_inspector.test.ts b/src/plugins/discover/public/application/main/hooks/use_inspector.test.ts index 66c5542f5647a..60327e84f2cd8 100644 --- a/src/plugins/discover/public/application/main/hooks/use_inspector.test.ts +++ b/src/plugins/discover/public/application/main/hooks/use_inspector.test.ts @@ -10,15 +10,23 @@ import { renderHook } from '@testing-library/react-hooks'; import { discoverServiceMock } from '../../../__mocks__/services'; import { savedSearchMock } from '../../../__mocks__/saved_search'; import { useInspector } from './use_inspector'; -import { RequestAdapter } from '@kbn/inspector-plugin/common'; +import { Adapters, RequestAdapter } from '@kbn/inspector-plugin/common'; +import { OverlayRef } from '@kbn/core/public'; +import { AggregateRequestAdapter } from '../utils/aggregate_request_adapter'; describe('test useInspector', () => { test('inspector open function is executed, expanded doc is closed', async () => { const setExpandedDoc = jest.fn(); - + let adapters: Adapters | undefined; + jest.spyOn(discoverServiceMock.inspector, 'open').mockImplementation((localAdapters) => { + adapters = localAdapters; + return {} as OverlayRef; + }); + const requests = new RequestAdapter(); + const lensRequests = new RequestAdapter(); const { result } = renderHook(() => { return useInspector({ - inspectorAdapters: { requests: new RequestAdapter() }, + inspectorAdapters: { requests, lensRequests }, savedSearch: savedSearchMock, inspector: discoverServiceMock.inspector, setExpandedDoc, @@ -27,5 +35,10 @@ describe('test useInspector', () => { result.current(); expect(setExpandedDoc).toHaveBeenCalledWith(undefined); expect(discoverServiceMock.inspector.open).toHaveBeenCalled(); + expect(adapters?.requests).toBeInstanceOf(AggregateRequestAdapter); + expect(adapters?.requests?.getRequests()).toEqual([ + ...requests.getRequests(), + ...lensRequests.getRequests(), + ]); }); }); diff --git a/src/plugins/discover/public/application/main/hooks/use_inspector.ts b/src/plugins/discover/public/application/main/hooks/use_inspector.ts index c7bcc0ba1cb4b..e23ca6425aa71 100644 --- a/src/plugins/discover/public/application/main/hooks/use_inspector.ts +++ b/src/plugins/discover/public/application/main/hooks/use_inspector.ts @@ -14,6 +14,12 @@ import { } from '@kbn/inspector-plugin/public'; import { SavedSearch } from '@kbn/saved-search-plugin/public'; import { DataTableRecord } from '../../../types'; +import { AggregateRequestAdapter } from '../utils/aggregate_request_adapter'; + +export interface InspectorAdapters { + requests: RequestAdapter; + lensRequests?: RequestAdapter; +} export function useInspector({ setExpandedDoc, @@ -21,7 +27,7 @@ export function useInspector({ inspectorAdapters, savedSearch, }: { - inspectorAdapters: { requests: RequestAdapter }; + inspectorAdapters: InspectorAdapters; savedSearch: SavedSearch; setExpandedDoc: (doc?: DataTableRecord) => void; inspector: InspectorPublicPluginStart; @@ -31,11 +37,24 @@ export function useInspector({ const onOpenInspector = useCallback(() => { // prevent overlapping setExpandedDoc(undefined); - const session = inspector.open(inspectorAdapters, { - title: savedSearch.title, - }); + + const requestAdapters = inspectorAdapters.lensRequests + ? [inspectorAdapters.requests, inspectorAdapters.lensRequests] + : [inspectorAdapters.requests]; + + const session = inspector.open( + { requests: new AggregateRequestAdapter(requestAdapters) }, + { title: savedSearch.title } + ); + setInspectorSession(session); - }, [setExpandedDoc, inspectorAdapters, savedSearch, inspector]); + }, [ + setExpandedDoc, + inspectorAdapters.lensRequests, + inspectorAdapters.requests, + inspector, + savedSearch.title, + ]); useEffect(() => { return () => { diff --git a/src/plugins/discover/public/application/main/hooks/use_saved_search.test.ts b/src/plugins/discover/public/application/main/hooks/use_saved_search.test.ts index 34cdeb232be88..f46378053d355 100644 --- a/src/plugins/discover/public/application/main/hooks/use_saved_search.test.ts +++ b/src/plugins/discover/public/application/main/hooks/use_saved_search.test.ts @@ -45,7 +45,6 @@ describe('test useSavedSearch', () => { expect(result.current.data$.main$.getValue().fetchStatus).toBe(FetchStatus.LOADING); expect(result.current.data$.documents$.getValue().fetchStatus).toBe(FetchStatus.LOADING); expect(result.current.data$.totalHits$.getValue().fetchStatus).toBe(FetchStatus.LOADING); - expect(result.current.data$.charts$.getValue().fetchStatus).toBe(FetchStatus.LOADING); }); test('refetch$ triggers a search', async () => { const { history, searchSessionManager } = createSearchSessionMock(); diff --git a/src/plugins/discover/public/application/main/hooks/use_saved_search.ts b/src/plugins/discover/public/application/main/hooks/use_saved_search.ts index 2f097daac982d..4f48945daaad1 100644 --- a/src/plugins/discover/public/application/main/hooks/use_saved_search.ts +++ b/src/plugins/discover/public/application/main/hooks/use_saved_search.ts @@ -25,19 +25,18 @@ import { useBehaviorSubject } from './use_behavior_subject'; import { sendResetMsg } from './use_saved_search_messages'; import { getFetch$ } from '../utils/get_fetch_observable'; import type { DataTableRecord } from '../../../types'; +import type { InspectorAdapters } from './use_inspector'; export interface SavedSearchData { main$: DataMain$; documents$: DataDocuments$; totalHits$: DataTotalHits$; - charts$: DataCharts$; availableFields$: AvailableFields$; } export type DataMain$ = BehaviorSubject; export type DataDocuments$ = BehaviorSubject; export type DataTotalHits$ = BehaviorSubject; -export type DataCharts$ = BehaviorSubject; export type AvailableFields$ = BehaviorSubject; export type DataRefetch$ = Subject; @@ -46,7 +45,7 @@ export interface UseSavedSearch { refetch$: DataRefetch$; data$: SavedSearchData; reset: () => void; - inspectorAdapters: { requests: RequestAdapter }; + inspectorAdapters: InspectorAdapters; } export enum RecordRawType { @@ -78,8 +77,6 @@ export interface DataDocumentsMsg extends DataMsg { } export interface DataTotalHitsMsg extends DataMsg { - fetchStatus: FetchStatus; - error?: Error; result?: number; } @@ -128,7 +125,6 @@ export const useSavedSearch = ({ const main$: DataMain$ = useBehaviorSubject(initialState) as DataMain$; const documents$: DataDocuments$ = useBehaviorSubject(initialState) as DataDocuments$; const totalHits$: DataTotalHits$ = useBehaviorSubject(initialState) as DataTotalHits$; - const charts$: DataCharts$ = useBehaviorSubject(initialState) as DataCharts$; const availableFields$: AvailableFields$ = useBehaviorSubject(initialState) as AvailableFields$; const dataSubjects = useMemo(() => { @@ -136,10 +132,9 @@ export const useSavedSearch = ({ main$, documents$, totalHits$, - charts$, availableFields$, }; - }, [main$, charts$, documents$, totalHits$, availableFields$]); + }, [main$, documents$, totalHits$, availableFields$]); /** * The observable to trigger data fetching in UI diff --git a/src/plugins/discover/public/application/main/hooks/use_saved_search_messages.test.ts b/src/plugins/discover/public/application/main/hooks/use_saved_search_messages.test.ts index 1159aee1c5d13..5973d679b6b1c 100644 --- a/src/plugins/discover/public/application/main/hooks/use_saved_search_messages.test.ts +++ b/src/plugins/discover/public/application/main/hooks/use_saved_search_messages.test.ts @@ -6,8 +6,10 @@ * Side Public License, v 1. */ import { + checkHitCount, sendCompleteMsg, sendErrorMsg, + sendErrorTo, sendLoadingMsg, sendNoResultsFoundMsg, sendPartialMsg, @@ -16,6 +18,7 @@ import { FetchStatus } from '../../types'; import { BehaviorSubject } from 'rxjs'; import { DataMainMsg, RecordRawType } from './use_saved_search'; import { filter } from 'rxjs/operators'; +import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; describe('test useSavedSearch message generators', () => { test('sendCompleteMsg', (done) => { @@ -62,7 +65,10 @@ describe('test useSavedSearch message generators', () => { done(); } }); - sendLoadingMsg(main$, RecordRawType.DOCUMENT); + sendLoadingMsg(main$, { + foundDocuments: true, + recordRawType: RecordRawType.DOCUMENT, + }); }); test('sendErrorMsg', (done) => { const main$ = new BehaviorSubject({ fetchStatus: FetchStatus.PARTIAL }); @@ -92,4 +98,36 @@ describe('test useSavedSearch message generators', () => { }); sendCompleteMsg(main$, false); }); + + test('sendErrorTo', (done) => { + const main$ = new BehaviorSubject({ fetchStatus: FetchStatus.PARTIAL }); + const data = dataPluginMock.createStartContract(); + const error = new Error('Pls help!'); + main$.subscribe((value) => { + expect(data.search.showError).toBeCalledWith(error); + expect(value.fetchStatus).toBe(FetchStatus.ERROR); + expect(value.error).toBe(error); + done(); + }); + sendErrorTo(data, main$)(error); + }); + + test('checkHitCount with hits', (done) => { + const main$ = new BehaviorSubject({ fetchStatus: FetchStatus.LOADING }); + main$.subscribe((value) => { + expect(value.fetchStatus).toBe(FetchStatus.PARTIAL); + done(); + }); + checkHitCount(main$, 100); + }); + + test('checkHitCount without hits', (done) => { + const main$ = new BehaviorSubject({ fetchStatus: FetchStatus.LOADING }); + main$.subscribe((value) => { + expect(value.fetchStatus).toBe(FetchStatus.COMPLETE); + expect(value.foundDocuments).toBe(false); + done(); + }); + checkHitCount(main$, 0); + }); }); diff --git a/src/plugins/discover/public/application/main/hooks/use_saved_search_messages.ts b/src/plugins/discover/public/application/main/hooks/use_saved_search_messages.ts index ae5abb36378a8..ab121f76e15a0 100644 --- a/src/plugins/discover/public/application/main/hooks/use_saved_search_messages.ts +++ b/src/plugins/discover/public/application/main/hooks/use_saved_search_messages.ts @@ -6,14 +6,14 @@ * Side Public License, v 1. */ -import { AggregateQuery, Query } from '@kbn/es-query'; +import { DataPublicPluginStart } from '@kbn/data-plugin/public'; +import type { BehaviorSubject } from 'rxjs'; import { FetchStatus } from '../../types'; -import { - DataCharts$, +import type { DataDocuments$, DataMain$, + DataMsg, DataTotalHits$, - RecordRawType, SavedSearchData, } from './use_saved_search'; @@ -60,27 +60,22 @@ export function sendPartialMsg(main$: DataMain$) { /** * Send LOADING message via main observable */ -export function sendLoadingMsg( - data$: DataMain$ | DataDocuments$ | DataTotalHits$ | DataCharts$, - recordRawType: RecordRawType, - query?: AggregateQuery | Query +export function sendLoadingMsg( + data$: BehaviorSubject, + props: Omit ) { if (data$.getValue().fetchStatus !== FetchStatus.LOADING) { data$.next({ + ...props, fetchStatus: FetchStatus.LOADING, - recordRawType, - query, - }); + } as T); } } /** * Send ERROR message */ -export function sendErrorMsg( - data$: DataMain$ | DataDocuments$ | DataTotalHits$ | DataCharts$, - error: Error -) { +export function sendErrorMsg(data$: DataMain$ | DataDocuments$ | DataTotalHits$, error: Error) { const recordRawType = data$.getValue().recordRawType; data$.next({ fetchStatus: FetchStatus.ERROR, @@ -105,14 +100,43 @@ export function sendResetMsg(data: SavedSearchData, initialFetchStatus: FetchSta result: [], recordRawType, }); - data.charts$.next({ - fetchStatus: initialFetchStatus, - response: undefined, - recordRawType, - }); data.totalHits$.next({ fetchStatus: initialFetchStatus, result: undefined, recordRawType, }); } + +/** + * Method to create an error handler that will forward the received error + * to the specified subjects. It will ignore AbortErrors and will use the data + * plugin to show a toast for the error (e.g. allowing better insights into shard failures). + */ +export const sendErrorTo = ( + data: DataPublicPluginStart, + ...errorSubjects: Array +) => { + return (error: Error) => { + if (error instanceof Error && error.name === 'AbortError') { + return; + } + + data.search.showError(error); + errorSubjects.forEach((subject) => sendErrorMsg(subject, error)); + }; +}; + +/** + * This method checks the passed in hit count and will send a PARTIAL message to main$ + * if there are results, indicating that we have finished some of the requests that have been + * sent. If there are no results we already COMPLETE main$ with no results found, so Discover + * can show the "no results" screen. We know at that point, that the other query returning + * will neither carry any data, since there are no documents. + */ +export const checkHitCount = (main$: DataMain$, hitsCount: number) => { + if (hitsCount > 0) { + sendPartialMsg(main$); + } else { + sendNoResultsFoundMsg(main$); + } +}; diff --git a/src/plugins/discover/public/application/main/services/discover_search_session.ts b/src/plugins/discover/public/application/main/services/discover_search_session.ts index 5797b0381b1bf..0cbaf74159a80 100644 --- a/src/plugins/discover/public/application/main/services/discover_search_session.ts +++ b/src/plugins/discover/public/application/main/services/discover_search_session.ts @@ -31,6 +31,8 @@ export class DiscoverSearchSessionManager { * skips if `searchSessionId` matches current search session id */ readonly newSearchSessionIdFromURL$: Rx.Observable; + readonly searchSessionId$: Rx.Observable; + private readonly deps: DiscoverSearchSessionManagerDeps; constructor(deps: DiscoverSearchSessionManagerDeps) { @@ -44,6 +46,7 @@ export class DiscoverSearchSessionManager { return !this.deps.session.isCurrentSession(searchSessionId); }) ); + this.searchSessionId$ = this.deps.session.getSession$(); } /** diff --git a/src/plugins/discover/public/application/main/services/discover_state.ts b/src/plugins/discover/public/application/main/services/discover_state.ts index 611b59eacdc79..77e870dfc75a5 100644 --- a/src/plugins/discover/public/application/main/services/discover_state.ts +++ b/src/plugins/discover/public/application/main/services/discover_state.ts @@ -98,6 +98,10 @@ export interface AppState { * Number of rows in the grid per page */ rowsPerPage?: number; + /** + * Current histogram breakdown field name + */ + breakdownField?: string; } export interface AppStateUrl extends Omit { @@ -447,5 +451,6 @@ function createUrlGeneratorState({ useHash: false, viewMode: appState.viewMode, hideAggregatedPreview: appState.hideAggregatedPreview, + breakdownField: appState.breakdownField, }; } diff --git a/src/plugins/discover/public/application/main/utils/aggregate_request_adapter.test.ts b/src/plugins/discover/public/application/main/utils/aggregate_request_adapter.test.ts new file mode 100644 index 0000000000000..effbb192e863b --- /dev/null +++ b/src/plugins/discover/public/application/main/utils/aggregate_request_adapter.test.ts @@ -0,0 +1,42 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 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 { RequestAdapter } from '@kbn/inspector-plugin/common'; +import { AggregateRequestAdapter } from './aggregate_request_adapter'; + +describe('AggregateRequestAdapter', () => { + it('should return all requests from all adapters', () => { + const adapter1 = new RequestAdapter(); + const adapter2 = new RequestAdapter(); + const adapter3 = new RequestAdapter(); + const aggregateAdapter = new AggregateRequestAdapter([adapter1, adapter2, adapter3]); + adapter1.start('request1'); + adapter2.start('request2'); + adapter3.start('request3'); + expect(aggregateAdapter.getRequests().map((request) => request.name)).toEqual([ + 'request1', + 'request2', + 'request3', + ]); + }); + + it('should allow adding and removing change listeners for all adapters', () => { + const adapter1 = new RequestAdapter(); + const adapter2 = new RequestAdapter(); + const aggregateAdapter = new AggregateRequestAdapter([adapter1, adapter2]); + const listener = jest.fn(); + aggregateAdapter.addListener('change', listener); + adapter1.start('request1'); + adapter2.start('request2'); + expect(listener).toHaveBeenCalledTimes(2); + aggregateAdapter.removeListener('change', listener); + adapter1.start('request3'); + adapter2.start('request4'); + expect(listener).toHaveBeenCalledTimes(2); + }); +}); diff --git a/src/plugins/discover/public/application/main/utils/aggregate_request_adapter.ts b/src/plugins/discover/public/application/main/utils/aggregate_request_adapter.ts new file mode 100644 index 0000000000000..4ce55c0723a11 --- /dev/null +++ b/src/plugins/discover/public/application/main/utils/aggregate_request_adapter.ts @@ -0,0 +1,132 @@ +/* + * Copyright 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 { RequestAdapter, Request } from '@kbn/inspector-plugin/public'; + +/** + * A request adapter that aggregates multiple separate adapters into one to allow inspection + */ +export class AggregateRequestAdapter extends RequestAdapter { + private readonly adapters: RequestAdapter[]; + + constructor(adapters: RequestAdapter[]) { + super(); + this.adapters = adapters; + } + + public reset(...args: Parameters): void { + super.reset(...args); + this.adapters.forEach((adapter) => adapter.reset(...args)); + } + + public resetRequest(...args: Parameters): void { + super.resetRequest(...args); + this.adapters.forEach((adapter) => adapter.resetRequest(...args)); + } + + public getRequests(...args: Parameters): Request[] { + return [ + ...super.getRequests(), + ...this.adapters.map((adapter) => adapter.getRequests(...args)).flat(), + ]; + } + + public addListener(...args: Parameters): this { + super.addListener(...args); + this.adapters.forEach((adapter) => adapter.addListener(...args)); + return this; + } + + public on(...args: Parameters): this { + super.on(...args); + this.adapters.forEach((adapter) => adapter.on(...args)); + return this; + } + + public once(...args: Parameters): this { + super.once(...args); + this.adapters.forEach((adapter) => adapter.once(...args)); + return this; + } + + public removeListener(...args: Parameters): this { + super.removeListener(...args); + this.adapters.forEach((adapter) => adapter.removeListener(...args)); + return this; + } + + public off(...args: Parameters): this { + super.off(...args); + this.adapters.forEach((adapter) => adapter.off(...args)); + return this; + } + + public removeAllListeners(...args: Parameters): this { + super.removeAllListeners(...args); + this.adapters.forEach((adapter) => adapter.removeAllListeners(...args)); + return this; + } + + public setMaxListeners(...args: Parameters): this { + super.setMaxListeners(...args); + this.adapters.forEach((adapter) => adapter.setMaxListeners(...args)); + return this; + } + + public getMaxListeners(...args: Parameters): number { + return Math.min( + super.getMaxListeners(...args), + ...this.adapters.map((adapter) => adapter.getMaxListeners(...args)) + ); + } + + public listeners(...args: Parameters): Function[] { + return [ + ...super.listeners(...args), + ...this.adapters.map((adapter) => adapter.listeners(...args)).flat(), + ]; + } + + public rawListeners(...args: Parameters): Function[] { + return [ + ...super.rawListeners(...args), + ...this.adapters.map((adapter) => adapter.rawListeners(...args)).flat(), + ]; + } + + public emit(...args: Parameters): boolean { + return [super.emit(...args), ...this.adapters.map((adapter) => adapter.emit(...args))].every( + (result) => result + ); + } + + public listenerCount(...args: Parameters): number { + return this.adapters + .map((adapter) => adapter.listenerCount(...args)) + .reduce((a, b) => a + b, super.listenerCount(...args)); + } + + public prependListener(...args: Parameters): this { + super.prependListener(...args); + this.adapters.forEach((adapter) => adapter.prependListener(...args)); + return this; + } + + public prependOnceListener(...args: Parameters): this { + super.prependOnceListener(...args); + this.adapters.forEach((adapter) => adapter.prependOnceListener(...args)); + return this; + } + + public eventNames(...args: Parameters): Array { + return [ + ...super.eventNames(...args), + ...this.adapters.map((adapter) => adapter.eventNames(...args)).flat(), + ]; + } +} diff --git a/src/plugins/discover/public/application/main/utils/calc_field_counts.test.ts b/src/plugins/discover/public/application/main/utils/calc_field_counts.test.ts index 5116bb78789ca..0aace63eb7754 100644 --- a/src/plugins/discover/public/application/main/utils/calc_field_counts.test.ts +++ b/src/plugins/discover/public/application/main/utils/calc_field_counts.test.ts @@ -7,7 +7,6 @@ */ import { calcFieldCounts } from './calc_field_counts'; -import { dataViewMock } from '../../../__mocks__/data_view'; import { buildDataTableRecord } from '../../../utils/build_data_record'; describe('calcFieldCounts', () => { @@ -16,7 +15,7 @@ describe('calcFieldCounts', () => { { _id: '1', _index: 'test', _source: { message: 'test1', bytes: 20 } }, { _id: '2', _index: 'test', _source: { name: 'test2', extension: 'jpg' } }, ].map((row) => buildDataTableRecord(row)); - const result = calcFieldCounts(rows, dataViewMock); + const result = calcFieldCounts(rows); expect(result).toMatchInlineSnapshot(` Object { "bytes": 1, @@ -31,7 +30,7 @@ describe('calcFieldCounts', () => { { _id: '1', _index: 'test', _source: { message: 'test1', bytes: 20 } }, { _id: '2', _index: 'test', _source: { name: 'test2', extension: 'jpg' } }, ].map((row) => buildDataTableRecord(row)); - const result = calcFieldCounts(rows, dataViewMock); + const result = calcFieldCounts(rows); expect(result).toMatchInlineSnapshot(` Object { "bytes": 1, diff --git a/src/plugins/discover/public/application/main/utils/calc_field_counts.ts b/src/plugins/discover/public/application/main/utils/calc_field_counts.ts index 10cdd92d9a250..2fd089816f9fb 100644 --- a/src/plugins/discover/public/application/main/utils/calc_field_counts.ts +++ b/src/plugins/discover/public/application/main/utils/calc_field_counts.ts @@ -5,24 +5,24 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ -import { DataView } from '@kbn/data-views-plugin/public'; import { DataTableRecord } from '../../../types'; /** * This function is calculating stats of the available fields, for usage in sidebar and sharing * Note that this values aren't displayed, but used for internal calculations */ -export function calcFieldCounts(rows?: DataTableRecord[], dataView?: DataView) { +export function calcFieldCounts(rows?: DataTableRecord[]) { const counts: Record = {}; - if (!rows || !dataView) { + if (!rows) { return {}; } - for (const hit of rows) { + + rows.forEach((hit) => { const fields = Object.keys(hit.flattened); - for (const fieldName of fields) { + fields.forEach((fieldName) => { counts[fieldName] = (counts[fieldName] || 0) + 1; - } - } + }); + }); return counts; } diff --git a/src/plugins/discover/public/application/main/utils/fetch_all.test.ts b/src/plugins/discover/public/application/main/utils/fetch_all.test.ts index 59dbc3ffe73d8..5258de6bdfdad 100644 --- a/src/plugins/discover/public/application/main/utils/fetch_all.test.ts +++ b/src/plugins/discover/public/application/main/utils/fetch_all.test.ts @@ -17,20 +17,17 @@ import { discoverServiceMock } from '../../../__mocks__/services'; import { fetchAll } from './fetch_all'; import { DataAvailableFieldsMsg, - DataChartsMessage, DataDocumentsMsg, DataMainMsg, DataTotalHitsMsg, + RecordRawType, SavedSearchData, } from '../hooks/use_saved_search'; import { fetchDocuments } from './fetch_documents'; import { fetchSql } from './fetch_sql'; -import { fetchChart } from './fetch_chart'; -import { fetchTotalHits } from './fetch_total_hits'; import { buildDataTableRecord } from '../../../utils/build_data_record'; import { dataViewMock } from '../../../__mocks__/data_view'; -import type { SearchResponse } from '@elastic/elasticsearch/lib/api/types'; jest.mock('./fetch_documents', () => ({ fetchDocuments: jest.fn().mockResolvedValue([]), @@ -40,17 +37,7 @@ jest.mock('./fetch_sql', () => ({ fetchSql: jest.fn().mockResolvedValue([]), })); -jest.mock('./fetch_chart', () => ({ - fetchChart: jest.fn(), -})); - -jest.mock('./fetch_total_hits', () => ({ - fetchTotalHits: jest.fn(), -})); - const mockFetchDocuments = fetchDocuments as unknown as jest.MockedFunction; -const mockFetchTotalHits = fetchTotalHits as unknown as jest.MockedFunction; -const mockFetchChart = fetchChart as unknown as jest.MockedFunction; const mockFetchSQL = fetchSql as unknown as jest.MockedFunction; function subjectCollector(subject: Subject): () => Promise { @@ -64,6 +51,8 @@ function subjectCollector(subject: Subject): () => Promise { }; } +const waitForNextTick = () => new Promise((resolve) => setTimeout(resolve, 0)); + describe('test fetchAll', () => { let subjects: SavedSearchData; let deps: Parameters[3]; @@ -73,7 +62,6 @@ describe('test fetchAll', () => { main$: new BehaviorSubject({ fetchStatus: FetchStatus.UNINITIALIZED }), documents$: new BehaviorSubject({ fetchStatus: FetchStatus.UNINITIALIZED }), totalHits$: new BehaviorSubject({ fetchStatus: FetchStatus.UNINITIALIZED }), - charts$: new BehaviorSubject({ fetchStatus: FetchStatus.UNINITIALIZED }), availableFields$: new BehaviorSubject({ fetchStatus: FetchStatus.UNINITIALIZED, }), @@ -97,10 +85,6 @@ describe('test fetchAll', () => { mockFetchDocuments.mockReset().mockResolvedValue([]); mockFetchSQL.mockReset().mockResolvedValue([]); - mockFetchTotalHits.mockReset().mockResolvedValue(42); - mockFetchChart - .mockReset() - .mockResolvedValue({ totalHits: 42, response: {} as unknown as SearchResponse }); }); test('changes of fetchStatus when starting with FetchStatus.UNINITIALIZED', async () => { @@ -108,7 +92,8 @@ describe('test fetchAll', () => { subjects.main$.subscribe((value) => stateArr.push(value.fetchStatus)); - await fetchAll(subjects, searchSource, false, deps); + fetchAll(subjects, searchSource, false, deps); + await waitForNextTick(); expect(stateArr).toEqual([ FetchStatus.UNINITIALIZED, @@ -125,7 +110,8 @@ describe('test fetchAll', () => { ]; const documents = hits.map((hit) => buildDataTableRecord(hit, dataViewMock)); mockFetchDocuments.mockResolvedValue(documents); - await fetchAll(subjects, searchSource, false, deps); + fetchAll(subjects, searchSource, false, deps); + await waitForNextTick(); expect(await collect()).toEqual([ { fetchStatus: FetchStatus.UNINITIALIZED }, { fetchStatus: FetchStatus.LOADING, recordRawType: 'document' }, @@ -147,8 +133,18 @@ describe('test fetchAll', () => { const documents = hits.map((hit) => buildDataTableRecord(hit, dataViewMock)); mockFetchDocuments.mockResolvedValue(documents); - mockFetchTotalHits.mockResolvedValue(42); - await fetchAll(subjects, searchSource, false, deps); + subjects.totalHits$.next({ + fetchStatus: FetchStatus.LOADING, + recordRawType: RecordRawType.DOCUMENT, + }); + fetchAll(subjects, searchSource, false, deps); + await waitForNextTick(); + subjects.totalHits$.next({ + fetchStatus: FetchStatus.COMPLETE, + recordRawType: RecordRawType.DOCUMENT, + result: 42, + }); + expect(await collect()).toEqual([ { fetchStatus: FetchStatus.UNINITIALIZED }, { fetchStatus: FetchStatus.LOADING, recordRawType: 'document' }, @@ -157,44 +153,48 @@ describe('test fetchAll', () => { ]); }); - test('emits loading and response on charts$ correctly', async () => { - const collect = subjectCollector(subjects.charts$); - searchSource.getField('index')!.isTimeBased = () => true; - await fetchAll(subjects, searchSource, false, deps); - expect(await collect()).toEqual([ - { fetchStatus: FetchStatus.UNINITIALIZED }, - { fetchStatus: FetchStatus.LOADING, recordRawType: 'document' }, - { - fetchStatus: FetchStatus.COMPLETE, - recordRawType: 'document', - response: {}, - }, - ]); - }); - test('should use charts query to fetch total hit count when chart is visible', async () => { const collect = subjectCollector(subjects.totalHits$); searchSource.getField('index')!.isTimeBased = () => true; - mockFetchChart.mockResolvedValue({ totalHits: 32, response: {} as unknown as SearchResponse }); - await fetchAll(subjects, searchSource, false, deps); + subjects.totalHits$.next({ + fetchStatus: FetchStatus.LOADING, + recordRawType: RecordRawType.DOCUMENT, + }); + fetchAll(subjects, searchSource, false, deps); + await waitForNextTick(); + subjects.totalHits$.next({ + fetchStatus: FetchStatus.COMPLETE, + recordRawType: RecordRawType.DOCUMENT, + result: 32, + }); + expect(await collect()).toEqual([ { fetchStatus: FetchStatus.UNINITIALIZED }, { fetchStatus: FetchStatus.LOADING, recordRawType: 'document' }, { fetchStatus: FetchStatus.PARTIAL, recordRawType: 'document', result: 0 }, // From documents query { fetchStatus: FetchStatus.COMPLETE, recordRawType: 'document', result: 32 }, ]); - expect(mockFetchTotalHits).not.toHaveBeenCalled(); }); test('should only fail totalHits$ query not main$ for error from that query', async () => { const collectTotalHits = subjectCollector(subjects.totalHits$); const collectMain = subjectCollector(subjects.main$); searchSource.getField('index')!.isTimeBased = () => false; - mockFetchTotalHits.mockRejectedValue({ msg: 'Oh noes!' }); const hits = [{ _id: '1', _index: 'logs' }]; const documents = hits.map((hit) => buildDataTableRecord(hit, dataViewMock)); mockFetchDocuments.mockResolvedValue(documents); - await fetchAll(subjects, searchSource, false, deps); + subjects.totalHits$.next({ + fetchStatus: FetchStatus.LOADING, + recordRawType: RecordRawType.DOCUMENT, + }); + fetchAll(subjects, searchSource, false, deps); + await waitForNextTick(); + subjects.totalHits$.next({ + fetchStatus: FetchStatus.ERROR, + recordRawType: RecordRawType.DOCUMENT, + error: { msg: 'Oh noes!' } as unknown as Error, + }); + expect(await collectTotalHits()).toEqual([ { fetchStatus: FetchStatus.UNINITIALIZED }, { fetchStatus: FetchStatus.LOADING, recordRawType: 'document' }, @@ -218,11 +218,21 @@ describe('test fetchAll', () => { const collectMain = subjectCollector(subjects.main$); searchSource.getField('index')!.isTimeBased = () => false; mockFetchDocuments.mockRejectedValue({ msg: 'This query failed' }); - await fetchAll(subjects, searchSource, false, deps); + subjects.totalHits$.next({ + fetchStatus: FetchStatus.LOADING, + recordRawType: RecordRawType.DOCUMENT, + }); + fetchAll(subjects, searchSource, false, deps); + await waitForNextTick(); + subjects.totalHits$.next({ + fetchStatus: FetchStatus.COMPLETE, + recordRawType: RecordRawType.DOCUMENT, + result: 5, + }); + expect(await collectMain()).toEqual([ { fetchStatus: FetchStatus.UNINITIALIZED }, { fetchStatus: FetchStatus.LOADING, recordRawType: 'document' }, - { fetchStatus: FetchStatus.PARTIAL, recordRawType: 'document' }, // From totalHits query { fetchStatus: FetchStatus.ERROR, error: { msg: 'This query failed' }, @@ -256,7 +266,9 @@ describe('test fetchAll', () => { savedSearch: savedSearchMock, services: discoverServiceMock, }; - await fetchAll(subjects, searchSource, false, deps); + fetchAll(subjects, searchSource, false, deps); + await waitForNextTick(); + expect(await collect()).toEqual([ { fetchStatus: FetchStatus.UNINITIALIZED }, { fetchStatus: FetchStatus.LOADING, recordRawType: 'plain', query }, diff --git a/src/plugins/discover/public/application/main/utils/fetch_all.ts b/src/plugins/discover/public/application/main/utils/fetch_all.ts index d530da1492fac..d782442db3953 100644 --- a/src/plugins/discover/public/application/main/utils/fetch_all.ts +++ b/src/plugins/discover/public/application/main/utils/fetch_all.ts @@ -8,31 +8,22 @@ import { DataPublicPluginStart, ISearchSource } from '@kbn/data-plugin/public'; import { Adapters } from '@kbn/inspector-plugin/common'; import { ReduxLikeStateContainer } from '@kbn/kibana-utils-plugin/common'; -import { DataViewType } from '@kbn/data-views-plugin/public'; import type { SavedSearch, SortOrder } from '@kbn/saved-search-plugin/public'; +import { BehaviorSubject, filter, firstValueFrom, map, merge, scan } from 'rxjs'; import { getRawRecordType } from './get_raw_record_type'; import { + checkHitCount, sendCompleteMsg, sendErrorMsg, + sendErrorTo, sendLoadingMsg, - sendNoResultsFoundMsg, - sendPartialMsg, sendResetMsg, } from '../hooks/use_saved_search_messages'; import { updateSearchSource } from './update_search_source'; import { fetchDocuments } from './fetch_documents'; -import { fetchTotalHits } from './fetch_total_hits'; -import { fetchChart } from './fetch_chart'; import { AppState } from '../services/discover_state'; import { FetchStatus } from '../../types'; -import { - DataCharts$, - DataDocuments$, - DataMain$, - DataTotalHits$, - RecordRawType, - SavedSearchData, -} from '../hooks/use_saved_search'; +import { DataMsg, RecordRawType, SavedSearchData } from '../hooks/use_saved_search'; import { DiscoverServices } from '../../../build_services'; import { fetchSql } from './fetch_sql'; @@ -50,8 +41,7 @@ export interface FetchDeps { /** * This function starts fetching all required queries in Discover. This will be the query to load the individual - * documents, and depending on whether a chart is shown either the aggregation query to load the chart data - * or a query to retrieve just the total hits. + * documents as well as any other requests that might be required to load the main view. * * This method returns a promise, which will resolve (without a value), as soon as all queries that have been started * have been completed (failed or successfully). @@ -64,30 +54,12 @@ export function fetchAll( ): Promise { const { initialFetchStatus, appStateContainer, services, useNewFieldsApi, data } = fetchDeps; - /** - * Method to create an error handler that will forward the received error - * to the specified subjects. It will ignore AbortErrors and will use the data - * plugin to show a toast for the error (e.g. allowing better insights into shard failures). - */ - const sendErrorTo = ( - ...errorSubjects: Array - ) => { - return (error: Error) => { - if (error instanceof Error && error.name === 'AbortError') { - return; - } - - data.search.showError(error); - errorSubjects.forEach((subject) => sendErrorMsg(subject, error)); - }; - }; - try { const dataView = searchSource.getField('index')!; if (reset) { sendResetMsg(dataSubjects, initialFetchStatus); } - const { hideChart, sort, query } = appStateContainer.getState(); + const { sort, query } = appStateContainer.getState(); const recordRawType = getRawRecordType(query); const useSql = recordRawType === RecordRawType.PLAIN; @@ -102,40 +74,17 @@ export function fetchAll( } // Mark all subjects as loading - sendLoadingMsg(dataSubjects.main$, recordRawType); - sendLoadingMsg(dataSubjects.documents$, recordRawType, query); - sendLoadingMsg(dataSubjects.totalHits$, recordRawType); - sendLoadingMsg(dataSubjects.charts$, recordRawType); - - const isChartVisible = - !hideChart && dataView.isTimeBased() && dataView.type !== DataViewType.ROLLUP; + sendLoadingMsg(dataSubjects.main$, { recordRawType }); + sendLoadingMsg(dataSubjects.documents$, { recordRawType, query }); + sendLoadingMsg(dataSubjects.totalHits$, { recordRawType }); // Start fetching all required requests const documents = useSql && query ? fetchSql(query, services.dataViews, data, services.expressions) : fetchDocuments(searchSource.createCopy(), fetchDeps); - const charts = - isChartVisible && !useSql ? fetchChart(searchSource.createCopy(), fetchDeps) : undefined; - const totalHits = - !isChartVisible && !useSql ? fetchTotalHits(searchSource.createCopy(), fetchDeps) : undefined; - /** - * This method checks the passed in hit count and will send a PARTIAL message to main$ - * if there are results, indicating that we have finished some of the requests that have been - * sent. If there are no results we already COMPLETE main$ with no results found, so Discover - * can show the "no results" screen. We know at that point, that the other query returning - * will neither carry any data, since there are no documents. - */ - const checkHitCount = (hitsCount: number) => { - if (hitsCount > 0) { - sendPartialMsg(dataSubjects.main$); - } else { - sendNoResultsFoundMsg(dataSubjects.main$); - } - }; // Handle results of the individual queries and forward the results to the corresponding dataSubjects - documents .then((docs) => { // If the total hits (or chart) query is still loading, emit a partial @@ -155,44 +104,20 @@ export function fetchAll( query, }); - checkHitCount(docs.length); + checkHitCount(dataSubjects.main$, docs.length); }) // Only the document query should send its errors to main$, to cause the full Discover app // to get into an error state. The other queries will not cause all of Discover to error out // but their errors will be shown in-place (e.g. of the chart). - .catch(sendErrorTo(dataSubjects.documents$, dataSubjects.main$)); - - charts - ?.then((chart) => { - dataSubjects.totalHits$.next({ - fetchStatus: FetchStatus.COMPLETE, - result: chart.totalHits, - recordRawType, - }); - - dataSubjects.charts$.next({ - fetchStatus: FetchStatus.COMPLETE, - response: chart.response, - recordRawType, - }); - - checkHitCount(chart.totalHits); - }) - .catch(sendErrorTo(dataSubjects.charts$, dataSubjects.totalHits$)); - - totalHits - ?.then((hitCount) => { - dataSubjects.totalHits$.next({ - fetchStatus: FetchStatus.COMPLETE, - result: hitCount, - recordRawType, - }); - checkHitCount(hitCount); - }) - .catch(sendErrorTo(dataSubjects.totalHits$)); + .catch(sendErrorTo(data, dataSubjects.documents$, dataSubjects.main$)); // Return a promise that will resolve once all the requests have finished or failed - return Promise.allSettled([documents, charts, totalHits]).then(() => { + return firstValueFrom( + merge( + fetchStatusByType(dataSubjects.documents$, 'documents'), + fetchStatusByType(dataSubjects.totalHits$, 'totalHits') + ).pipe(scan(toRequestFinishedMap, {}), filter(allRequestsFinished)) + ).then(() => { // Send a complete message to main$ once all queries are done and if main$ // is not already in an ERROR state, e.g. because the document query has failed. // This will only complete main$, if it hasn't already been completed previously @@ -207,3 +132,17 @@ export function fetchAll( return Promise.resolve(); } } + +const fetchStatusByType = (subject: BehaviorSubject, type: string) => + subject.pipe(map(({ fetchStatus }) => ({ type, fetchStatus }))); + +const toRequestFinishedMap = ( + currentMap: Record, + { type, fetchStatus }: { type: string; fetchStatus: FetchStatus } +) => ({ + ...currentMap, + [type]: [FetchStatus.COMPLETE, FetchStatus.ERROR].includes(fetchStatus), +}); + +const allRequestsFinished = (requests: Record) => + Object.values(requests).every((finished) => finished); diff --git a/src/plugins/discover/public/application/main/utils/fetch_chart.test.ts b/src/plugins/discover/public/application/main/utils/fetch_chart.test.ts deleted file mode 100644 index e1020404d3996..0000000000000 --- a/src/plugins/discover/public/application/main/utils/fetch_chart.test.ts +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ -import { of, throwError as throwErrorRx } from 'rxjs'; -import { RequestAdapter } from '@kbn/inspector-plugin/common'; -import { savedSearchMockWithTimeField } from '../../../__mocks__/saved_search'; -import { fetchChart, updateSearchSource } from './fetch_chart'; -import { ReduxLikeStateContainer } from '@kbn/kibana-utils-plugin/common'; -import { AppState } from '../services/discover_state'; -import { discoverServiceMock } from '../../../__mocks__/services'; -import { calculateBounds } from '@kbn/data-plugin/public'; -import { FetchDeps } from './fetch_all'; - -function getDeps() { - const deps = { - appStateContainer: { - getState: () => { - return { interval: 'auto' }; - }, - } as ReduxLikeStateContainer, - abortController: new AbortController(), - data: discoverServiceMock.data, - inspectorAdapters: { requests: new RequestAdapter() }, - onResults: jest.fn(), - savedSearch: savedSearchMockWithTimeField, - searchSessionId: '123', - } as unknown as FetchDeps; - deps.data.query.timefilter.timefilter.getTime = () => { - return { from: '2021-07-07T00:05:13.590', to: '2021-07-07T11:20:13.590' }; - }; - - deps.data.query.timefilter.timefilter.calculateBounds = (timeRange) => calculateBounds(timeRange); - return deps; -} - -const requestResult = { - id: 'Fjk5bndxTHJWU2FldVRVQ0tYR0VqOFEcRWtWNDhOdG5SUzJYcFhONVVZVTBJQToxMDMwOQ==', - rawResponse: { - took: 2, - timed_out: false, - _shards: { total: 1, successful: 1, skipped: 0, failed: 0 }, - hits: { max_score: null, hits: [], total: 42 }, - aggregations: { - '2': { - buckets: [ - { - key_as_string: '2021-07-07T06:36:00.000+02:00', - key: 1625632560000, - doc_count: 1, - }, - ], - }, - }, - }, - isPartial: false, - isRunning: false, - total: 1, - loaded: 1, - isRestored: false, -}; - -describe('test fetchCharts', () => { - test('updateSearchSource helper function', () => { - const chartAggConfigs = updateSearchSource( - savedSearchMockWithTimeField.searchSource, - 'auto', - discoverServiceMock.data - ); - expect(chartAggConfigs.aggs).toMatchInlineSnapshot(` - Array [ - Object { - "enabled": true, - "id": "1", - "params": Object { - "emptyAsNull": false, - }, - "schema": "metric", - "type": "count", - }, - Object { - "enabled": true, - "id": "2", - "params": Object { - "drop_partials": false, - "extendToTimeRange": false, - "extended_bounds": Object {}, - "field": "timestamp", - "interval": "auto", - "min_doc_count": 1, - "scaleMetricValues": false, - "useNormalizedEsInterval": true, - "used_interval": "0ms", - }, - "schema": "segment", - "type": "date_histogram", - }, - ] - `); - }); - - test('resolves with summarized chart data', async () => { - savedSearchMockWithTimeField.searchSource.fetch$ = () => of(requestResult); - - const result = await fetchChart(savedSearchMockWithTimeField.searchSource, getDeps()); - expect(result).toHaveProperty('totalHits', 42); - expect(result).toHaveProperty('response'); - }); - - test('rejects promise on query failure', async () => { - savedSearchMockWithTimeField.searchSource.fetch$ = () => - throwErrorRx(() => new Error('Oh noes!')); - - await expect(fetchChart(savedSearchMockWithTimeField.searchSource, getDeps())).rejects.toEqual( - new Error('Oh noes!') - ); - }); - - test('fetch$ is called with request specific execution context', async () => { - const fetch$Mock = jest.fn().mockReturnValue(of(requestResult)); - - savedSearchMockWithTimeField.searchSource.fetch$ = fetch$Mock; - - await fetchChart(savedSearchMockWithTimeField.searchSource, getDeps()); - expect(fetch$Mock.mock.calls[0][0].executionContext).toMatchInlineSnapshot(` - Object { - "description": "fetch chart data and total hits", - } - `); - }); -}); diff --git a/src/plugins/discover/public/application/main/utils/fetch_chart.ts b/src/plugins/discover/public/application/main/utils/fetch_chart.ts deleted file mode 100644 index e4e5b67782cb9..0000000000000 --- a/src/plugins/discover/public/application/main/utils/fetch_chart.ts +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { i18n } from '@kbn/i18n'; -import { filter, map } from 'rxjs/operators'; -import { lastValueFrom } from 'rxjs'; -import { DataPublicPluginStart, isCompleteResponse, ISearchSource } from '@kbn/data-plugin/public'; -import type { SearchResponse } from '@elastic/elasticsearch/lib/api/types'; -import { getChartAggConfigs } from '@kbn/unified-histogram-plugin/public'; -import { FetchDeps } from './fetch_all'; - -interface Result { - totalHits: number; - response: SearchResponse; -} - -export function fetchChart( - searchSource: ISearchSource, - { abortController, appStateContainer, data, inspectorAdapters, searchSessionId }: FetchDeps -): Promise { - const timeInterval = appStateContainer.getState().interval ?? 'auto'; - - updateSearchSource(searchSource, timeInterval, data); - - const executionContext = { - description: 'fetch chart data and total hits', - }; - - const fetch$ = searchSource - .fetch$({ - abortSignal: abortController.signal, - sessionId: searchSessionId, - inspector: { - adapter: inspectorAdapters.requests, - title: i18n.translate('discover.inspectorRequestDataTitleChart', { - defaultMessage: 'Chart data', - }), - description: i18n.translate('discover.inspectorRequestDescriptionChart', { - defaultMessage: - 'This request queries Elasticsearch to fetch the aggregation data for the chart.', - }), - }, - executionContext, - }) - .pipe( - filter((res) => isCompleteResponse(res)), - map((res) => ({ - response: res.rawResponse, - totalHits: res.rawResponse.hits.total as number, - })) - ); - - return lastValueFrom(fetch$); -} - -export function updateSearchSource( - searchSource: ISearchSource, - timeInterval: string, - data: DataPublicPluginStart -) { - const dataView = searchSource.getField('index')!; - searchSource.setField('filter', data.query.timefilter.timefilter.createFilter(dataView)); - searchSource.setField('size', 0); - searchSource.setField('trackTotalHits', true); - const chartAggConfigs = getChartAggConfigs({ dataView, timeInterval, data }); - searchSource.setField('aggs', chartAggConfigs.toDsl()); - searchSource.removeField('sort'); - searchSource.removeField('fields'); - return chartAggConfigs; -} diff --git a/src/plugins/discover/public/application/main/utils/fetch_documents.test.ts b/src/plugins/discover/public/application/main/utils/fetch_documents.test.ts index 4809da54655be..28738cdc522c9 100644 --- a/src/plugins/discover/public/application/main/utils/fetch_documents.test.ts +++ b/src/plugins/discover/public/application/main/utils/fetch_documents.test.ts @@ -8,12 +8,11 @@ import { fetchDocuments } from './fetch_documents'; import { throwError as throwErrorRx, of } from 'rxjs'; import { RequestAdapter } from '@kbn/inspector-plugin/common'; -import { savedSearchMock, savedSearchMockWithTimeField } from '../../../__mocks__/saved_search'; +import { savedSearchMock } from '../../../__mocks__/saved_search'; import { discoverServiceMock } from '../../../__mocks__/services'; import { IKibanaSearchResponse } from '@kbn/data-plugin/public'; import { SearchResponse } from '@elastic/elasticsearch/lib/api/types'; import { FetchDeps } from './fetch_all'; -import { fetchTotalHits } from './fetch_total_hits'; import type { EsHitRecord } from '../../../types'; import { buildDataTableRecord } from '../../../utils/build_data_record'; import { dataViewMock } from '../../../__mocks__/data_view'; @@ -47,21 +46,4 @@ describe('test fetchDocuments', () => { new Error('Oh noes!') ); }); - - test('fetch$ is called with execution context containing savedSearch id', async () => { - const fetch$Mock = jest.fn().mockReturnValue( - of({ - rawResponse: { hits: { hits: [] } }, - } as unknown as IKibanaSearchResponse) - ); - - savedSearchMockWithTimeField.searchSource.fetch$ = fetch$Mock; - - await fetchTotalHits(savedSearchMockWithTimeField.searchSource, getDeps()); - expect(fetch$Mock.mock.calls[0][0].executionContext).toMatchInlineSnapshot(` - Object { - "description": "fetch total hits", - } - `); - }); }); diff --git a/src/plugins/discover/public/application/main/utils/fetch_total_hits.test.ts b/src/plugins/discover/public/application/main/utils/fetch_total_hits.test.ts deleted file mode 100644 index f2851a57e7365..0000000000000 --- a/src/plugins/discover/public/application/main/utils/fetch_total_hits.test.ts +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ -import { throwError as throwErrorRx, of } from 'rxjs'; -import { RequestAdapter } from '@kbn/inspector-plugin/common'; -import { savedSearchMock, savedSearchMockWithTimeField } from '../../../__mocks__/saved_search'; -import { fetchTotalHits } from './fetch_total_hits'; -import { discoverServiceMock } from '../../../__mocks__/services'; -import { SearchResponse } from '@elastic/elasticsearch/lib/api/types'; -import { IKibanaSearchResponse } from '@kbn/data-plugin/public'; -import { FetchDeps } from './fetch_all'; - -const getDeps = () => - ({ - abortController: new AbortController(), - inspectorAdapters: { requests: new RequestAdapter() }, - searchSessionId: '123', - data: discoverServiceMock.data, - savedSearch: savedSearchMock, - } as FetchDeps); - -describe('test fetchTotalHits', () => { - test('resolves returned promise with hit count', async () => { - savedSearchMock.searchSource.fetch$ = () => - of({ rawResponse: { hits: { total: 45 } } } as IKibanaSearchResponse>); - - await expect(fetchTotalHits(savedSearchMock.searchSource, getDeps())).resolves.toBe(45); - }); - - test('rejects in case of an error', async () => { - savedSearchMock.searchSource.fetch$ = () => throwErrorRx(() => new Error('Oh noes!')); - - await expect(fetchTotalHits(savedSearchMock.searchSource, getDeps())).rejects.toEqual( - new Error('Oh noes!') - ); - }); - test('fetch$ is called with execution context containing savedSearch id', async () => { - const fetch$Mock = jest - .fn() - .mockReturnValue( - of({ rawResponse: { hits: { total: 45 } } } as IKibanaSearchResponse) - ); - - savedSearchMockWithTimeField.searchSource.fetch$ = fetch$Mock; - - await fetchTotalHits(savedSearchMockWithTimeField.searchSource, getDeps()); - expect(fetch$Mock.mock.calls[0][0].executionContext).toMatchInlineSnapshot(` - Object { - "description": "fetch total hits", - } - `); - }); -}); diff --git a/src/plugins/discover/public/application/main/utils/fetch_total_hits.ts b/src/plugins/discover/public/application/main/utils/fetch_total_hits.ts deleted file mode 100644 index 16bd138e2caf5..0000000000000 --- a/src/plugins/discover/public/application/main/utils/fetch_total_hits.ts +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { i18n } from '@kbn/i18n'; -import { filter, map } from 'rxjs/operators'; -import { lastValueFrom } from 'rxjs'; -import { isCompleteResponse, ISearchSource } from '@kbn/data-plugin/public'; -import { DataViewType } from '@kbn/data-views-plugin/public'; -import { FetchDeps } from './fetch_all'; - -export function fetchTotalHits( - searchSource: ISearchSource, - { abortController, inspectorAdapters, searchSessionId, savedSearch }: FetchDeps -) { - searchSource.setField('trackTotalHits', true); - searchSource.setField('size', 0); - searchSource.removeField('sort'); - searchSource.removeField('fields'); - searchSource.removeField('aggs'); - if (searchSource.getField('index')?.type === DataViewType.ROLLUP) { - // We treat that data view as "normal" even if it was a rollup data view, - // since the rollup endpoint does not support querying individual documents, but we - // can get them from the regular _search API that will be used if the data view - // not a rollup data view. - searchSource.setOverwriteDataViewType(undefined); - } - - const executionContext = { - description: 'fetch total hits', - }; - - const fetch$ = searchSource - .fetch$({ - inspector: { - adapter: inspectorAdapters.requests, - title: i18n.translate('discover.inspectorRequestDataTitleTotalHits', { - defaultMessage: 'Total hits', - }), - description: i18n.translate('discover.inspectorRequestDescriptionTotalHits', { - defaultMessage: 'This request queries Elasticsearch to fetch the total hits.', - }), - }, - abortSignal: abortController.signal, - sessionId: searchSessionId, - executionContext, - }) - .pipe( - filter((res) => isCompleteResponse(res)), - map((res) => res.rawResponse.hits.total as number) - ); - - return lastValueFrom(fetch$); -} diff --git a/src/plugins/discover/public/application/main/utils/get_state_defaults.test.ts b/src/plugins/discover/public/application/main/utils/get_state_defaults.test.ts index 1d5cf07446d60..aed900821c747 100644 --- a/src/plugins/discover/public/application/main/utils/get_state_defaults.test.ts +++ b/src/plugins/discover/public/application/main/utils/get_state_defaults.test.ts @@ -22,6 +22,7 @@ describe('getStateDefaults', () => { }); expect(actual).toMatchInlineSnapshot(` Object { + "breakdownField": undefined, "columns": Array [ "default_column", ], @@ -55,6 +56,7 @@ describe('getStateDefaults', () => { }); expect(actual).toMatchInlineSnapshot(` Object { + "breakdownField": undefined, "columns": Array [ "default_column", ], diff --git a/src/plugins/discover/public/application/main/utils/get_state_defaults.ts b/src/plugins/discover/public/application/main/utils/get_state_defaults.ts index b8b3c3579f343..f32af6ec5f23b 100644 --- a/src/plugins/discover/public/application/main/utils/get_state_defaults.ts +++ b/src/plugins/discover/public/application/main/utils/get_state_defaults.ts @@ -70,6 +70,7 @@ export function getStateDefaults({ rowHeight: undefined, rowsPerPage: undefined, grid: undefined, + breakdownField: undefined, }; if (savedSearch.grid) { defaultState.grid = savedSearch.grid; @@ -90,5 +91,9 @@ export function getStateDefaults({ defaultState.rowsPerPage = savedSearch.rowsPerPage; } + if (savedSearch.breakdownField) { + defaultState.breakdownField = savedSearch.breakdownField; + } + return defaultState; } diff --git a/src/plugins/discover/public/application/main/utils/persist_saved_search.ts b/src/plugins/discover/public/application/main/utils/persist_saved_search.ts index 73859e46eaf24..8162f3650b8b0 100644 --- a/src/plugins/discover/public/application/main/utils/persist_saved_search.ts +++ b/src/plugins/discover/public/application/main/utils/persist_saved_search.ts @@ -56,6 +56,12 @@ export async function persistSavedSearch( savedSearch.viewMode = state.viewMode; } + if (typeof state.breakdownField !== 'undefined') { + savedSearch.breakdownField = state.breakdownField; + } else if (savedSearch.breakdownField) { + savedSearch.breakdownField = ''; + } + if (state.hideAggregatedPreview) { savedSearch.hideAggregatedPreview = state.hideAggregatedPreview; } diff --git a/src/plugins/discover/public/build_services.ts b/src/plugins/discover/public/build_services.ts index 4c25f466b0fdd..27f5d59b07e10 100644 --- a/src/plugins/discover/public/build_services.ts +++ b/src/plugins/discover/public/build_services.ts @@ -46,6 +46,7 @@ import type { TriggersAndActionsUIPublicPluginStart } from '@kbn/triggers-action import type { SavedObjectsTaggingApi } from '@kbn/saved-objects-tagging-oss-plugin/public'; import type { SavedObjectsManagementPluginStart } from '@kbn/saved-objects-management-plugin/public'; import type { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/public'; +import type { LensPublicStart } from '@kbn/lens-plugin/public'; import { DiscoverAppLocator } from './locator'; import { getHistory } from './kibana_services'; import { DiscoverStartPlugins } from './plugin'; @@ -97,6 +98,7 @@ export interface DiscoverServices { savedObjectsManagement: SavedObjectsManagementPluginStart; savedObjectsTagging?: SavedObjectsTaggingApi; unifiedSearch: UnifiedSearchPublicPluginStart; + lens: LensPublicStart; } export const buildServices = memoize(function ( @@ -150,5 +152,6 @@ export const buildServices = memoize(function ( savedObjectsTagging: plugins.savedObjectsTaggingOss?.getTaggingApi(), savedObjectsManagement: plugins.savedObjectsManagement, unifiedSearch: plugins.unifiedSearch, + lens: plugins.lens, }; }); diff --git a/src/plugins/discover/public/components/discover_tour/discover_tour_anchors.tsx b/src/plugins/discover/public/components/discover_tour/discover_tour_anchors.tsx index 030876291aeea..2344acf3e60d9 100644 --- a/src/plugins/discover/public/components/discover_tour/discover_tour_anchors.tsx +++ b/src/plugins/discover/public/components/discover_tour/discover_tour_anchors.tsx @@ -14,7 +14,7 @@ export const DISCOVER_TOUR_STEP_ANCHOR_IDS = { }; export const DISCOVER_TOUR_STEP_ANCHORS = { - addFields: `#${DISCOVER_TOUR_STEP_ANCHOR_IDS.addFields}`, + addFields: `[data-test-subj="fieldListGroupedAvailableFields-count"], #${DISCOVER_TOUR_STEP_ANCHOR_IDS.addFields}`, reorderColumns: '[data-test-subj="dataGridColumnSelectorButton"]', sort: '[data-test-subj="dataGridColumnSortingButton"]', changeRowHeight: '[data-test-subj="dataGridDisplaySelectorButton"]', diff --git a/src/plugins/discover/public/locator.ts b/src/plugins/discover/public/locator.ts index e59c61c98412c..e803433c4d70c 100644 --- a/src/plugins/discover/public/locator.ts +++ b/src/plugins/discover/public/locator.ts @@ -91,6 +91,10 @@ export interface DiscoverAppLocatorParams extends SerializableRecord { * Hide mini distribution/preview charts when in Field Statistics mode */ hideAggregatedPreview?: boolean; + /** + * Breakdown field + */ + breakdownField?: string; } export type DiscoverAppLocator = LocatorPublic; @@ -129,6 +133,7 @@ export class DiscoverAppLocatorDefinition implements LocatorDefinition { } as DataViewField) ).toBe('version'); }); + + it('extracts type for meta fields', () => { + expect( + getTypeForFieldIcon({ + type: 'string', + esTypes: ['_id'], + } as DataViewField) + ).toBe('string'); + }); }); diff --git a/src/plugins/discover/public/utils/get_type_for_field_icon.ts b/src/plugins/discover/public/utils/get_type_for_field_icon.ts index 429fdf87991eb..3d05e8365e59c 100644 --- a/src/plugins/discover/public/utils/get_type_for_field_icon.ts +++ b/src/plugins/discover/public/utils/get_type_for_field_icon.ts @@ -13,5 +13,10 @@ import { DataViewField } from '@kbn/data-views-plugin/common'; * * We define custom logic for Discover in order to distinguish between various "string" types. */ -export const getTypeForFieldIcon = (field: DataViewField) => - field.type === 'string' && field.esTypes ? field.esTypes[0] : field.type; +export const getTypeForFieldIcon = (field: DataViewField) => { + const esType = field.esTypes?.[0] || null; + if (esType && ['_id', '_index'].includes(esType)) { + return field.type; + } + return field.type === 'string' && esType ? esType : field.type; +}; diff --git a/src/plugins/event_annotation/common/fetch_event_annotations/request_event_annotations.ts b/src/plugins/event_annotation/common/fetch_event_annotations/request_event_annotations.ts index dbf653ea72f3a..56748495a3456 100644 --- a/src/plugins/event_annotation/common/fetch_event_annotations/request_event_annotations.ts +++ b/src/plugins/event_annotation/common/fetch_event_annotations/request_event_annotations.ts @@ -23,6 +23,7 @@ import { ESCalendarInterval, ESFixedInterval, roundDateToESInterval } from '@ela import { Adapters } from '@kbn/inspector-plugin/common'; import { SerializableRecord } from '@kbn/utility-types'; import { IUiSettingsClient } from '@kbn/core-ui-settings-browser'; +import { i18n } from '@kbn/i18n'; import { handleRequest } from './handle_request'; import { ANNOTATIONS_PER_BUCKET, @@ -134,6 +135,19 @@ export const requestEventAnnotations = ( searchSourceService: searchSource, getNow, executionContext: getExecutionContext(), + title: i18n.translate( + 'eventAnnotation.fetchEventAnnotations.inspector.dataRequest.title', + { + defaultMessage: 'Annotations', + } + ), + description: i18n.translate( + 'eventAnnotation.fetchEventAnnotations.inspector.dataRequest.description', + { + defaultMessage: + 'This request queries Elasticsearch to fetch the data for the annotations.', + } + ), }) ); diff --git a/src/plugins/guided_onboarding/.i18nrc.json b/src/plugins/guided_onboarding/.i18nrc.json index 4be5bba087b2a..f168a83139f97 100755 --- a/src/plugins/guided_onboarding/.i18nrc.json +++ b/src/plugins/guided_onboarding/.i18nrc.json @@ -3,5 +3,5 @@ "paths": { "guidedOnboarding": "." }, - "translations": ["translations/ja-JP.json"] + "translations": [] } diff --git a/src/plugins/guided_onboarding/common/index.ts b/src/plugins/guided_onboarding/common/index.ts new file mode 100644 index 0000000000000..fb3a9c6c23333 --- /dev/null +++ b/src/plugins/guided_onboarding/common/index.ts @@ -0,0 +1,11 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export { PLUGIN_ID, PLUGIN_NAME, API_BASE_PATH } from './constants'; +export { testGuideConfig } from './test_guide_config'; +export type { PluginStatus, PluginState, StepConfig, GuideConfig, GuidesConfig } from './types'; diff --git a/src/plugins/guided_onboarding/public/constants/guides_config/test_guide.ts b/src/plugins/guided_onboarding/common/test_guide_config.ts similarity index 98% rename from src/plugins/guided_onboarding/public/constants/guides_config/test_guide.ts rename to src/plugins/guided_onboarding/common/test_guide_config.ts index 8a0e13cb367ac..9dc252d83e8b0 100644 --- a/src/plugins/guided_onboarding/public/constants/guides_config/test_guide.ts +++ b/src/plugins/guided_onboarding/common/test_guide_config.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import type { GuideConfig } from '../../types'; +import type { GuideConfig } from './types'; export const testGuideConfig: GuideConfig = { title: 'Test guide for development', diff --git a/src/plugins/guided_onboarding/common/types.ts b/src/plugins/guided_onboarding/common/types.ts index f7f077c0d2b82..667390aa342fb 100644 --- a/src/plugins/guided_onboarding/common/types.ts +++ b/src/plugins/guided_onboarding/common/types.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { GuideState } from '@kbn/guided-onboarding'; +import type { GuideId, GuideState, GuideStepIds, StepStatus } from '@kbn/guided-onboarding'; /** * Guided onboarding overall status: @@ -31,3 +31,42 @@ export interface PluginState { isActivePeriod: boolean; activeGuide?: GuideState; } + +export interface StepConfig { + id: GuideStepIds; + title: string; + // description is displayed as a single paragraph, can be combined with description list + description?: string; + // description list is displayed as an unordered list, can be combined with description + descriptionList?: Array; + location?: { + appID: string; + path: string; + }; + status?: StepStatus; + integration?: string; + manualCompletion?: { + title: string; + description: string; + readyToCompleteOnNavigation?: boolean; + }; +} + +export interface GuideConfig { + title: string; + description: string; + guideName: string; + docs?: { + text: string; + url: string; + }; + completedGuideRedirectLocation?: { + appID: string; + path: string; + }; + steps: StepConfig[]; +} + +export type GuidesConfig = { + [key in GuideId]: GuideConfig; +}; diff --git a/src/plugins/guided_onboarding/public/components/guide_button.tsx b/src/plugins/guided_onboarding/public/components/guide_button.tsx index c8e17e749b125..7bff376c5af4b 100644 --- a/src/plugins/guided_onboarding/public/components/guide_button.tsx +++ b/src/plugins/guided_onboarding/public/components/guide_button.tsx @@ -11,12 +11,12 @@ import { EuiButton } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import type { GuideState } from '@kbn/guided-onboarding'; -import type { PluginState } from '../../common/types'; -import { getStepConfig } from '../services/helpers'; +import type { GuideConfig, PluginState } from '../../common'; import { GuideButtonPopover } from './guide_button_popover'; interface GuideButtonProps { pluginState: PluginState | undefined; + guideConfig: GuideConfig | undefined; toggleGuidePanel: () => void; isGuidePanelOpen: boolean; navigateToLandingPage: () => void; @@ -42,6 +42,7 @@ const getStepNumber = (state: GuideState): number | undefined => { export const GuideButton = ({ pluginState, + guideConfig, toggleGuidePanel, isGuidePanelOpen, navigateToLandingPage, @@ -101,7 +102,7 @@ export const GuideButton = ({ ); if (stepReadyToComplete) { - const stepConfig = getStepConfig(pluginState.activeGuide.guideId, stepReadyToComplete.id); + const stepConfig = guideConfig?.steps.find((step) => step.id === stepReadyToComplete.id); // check if the stepConfig has manualCompletion info if (stepConfig && stepConfig.manualCompletion) { return ( diff --git a/src/plugins/guided_onboarding/public/components/guide_panel.test.tsx b/src/plugins/guided_onboarding/public/components/guide_panel.test.tsx index a552444f8b0f1..cff22fd433bdc 100644 --- a/src/plugins/guided_onboarding/public/components/guide_panel.test.tsx +++ b/src/plugins/guided_onboarding/public/components/guide_panel.test.tsx @@ -15,11 +15,12 @@ import { httpServiceMock } from '@kbn/core/public/mocks'; import type { HttpSetup } from '@kbn/core/public'; import { registerTestBed, TestBed } from '@kbn/test-jest-helpers'; -import type { PluginState } from '../../common/types'; -import { guidesConfig } from '../constants/guides_config'; +import type { PluginState } from '../../common'; +import { API_BASE_PATH, testGuideConfig } from '../../common'; import { apiService } from '../services/api'; import type { GuidedOnboardingApi } from '../types'; import { + testGuide, testGuideStep1ActiveState, testGuideStep1InProgressState, testGuideStep2InProgressState, @@ -33,13 +34,21 @@ import { GuidePanel } from './guide_panel'; const applicationMock = applicationServiceMock.createStartContract(); const notificationsMock = notificationServiceMock.createStartContract(); +const mockGetResponse = (path: string, pluginState: PluginState) => { + if (path === `${API_BASE_PATH}/configs/${testGuide}`) { + return Promise.resolve({ + config: testGuideConfig, + }); + } + return Promise.resolve({ pluginState }); +}; const setupComponentWithPluginStateMock = async ( httpClient: jest.Mocked, pluginState: PluginState ) => { - httpClient.get.mockResolvedValue({ - pluginState, - }); + httpClient.get.mockImplementation((path) => + mockGetResponse(path as unknown as string, pluginState) + ); apiService.setup(httpClient, true); return await setupGuidePanelComponent(apiService); }; @@ -232,7 +241,7 @@ describe('Guided setup', () => { expect(exists('guidePanel')).toBe(true); expect(exists('guideProgress')).toBe(false); - expect(find('guidePanelStep').length).toEqual(guidesConfig.testGuide.steps.length); + expect(find('guidePanelStep').length).toEqual(testGuideConfig.steps.length); }); describe('Guide completion', () => { @@ -423,7 +432,7 @@ describe('Guided setup', () => { expect( find('guidePanelStepDescription') .last() - .containsMatchingElement(

    {guidesConfig.testGuide.steps[2].description}

    ) + .containsMatchingElement(

    {testGuideConfig.steps[2].description}

    ) ).toBe(true); }); @@ -441,7 +450,7 @@ describe('Guided setup', () => { .first() .containsMatchingElement(
      - {guidesConfig.testGuide.steps[0].descriptionList?.map((description, i) => ( + {testGuideConfig.steps[0].descriptionList?.map((description, i) => (
    • {description}
    • ))}
    diff --git a/src/plugins/guided_onboarding/public/components/guide_panel.tsx b/src/plugins/guided_onboarding/public/components/guide_panel.tsx index 69cf5c06f2115..b3afe28e2becc 100644 --- a/src/plugins/guided_onboarding/public/components/guide_panel.tsx +++ b/src/plugins/guided_onboarding/public/components/guide_panel.tsx @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import React, { useState, useEffect } from 'react'; +import React, { useState, useEffect, useCallback } from 'react'; import { EuiFlyout, EuiFlyoutBody, @@ -32,10 +32,9 @@ import { ApplicationStart, NotificationsStart } from '@kbn/core/public'; import type { GuideState, GuideStep as GuideStepStatus } from '@kbn/guided-onboarding'; import { GuideId } from '@kbn/guided-onboarding'; -import type { GuideConfig, GuidedOnboardingApi, StepConfig } from '../types'; +import type { GuidedOnboardingApi } from '../types'; -import type { PluginState } from '../../common/types'; -import { getGuideConfig } from '../services/helpers'; +import type { GuideConfig, PluginState, StepConfig } from '../../common'; import { GuideStep } from './guide_panel_step'; import { QuitGuideModal } from './quit_guide_modal'; @@ -79,6 +78,7 @@ export const GuidePanel = ({ api, application, notifications }: GuidePanelProps) const [isGuideOpen, setIsGuideOpen] = useState(false); const [isQuitGuideModalOpen, setIsQuitGuideModalOpen] = useState(false); const [pluginState, setPluginState] = useState(undefined); + const [guideConfig, setGuideConfig] = useState(undefined); const styles = getGuidePanelStyles(euiTheme); @@ -170,7 +170,16 @@ export const GuidePanel = ({ api, application, notifications }: GuidePanelProps) return () => subscription.unsubscribe(); }, [api]); - const guideConfig = getGuideConfig(pluginState?.activeGuide?.guideId)!; + const fetchGuideConfig = useCallback(async () => { + if (pluginState?.activeGuide?.guideId) { + const config = await api.getGuideConfig(pluginState.activeGuide.guideId); + if (config) setGuideConfig(config); + } + }, [api, pluginState]); + + useEffect(() => { + fetchGuideConfig(); + }, [fetchGuideConfig]); // TODO handle loading state // https://github.com/elastic/kibana/issues/139799 @@ -184,6 +193,7 @@ export const GuidePanel = ({ api, application, notifications }: GuidePanelProps)
    = { completeGuidedOnboardingForIntegration: jest.fn(), skipGuidedOnboarding: jest.fn(), isGuidePanelOpen$: new BehaviorSubject(false), + getGuideConfig: jest.fn(), }, }; diff --git a/src/plugins/guided_onboarding/public/services/api.mocks.ts b/src/plugins/guided_onboarding/public/services/api.mocks.ts index 19cb489a3fbdb..ed87a28c51c33 100644 --- a/src/plugins/guided_onboarding/public/services/api.mocks.ts +++ b/src/plugins/guided_onboarding/public/services/api.mocks.ts @@ -8,7 +8,7 @@ import type { GuideState, GuideId, GuideStepIds } from '@kbn/guided-onboarding'; -import { PluginState } from '../../common/types'; +import { PluginState } from '../../common'; export const testGuide: GuideId = 'testGuide'; export const testGuideFirstStep: GuideStepIds = 'step1'; @@ -87,7 +87,7 @@ export const testGuideStep2ReadyToCompleteState: GuideState = { status: 'complete', }, { - id: testGuideStep1ActiveState.steps[1].id, + ...testGuideStep1ActiveState.steps[1], status: 'ready_to_complete', }, testGuideStep1ActiveState.steps[2], diff --git a/src/plugins/guided_onboarding/public/services/api.test.ts b/src/plugins/guided_onboarding/public/services/api.test.ts index db995002ddfcb..0f308fc66a250 100644 --- a/src/plugins/guided_onboarding/public/services/api.test.ts +++ b/src/plugins/guided_onboarding/public/services/api.test.ts @@ -11,7 +11,7 @@ import { httpServiceMock } from '@kbn/core/public/mocks'; import type { GuideState } from '@kbn/guided-onboarding'; import { firstValueFrom, Subscription } from 'rxjs'; -import { API_BASE_PATH } from '../../common/constants'; +import { API_BASE_PATH, testGuideConfig } from '../../common'; import { ApiService } from './api'; import { testGuide, @@ -129,9 +129,9 @@ describe('GuidedOnboarding ApiService', () => { describe('activateGuide', () => { it('activates a new guide', async () => { - // update the mock to no active guides - httpClient.get.mockResolvedValue({ - pluginState: mockPluginStateNotStarted, + // mock the get config request + httpClient.get.mockResolvedValueOnce({ + config: testGuideConfig, }); apiService.setup(httpClient, true); @@ -305,9 +305,12 @@ describe('GuidedOnboarding ApiService', () => { }); it(`marks the step as 'ready_to_complete' if it's configured for manual completion`, async () => { - httpClient.get.mockResolvedValue({ + httpClient.get.mockResolvedValueOnce({ pluginState: { ...mockPluginStateInProgress, activeGuide: testGuideStep2InProgressState }, }); + httpClient.get.mockResolvedValueOnce({ + config: testGuideConfig, + }); apiService.setup(httpClient, true); await apiService.completeGuideStep(testGuide, testGuideManualCompletionStep); @@ -329,7 +332,7 @@ describe('GuidedOnboarding ApiService', () => { }); it('marks the guide as "ready_to_complete" if the current step is the last step in the guide and configured for manual completion', async () => { - httpClient.get.mockResolvedValue({ + httpClient.get.mockResolvedValueOnce({ pluginState: { ...mockPluginStateInProgress, activeGuide: { @@ -341,6 +344,9 @@ describe('GuidedOnboarding ApiService', () => { }, }, }); + httpClient.get.mockResolvedValueOnce({ + config: testGuideConfig, + }); apiService.setup(httpClient, true); await apiService.completeGuideStep(testGuide, testGuideLastStep); @@ -402,9 +408,12 @@ describe('GuidedOnboarding ApiService', () => { describe('isGuidedOnboardingActiveForIntegration$', () => { it('returns true if the integration is part of the active step', (done) => { - httpClient.get.mockResolvedValue({ + httpClient.get.mockResolvedValueOnce({ pluginState: { ...mockPluginStateInProgress, activeGuide: testGuideStep1InProgressState }, }); + httpClient.get.mockResolvedValueOnce({ + config: testGuideConfig, + }); apiService.setup(httpClient, true); subscription = apiService .isGuidedOnboardingActiveForIntegration$(testIntegration) @@ -449,9 +458,12 @@ describe('GuidedOnboarding ApiService', () => { describe('completeGuidedOnboardingForIntegration', () => { it(`completes the step if it's active for the integration`, async () => { - httpClient.get.mockResolvedValue({ + httpClient.get.mockResolvedValueOnce({ pluginState: { ...mockPluginStateInProgress, activeGuide: testGuideStep1InProgressState }, }); + httpClient.get.mockResolvedValueOnce({ + config: testGuideConfig, + }); apiService.setup(httpClient, true); await apiService.completeGuidedOnboardingForIntegration(testIntegration); @@ -482,6 +494,26 @@ describe('GuidedOnboarding ApiService', () => { }); }); + describe('skipGuidedOnboarding', () => { + it(`sends a request to the put state API`, async () => { + await apiService.skipGuidedOnboarding(); + expect(httpClient.put).toHaveBeenCalledTimes(1); + // this assertion depends on the guides config + expect(httpClient.put).toHaveBeenCalledWith(`${API_BASE_PATH}/state`, { + body: JSON.stringify({ status: 'skipped' }), + }); + }); + }); + + describe('getGuideConfig', () => { + it('sends a request to the get config API', async () => { + apiService.setup(httpClient, true); + await apiService.getGuideConfig(testGuide); + expect(httpClient.get).toHaveBeenCalledTimes(1); + expect(httpClient.get).toHaveBeenCalledWith(`${API_BASE_PATH}/configs/${testGuide}`); + }); + }); + describe('no API requests are sent on self-managed deployments', () => { beforeEach(() => { apiService.setup(httpClient, false); @@ -501,5 +533,10 @@ describe('GuidedOnboarding ApiService', () => { await apiService.updatePluginState({}, false); expect(httpClient.put).not.toHaveBeenCalled(); }); + + it('getGuideConfig', async () => { + await apiService.getGuideConfig(testGuide); + expect(httpClient.get).not.toHaveBeenCalled(); + }); }); }); diff --git a/src/plugins/guided_onboarding/public/services/api.ts b/src/plugins/guided_onboarding/public/services/api.ts index 3452e282b1680..4bf9cd5b55cc6 100644 --- a/src/plugins/guided_onboarding/public/services/api.ts +++ b/src/plugins/guided_onboarding/public/services/api.ts @@ -7,23 +7,31 @@ */ import { HttpSetup } from '@kbn/core/public'; -import { BehaviorSubject, map, Observable, firstValueFrom, concat, of } from 'rxjs'; +import { + BehaviorSubject, + map, + Observable, + firstValueFrom, + concatMap, + of, + concat, + from, +} from 'rxjs'; import type { GuideState, GuideId, GuideStep, GuideStepIds } from '@kbn/guided-onboarding'; -import { API_BASE_PATH } from '../../common/constants'; -import { PluginState, PluginStatus } from '../../common/types'; +import { API_BASE_PATH } from '../../common'; +import type { PluginState, PluginStatus, GuideConfig } from '../../common'; import { GuidedOnboardingApi } from '../types'; import { - getGuideConfig, getInProgressStepId, - getStepConfig, - getUpdatedSteps, - getGuideStatusOnStepCompletion, - isIntegrationInGuideStep, + getCompletedSteps, isStepInProgress, isStepReadyToComplete, isGuideActive, + getStepConfig, + isLastStep, } from './helpers'; +import { ConfigService } from './config_service'; export class ApiService implements GuidedOnboardingApi { private isCloudEnabled: boolean | undefined; @@ -31,12 +39,14 @@ export class ApiService implements GuidedOnboardingApi { private pluginState$!: BehaviorSubject; private isPluginStateLoading: boolean | undefined; public isGuidePanelOpen$: BehaviorSubject = new BehaviorSubject(false); + private configService = new ConfigService(); public setup(httpClient: HttpSetup, isCloudEnabled: boolean) { this.isCloudEnabled = isCloudEnabled; this.client = httpClient; this.pluginState$ = new BehaviorSubject(undefined); this.isGuidePanelOpen$ = new BehaviorSubject(false); + this.configService.setup(httpClient); } private createGetPluginStateObservable(): Observable { @@ -175,7 +185,7 @@ export class ApiService implements GuidedOnboardingApi { } // If this is the 1st-time attempt, we need to create the default state - const guideConfig = getGuideConfig(guideId); + const guideConfig = await this.configService.getGuideConfig(guideId); if (guideConfig) { const updatedSteps: GuideStep[] = guideConfig.steps.map((step, stepIndex) => { @@ -242,8 +252,7 @@ export class ApiService implements GuidedOnboardingApi { // All steps should be complete at this point // However, we do a final check here as a safeguard - const allStepsComplete = - Boolean(activeGuide!.steps.find((step) => step.status !== 'complete')) === false; + const allStepsComplete = Boolean(activeGuide!.steps.find((step) => step.status === 'complete')); if (allStepsComplete) { const updatedGuide: GuideState = { @@ -335,11 +344,13 @@ export class ApiService implements GuidedOnboardingApi { const isCurrentStepInProgress = isStepInProgress(activeGuide, guideId, stepId); const isCurrentStepReadyToComplete = isStepReadyToComplete(activeGuide, guideId, stepId); - const stepConfig = getStepConfig(activeGuide!.guideId, stepId); + const guideConfig = await this.configService.getGuideConfig(guideId); + const stepConfig = getStepConfig(guideConfig, activeGuide!.guideId, stepId); const isManualCompletion = stepConfig ? !!stepConfig.manualCompletion : false; + const isLastStepInGuide = isLastStep(guideConfig, guideId, stepId); if (isCurrentStepInProgress || isCurrentStepReadyToComplete) { - const updatedSteps = getUpdatedSteps( + const updatedSteps = getCompletedSteps( activeGuide!, stepId, // if current step is in progress and configured for manual completion, @@ -347,10 +358,15 @@ export class ApiService implements GuidedOnboardingApi { isManualCompletion && isCurrentStepInProgress ); + const status = await this.configService.getGuideStatusOnStepCompletion({ + isLastStepInGuide, + isManualCompletion, + isStepReadyToComplete: isCurrentStepReadyToComplete, + }); const currentGuide: GuideState = { guideId, isActive: true, - status: getGuideStatusOnStepCompletion(activeGuide, guideId, stepId), + status, steps: updatedSteps, }; @@ -377,7 +393,9 @@ export class ApiService implements GuidedOnboardingApi { */ public isGuidedOnboardingActiveForIntegration$(integration?: string): Observable { return this.fetchPluginState$().pipe( - map((state) => isIntegrationInGuideStep(state?.activeGuide, integration)) + concatMap((state) => + from(this.configService.isIntegrationInGuideStep(state?.activeGuide, integration)) + ) ); } @@ -396,7 +414,10 @@ export class ApiService implements GuidedOnboardingApi { const { activeGuide } = pluginState!; const inProgressStepId = getInProgressStepId(activeGuide!); if (!inProgressStepId) return undefined; - const isIntegrationStepActive = isIntegrationInGuideStep(activeGuide!, integration); + const isIntegrationStepActive = await this.configService.isIntegrationInGuideStep( + activeGuide!, + integration + ); if (isIntegrationStepActive) { return await this.completeGuideStep(activeGuide!.guideId, inProgressStepId); } @@ -410,6 +431,20 @@ export class ApiService implements GuidedOnboardingApi { public async skipGuidedOnboarding(): Promise<{ pluginState: PluginState } | undefined> { return await this.updatePluginState({ status: 'skipped' }, false); } + + /** + * Gets the config for the guide. + * @return {Promise} a promise with the guide config or undefined if the config is not found + */ + public async getGuideConfig(guideId: GuideId): Promise { + if (!this.isCloudEnabled) { + return undefined; + } + if (!this.client) { + throw new Error('ApiService has not be initialized.'); + } + return await this.configService.getGuideConfig(guideId); + } } export const apiService = new ApiService(); diff --git a/src/plugins/guided_onboarding/public/services/config_service.test.ts b/src/plugins/guided_onboarding/public/services/config_service.test.ts new file mode 100644 index 0000000000000..11132059af7fa --- /dev/null +++ b/src/plugins/guided_onboarding/public/services/config_service.test.ts @@ -0,0 +1,119 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { HttpSetup } from '@kbn/core-http-browser'; +import { httpServiceMock } from '@kbn/core-http-browser-mocks'; +import { API_BASE_PATH, testGuideConfig } from '../../common'; +import { + testGuide, + testGuideNotActiveState, + testGuideStep1InProgressState, + testGuideStep2InProgressState, + testIntegration, + wrongIntegration, +} from './api.mocks'; + +import { ConfigService } from './config_service'; + +describe('GuidedOnboarding ConfigService', () => { + let configService: ConfigService; + let httpClient: jest.Mocked; + + beforeEach(() => { + httpClient = httpServiceMock.createStartContract({ basePath: '/base/path' }); + httpClient.get.mockResolvedValue({ + config: testGuideConfig, + }); + configService = new ConfigService(); + configService.setup(httpClient); + }); + describe('getGuideConfig', () => { + it('sends only one request to the get configs API', async () => { + await configService.getGuideConfig(testGuide); + await configService.getGuideConfig(testGuide); + expect(httpClient.get).toHaveBeenCalledTimes(1); + expect(httpClient.get).toHaveBeenCalledWith(`${API_BASE_PATH}/configs/${testGuide}`); + }); + + it('returns undefined if the config is not found', async () => { + httpClient.get.mockRejectedValueOnce(new Error('Not found')); + configService.setup(httpClient); + const config = await configService.getGuideConfig(testGuide); + expect(config).toBeUndefined(); + }); + + it('returns the config for the guide', async () => { + const config = await configService.getGuideConfig(testGuide); + expect(config).toHaveProperty('title'); + }); + }); + + describe('getGuideStatusOnStepCompletion', () => { + it('returns in_progress when completing not the last step', async () => { + const status = await configService.getGuideStatusOnStepCompletion({ + isLastStepInGuide: false, + isManualCompletion: true, + isStepReadyToComplete: true, + }); + expect(status).toBe('in_progress'); + }); + + it('when completing the last step that is configured for manual completion, returns in_progress if the step is in progress', async () => { + const status = await configService.getGuideStatusOnStepCompletion({ + isLastStepInGuide: true, + isManualCompletion: true, + isStepReadyToComplete: false, + }); + expect(status).toBe('in_progress'); + }); + + it('when completing the last step that is configured for manual completion, returns ready_to_complete if the step is ready_to_complete', async () => { + const status = await configService.getGuideStatusOnStepCompletion({ + isLastStepInGuide: true, + isManualCompletion: true, + isStepReadyToComplete: true, + }); + expect(status).toBe('ready_to_complete'); + }); + }); + + describe('isIntegrationInGuideStep', () => { + it('return true if the integration is defined in the guide step config', async () => { + const result = await configService.isIntegrationInGuideStep( + testGuideStep1InProgressState, + testIntegration + ); + expect(result).toBe(true); + }); + it('returns false if a different integration is defined in the guide step', async () => { + const result = await configService.isIntegrationInGuideStep( + testGuideStep1InProgressState, + wrongIntegration + ); + expect(result).toBe(false); + }); + it('returns false if no integration is defined in the guide step', async () => { + const result = await configService.isIntegrationInGuideStep( + testGuideStep2InProgressState, + testIntegration + ); + expect(result).toBe(false); + }); + it('returns false if no guide is active', async () => { + const result = await configService.isIntegrationInGuideStep( + testGuideNotActiveState, + testIntegration + ); + expect(result).toBe(false); + }); + it('returns false if no integration passed', async () => { + const result = await configService.isIntegrationInGuideStep(testGuideStep1InProgressState); + expect(result).toBe(false); + }); + }); +}); diff --git a/src/plugins/guided_onboarding/public/services/config_service.ts b/src/plugins/guided_onboarding/public/services/config_service.ts new file mode 100644 index 0000000000000..b0bea7deb47bc --- /dev/null +++ b/src/plugins/guided_onboarding/public/services/config_service.ts @@ -0,0 +1,86 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { HttpSetup } from '@kbn/core-http-browser'; +import { GuideId, GuideState, GuideStatus } from '@kbn/guided-onboarding'; +import type { GuideConfig, GuidesConfig } from '../../common'; +import { API_BASE_PATH } from '../../common'; +import { findGuideConfigByGuideId, getInProgressStepConfig } from './helpers'; + +type ConfigInitialization = { + [key in GuideId]: boolean | undefined; +}; +export class ConfigService { + private client: HttpSetup | undefined; + private configs: GuidesConfig | undefined; + private isConfigInitialized: ConfigInitialization | undefined; + + setup(httpClient: HttpSetup) { + this.client = httpClient; + this.configs = {} as GuidesConfig; + this.isConfigInitialized = {} as ConfigInitialization; + } + + public async getGuideConfig(guideId: GuideId): Promise { + if (!this.client) { + throw new Error('ConfigService has not be initialized.'); + } + // if not initialized yet, get the config from the backend + if (!this.isConfigInitialized || !this.isConfigInitialized[guideId]) { + try { + const { config } = await this.client.get<{ config: GuideConfig }>( + `${API_BASE_PATH}/configs/${guideId}` + ); + if (!this.isConfigInitialized) this.isConfigInitialized = {} as ConfigInitialization; + this.isConfigInitialized[guideId] = true; + if (!this.configs) this.configs = {} as GuidesConfig; + this.configs[guideId] = config; + } catch (e) { + // if there is an error, set the isInitialized property to avoid multiple requests + if (!this.isConfigInitialized) this.isConfigInitialized = {} as ConfigInitialization; + this.isConfigInitialized[guideId] = true; + } + } + // get the config from the configs property + return findGuideConfigByGuideId(this.configs, guideId); + } + + public async getGuideStatusOnStepCompletion({ + isLastStepInGuide, + isManualCompletion, + isStepReadyToComplete, + }: { + isLastStepInGuide: boolean; + isManualCompletion: boolean; + isStepReadyToComplete: boolean; + }): Promise { + // We want to set the guide status to 'ready_to_complete' if the current step is the last step in the guide + // and the step is not configured for manual completion + // or if the current step is configured for manual completion and the last step is ready to complete + if ( + (isLastStepInGuide && !isManualCompletion) || + (isLastStepInGuide && isManualCompletion && isStepReadyToComplete) + ) { + return 'ready_to_complete'; + } + + // Otherwise the guide is still in progress + return 'in_progress'; + } + + public async isIntegrationInGuideStep( + guideState?: GuideState, + integration?: string + ): Promise { + if (!guideState || !guideState.isActive) return false; + + const guideConfig = await this.getGuideConfig(guideState.guideId); + const stepConfig = getInProgressStepConfig(guideConfig, guideState); + return stepConfig ? stepConfig.integration === integration : false; + } +} diff --git a/src/plugins/guided_onboarding/public/services/helpers.test.ts b/src/plugins/guided_onboarding/public/services/helpers.test.ts index 82720c4f9d223..f1cf0c7c0c561 100644 --- a/src/plugins/guided_onboarding/public/services/helpers.test.ts +++ b/src/plugins/guided_onboarding/public/services/helpers.test.ts @@ -6,51 +6,219 @@ * Side Public License, v 1. */ -import { isIntegrationInGuideStep, isLastStep } from './helpers'; +import { testGuideConfig } from '../../common'; +import type { GuidesConfig } from '../../common'; import { + findGuideConfigByGuideId, + getCompletedSteps, + getInProgressStepConfig, + getInProgressStepId, + getStepConfig, + isGuideActive, + isLastStep, + isStepInProgress, + isStepReadyToComplete, +} from './helpers'; +import { + mockPluginStateInProgress, + mockPluginStateNotStarted, testGuide, testGuideFirstStep, testGuideLastStep, - testGuideNotActiveState, + testGuideManualCompletionStep, + testGuideStep1ActiveState, testGuideStep1InProgressState, testGuideStep2InProgressState, - testIntegration, - wrongIntegration, + testGuideStep2ReadyToCompleteState, } from './api.mocks'; describe('GuidedOnboarding ApiService helpers', () => { - describe('isLastStepActive', () => { + describe('findGuideConfigByGuideId', () => { + it('returns undefined if the config is not found', () => { + const config = findGuideConfigByGuideId( + { testGuide: testGuideConfig } as GuidesConfig, + 'security' + ); + expect(config).toBeUndefined(); + }); + + it('returns the correct config guide', () => { + const config = findGuideConfigByGuideId( + { testGuide: testGuideConfig } as GuidesConfig, + testGuide + ); + expect(config).not.toBeUndefined(); + }); + }); + + describe('getStepConfig', () => { + it('returns undefined if the config is not found', async () => { + const config = getStepConfig(undefined, testGuide, testGuideFirstStep); + expect(config).toBeUndefined(); + }); + + it('returns the config for the step', async () => { + const config = getStepConfig(testGuideConfig, testGuide, testGuideFirstStep); + expect(config).toHaveProperty('title'); + }); + }); + + describe('isLastStep', () => { it('returns true if the passed params are for the last step', () => { - const result = isLastStep(testGuide, testGuideLastStep); + const result = isLastStep(testGuideConfig, testGuide, testGuideLastStep); expect(result).toBe(true); }); it('returns false if the passed params are not for the last step', () => { - const result = isLastStep(testGuide, testGuideFirstStep); + const result = isLastStep(testGuideConfig, testGuide, testGuideFirstStep); expect(result).toBe(false); }); }); - describe('isIntegrationInGuideStep', () => { - it('return true if the integration is defined in the guide step config', () => { - const result = isIntegrationInGuideStep(testGuideStep1InProgressState, testIntegration); - expect(result).toBe(true); + describe('getInProgressStepId', () => { + it('returns undefined if no step is in progress', () => { + const stepId = getInProgressStepId(testGuideStep1ActiveState); + expect(stepId).toBeUndefined(); }); - it('returns false if a different integration is defined in the guide step', () => { - const result = isIntegrationInGuideStep(testGuideStep1InProgressState, wrongIntegration); - expect(result).toBe(false); + it('returns the correct step if that is in progress', () => { + const stepId = getInProgressStepId(testGuideStep1InProgressState); + expect(stepId).toBe('step1'); }); - it('returns false if no integration is defined in the guide step', () => { - const result = isIntegrationInGuideStep(testGuideStep2InProgressState, testIntegration); - expect(result).toBe(false); + }); + + describe('getInProgressStepConfig', () => { + it('returns undefined if no guide config', () => { + const stepConfig = getInProgressStepConfig(undefined, testGuideStep1ActiveState); + expect(stepConfig).toBeUndefined(); }); - it('returns false if no guide is active', () => { - const result = isIntegrationInGuideStep(testGuideNotActiveState, testIntegration); - expect(result).toBe(false); + + it('returns undefined if no step is in progress', () => { + const stepConfig = getInProgressStepConfig(testGuideConfig, testGuideStep1ActiveState); + expect(stepConfig).toBeUndefined(); }); - it('returns false if no integration passed', () => { - const result = isIntegrationInGuideStep(testGuideStep1InProgressState); - expect(result).toBe(false); + + it('returns the correct step config for the step in progress', () => { + const stepConfig = getInProgressStepConfig(testGuideConfig, testGuideStep1InProgressState); + expect(stepConfig).toEqual(testGuideConfig.steps[0]); + }); + }); + + describe('isGuideActive', () => { + it('returns false if plugin state is undefined', () => { + const isActive = isGuideActive(undefined, testGuide); + expect(isActive).toBe(false); + }); + + it('returns true if guideId is undefined and the guide is active', () => { + const isActive = isGuideActive(mockPluginStateInProgress, undefined); + expect(isActive).toBe(true); + }); + + it('returns false if guideId is undefined and the guide is not active', () => { + const isActive = isGuideActive(mockPluginStateNotStarted, undefined); + expect(isActive).toBe(false); + }); + + it('returns false if guide is not in progress', () => { + const isActive = isGuideActive(mockPluginStateInProgress, 'security'); + expect(isActive).toBe(false); + }); + + it('returns true if guide is in progress', () => { + const isActive = isGuideActive(mockPluginStateInProgress, testGuide); + expect(isActive).toBe(true); + }); + }); + + describe('isStepInProgress', () => { + it('returns false if guide state is undefined', () => { + const isInProgress = isStepInProgress(undefined, testGuide, testGuideFirstStep); + expect(isInProgress).toBe(false); + }); + + it('returns false if guide is not active', () => { + const isInProgress = isStepInProgress( + testGuideStep1InProgressState, + 'security', + testGuideFirstStep + ); + expect(isInProgress).toBe(false); + }); + + it('returns false if step is not in progress', () => { + const isInProgress = isStepInProgress( + testGuideStep1InProgressState, + testGuide, + testGuideLastStep + ); + expect(isInProgress).toBe(false); + }); + + it('returns true if step is in progress', () => { + const isInProgress = isStepInProgress( + testGuideStep1InProgressState, + testGuide, + testGuideFirstStep + ); + expect(isInProgress).toBe(true); + }); + }); + + describe('isStepReadyToComplete', () => { + it('returns false if guide state is undefined', () => { + const isReadyToComplete = isStepReadyToComplete(undefined, testGuide, testGuideFirstStep); + expect(isReadyToComplete).toBe(false); + }); + + it('returns false if guide is not active', () => { + const isReadyToComplete = isStepReadyToComplete( + testGuideStep1InProgressState, + 'security', + testGuideFirstStep + ); + expect(isReadyToComplete).toBe(false); + }); + + it('returns false if step is not ready not complete', () => { + const isReadyToComplete = isStepReadyToComplete( + testGuideStep2ReadyToCompleteState, + testGuide, + testGuideLastStep + ); + expect(isReadyToComplete).toBe(false); + }); + + it('returns true if step is ready to complete', () => { + const isInProgress = isStepReadyToComplete( + testGuideStep2ReadyToCompleteState, + testGuide, + testGuideManualCompletionStep + ); + expect(isInProgress).toBe(true); + }); + }); + + describe('getCompletedSteps', () => { + it('completes the step if setToReadyToComplete is false', () => { + const completedSteps = getCompletedSteps( + testGuideStep1InProgressState, + testGuideFirstStep, + false + ); + expect(completedSteps[0].status).toBe('complete'); + // the next step is active + expect(completedSteps[1].status).toBe('active'); + }); + + it('sets the step to ready_to_complete if setToReadyToComplete is true', () => { + const completedSteps = getCompletedSteps( + testGuideStep2InProgressState, + testGuideManualCompletionStep, + true + ); + expect(completedSteps[1].status).toBe('ready_to_complete'); + // the next step is inactive + expect(completedSteps[2].status).toBe('inactive'); }); }); }); diff --git a/src/plugins/guided_onboarding/public/services/helpers.ts b/src/plugins/guided_onboarding/public/services/helpers.ts index 5dfba15f3e2d0..05e8861589da3 100644 --- a/src/plugins/guided_onboarding/public/services/helpers.ts +++ b/src/plugins/guided_onboarding/public/services/helpers.ts @@ -11,35 +11,45 @@ import type { GuideStepIds, GuideState, GuideStep, - GuideStatus, + StepStatus, } from '@kbn/guided-onboarding'; -import { guidesConfig } from '../constants/guides_config'; -import { GuideConfig, StepConfig } from '../types'; -import type { PluginState } from '../../common/types'; +import type { GuidesConfig, PluginState, GuideConfig, StepConfig } from '../../common'; -export const getGuideConfig = (guideId?: GuideId): GuideConfig | undefined => { - if (guideId && Object.keys(guidesConfig).includes(guideId)) { +export const findGuideConfigByGuideId = ( + guidesConfig?: GuidesConfig, + guideId?: GuideId +): GuideConfig | undefined => { + if (guidesConfig && guideId && Object.keys(guidesConfig).includes(guideId)) { return guidesConfig[guideId]; } }; -export const getStepConfig = (guideId: GuideId, stepId: GuideStepIds): StepConfig | undefined => { - const guideConfig = getGuideConfig(guideId); +export const getStepConfig = ( + guideConfig: GuideConfig | undefined, + guideId: GuideId, + stepId: GuideStepIds +): StepConfig | undefined => { return guideConfig?.steps.find((step) => step.id === stepId); }; -const getStepIndex = (guideId: GuideId, stepId: GuideStepIds): number => { - const guide = getGuideConfig(guideId); - if (guide) { - return guide.steps.findIndex((step: StepConfig) => step.id === stepId); +const getStepIndex = ( + guideConfig: GuideConfig | undefined, + guideId: GuideId, + stepId: GuideStepIds +): number => { + if (guideConfig) { + return guideConfig.steps.findIndex((step: StepConfig) => step.id === stepId); } return -1; }; -export const isLastStep = (guideId: GuideId, stepId: GuideStepIds): boolean => { - const guide = getGuideConfig(guideId); - const activeStepIndex = getStepIndex(guideId, stepId); - const stepsNumber = guide?.steps.length || 0; +export const isLastStep = ( + guideConfig: GuideConfig | undefined, + guideId: GuideId, + stepId: GuideStepIds +): boolean => { + const activeStepIndex = getStepIndex(guideConfig, guideId, stepId); + const stepsNumber = guideConfig?.steps.length || 0; if (stepsNumber > 0) { return activeStepIndex === stepsNumber - 1; } @@ -51,26 +61,18 @@ export const getInProgressStepId = (state: GuideState): GuideStepIds | undefined return inProgressStep ? inProgressStep.id : undefined; }; -const getInProgressStepConfig = (state: GuideState): StepConfig | undefined => { +export const getInProgressStepConfig = ( + guideConfig: GuideConfig | undefined, + state: GuideState +): StepConfig | undefined => { const inProgressStepId = getInProgressStepId(state); if (inProgressStepId) { - const config = getGuideConfig(state.guideId); - if (config) { - return config.steps.find((step) => step.id === inProgressStepId); + if (guideConfig) { + return guideConfig.steps.find((step) => step.id === inProgressStepId); } } }; -export const isIntegrationInGuideStep = ( - guideState?: GuideState, - integration?: string -): boolean => { - if (!guideState || !guideState.isActive) return false; - - const stepConfig = getInProgressStepConfig(guideState); - return stepConfig ? stepConfig.integration === integration : false; -}; - export const isGuideActive = (pluginState?: PluginState, guideId?: GuideId): boolean => { // false if pluginState is undefined or plugin state is not in progress // or active guide is undefined @@ -85,16 +87,24 @@ export const isGuideActive = (pluginState?: PluginState, guideId?: GuideId): boo return true; }; -export const isStepInProgress = ( +const isStepStatus = ( guideState: GuideState | undefined, + status: StepStatus, guideId: GuideId, stepId: GuideStepIds ): boolean => { - if (!guideState || !guideState.isActive) return false; + if (!guideState || !guideState.isActive || guideState.guideId !== guideId) return false; // false if the step is not 'in_progress' const selectedStep = guideState.steps.find((step) => step.id === stepId); - return selectedStep ? selectedStep.status === 'in_progress' : false; + return selectedStep ? selectedStep.status === status : false; +}; +export const isStepInProgress = ( + guideState: GuideState | undefined, + guideId: GuideId, + stepId: GuideStepIds +): boolean => { + return isStepStatus(guideState, 'in_progress', guideId, stepId); }; export const isStepReadyToComplete = ( @@ -102,13 +112,10 @@ export const isStepReadyToComplete = ( guideId: GuideId, stepId: GuideStepIds ): boolean => { - if (!guideState || !guideState.isActive) return false; - // false if the step is not 'ready_to_complete' - const selectedStep = guideState!.steps.find((step) => step.id === stepId); - return selectedStep ? selectedStep.status === 'ready_to_complete' : false; + return isStepStatus(guideState, 'ready_to_complete', guideId, stepId); }; -export const getUpdatedSteps = ( +export const getCompletedSteps = ( guideState: GuideState, stepId: GuideStepIds, setToReadyToComplete?: boolean @@ -141,27 +148,3 @@ export const getUpdatedSteps = ( return step; }); }; - -export const getGuideStatusOnStepCompletion = ( - guideState: GuideState | undefined, - guideId: GuideId, - stepId: GuideStepIds -): GuideStatus => { - const stepConfig = getStepConfig(guideId, stepId); - const isManualCompletion = stepConfig?.manualCompletion || false; - const isLastStepInGuide = isLastStep(guideId, stepId); - const isCurrentStepReadyToComplete = isStepReadyToComplete(guideState, guideId, stepId); - - // We want to set the guide status to 'ready_to_complete' if the current step is the last step in the guide - // and the step is not configured for manual completion - // or if the current step is configured for manual completion and the last step is ready to complete - if ( - (isLastStepInGuide && !isManualCompletion) || - (isLastStepInGuide && isManualCompletion && isCurrentStepReadyToComplete) - ) { - return 'ready_to_complete'; - } - - // Otherwise the guide is still in progress - return 'in_progress'; -}; diff --git a/src/plugins/guided_onboarding/public/types.ts b/src/plugins/guided_onboarding/public/types.ts index aeacb79d79a27..034c0337f3cb3 100755 --- a/src/plugins/guided_onboarding/public/types.ts +++ b/src/plugins/guided_onboarding/public/types.ts @@ -6,12 +6,11 @@ * Side Public License, v 1. */ -import React from 'react'; import { Observable } from 'rxjs'; import { HttpSetup } from '@kbn/core/public'; -import type { GuideState, GuideId, GuideStepIds, StepStatus } from '@kbn/guided-onboarding'; +import type { GuideState, GuideId, GuideStepIds } from '@kbn/guided-onboarding'; import type { CloudStart } from '@kbn/cloud-plugin/public'; -import type { PluginStatus, PluginState } from '../common/types'; +import type { PluginStatus, PluginState, GuideConfig } from '../common'; // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface GuidedOnboardingPluginSetup {} @@ -53,42 +52,5 @@ export interface GuidedOnboardingApi { ) => Promise<{ pluginState: PluginState } | undefined>; skipGuidedOnboarding: () => Promise<{ pluginState: PluginState } | undefined>; isGuidePanelOpen$: Observable; + getGuideConfig: (guideId: GuideId) => Promise; } - -export interface StepConfig { - id: GuideStepIds; - title: string; - // description is displayed as a single paragraph, can be combined with description list - description?: string; - // description list is displayed as an unordered list, can be combined with description - descriptionList?: Array; - location?: { - appID: string; - path: string; - }; - status?: StepStatus; - integration?: string; - manualCompletion?: { - title: string; - description: string; - readyToCompleteOnNavigation?: boolean; - }; -} -export interface GuideConfig { - title: string; - description: string; - guideName: string; - docs?: { - text: string; - url: string; - }; - completedGuideRedirectLocation?: { - appID: string; - path: string; - }; - steps: StepConfig[]; -} - -export type GuidesConfig = { - [key in GuideId]: GuideConfig; -}; diff --git a/src/plugins/guided_onboarding/public/constants/guides_config/index.ts b/src/plugins/guided_onboarding/server/helpers/guides_config/index.ts similarity index 86% rename from src/plugins/guided_onboarding/public/constants/guides_config/index.ts rename to src/plugins/guided_onboarding/server/helpers/guides_config/index.ts index e2ab4f7e7747f..a21478ff4ae75 100644 --- a/src/plugins/guided_onboarding/public/constants/guides_config/index.ts +++ b/src/plugins/guided_onboarding/server/helpers/guides_config/index.ts @@ -6,11 +6,11 @@ * Side Public License, v 1. */ -import type { GuidesConfig } from '../../types'; +import type { GuidesConfig } from '../../../common'; +import { testGuideConfig } from '../../../common'; import { securityConfig } from './security'; import { observabilityConfig } from './observability'; import { searchConfig } from './search'; -import { testGuideConfig } from './test_guide'; export const guidesConfig: GuidesConfig = { security: securityConfig, diff --git a/src/plugins/guided_onboarding/public/constants/guides_config/observability.tsx b/src/plugins/guided_onboarding/server/helpers/guides_config/observability.tsx similarity index 83% rename from src/plugins/guided_onboarding/public/constants/guides_config/observability.tsx rename to src/plugins/guided_onboarding/server/helpers/guides_config/observability.tsx index 4dacb14d57c2d..b57d328345119 100644 --- a/src/plugins/guided_onboarding/public/constants/guides_config/observability.tsx +++ b/src/plugins/guided_onboarding/server/helpers/guides_config/observability.tsx @@ -6,13 +6,8 @@ * Side Public License, v 1. */ -import React from 'react'; - import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n-react'; - -import { EuiLink } from '@elastic/eui'; -import type { GuideConfig } from '../../types'; +import type { GuideConfig } from '../../../common'; export const observabilityConfig: GuideConfig = { title: i18n.translate('guidedOnboarding.observabilityGuide.title', { @@ -36,21 +31,10 @@ export const observabilityConfig: GuideConfig = { }), integration: 'kubernetes', descriptionList: [ - - kube-state-metrics - - ), - }} - />, + i18n.translate('guidedOnboarding.observabilityGuide.addDataStep.descriptionList.item1', { + // TODO add the link to the docs, when markdown support is implemented https://github.com/elastic/kibana/issues/146404 + defaultMessage: 'Deploy kube-state-metrics service to your Kubernetes.', + }), i18n.translate('guidedOnboarding.observabilityGuide.addDataStep.descriptionList.item2', { defaultMessage: 'Add the Elastic Kubernetes integration.', }), diff --git a/src/plugins/guided_onboarding/public/constants/guides_config/search.ts b/src/plugins/guided_onboarding/server/helpers/guides_config/search.ts similarity index 98% rename from src/plugins/guided_onboarding/public/constants/guides_config/search.ts rename to src/plugins/guided_onboarding/server/helpers/guides_config/search.ts index 7a28ad6e86925..fdfe9de877944 100644 --- a/src/plugins/guided_onboarding/public/constants/guides_config/search.ts +++ b/src/plugins/guided_onboarding/server/helpers/guides_config/search.ts @@ -7,7 +7,7 @@ */ import { i18n } from '@kbn/i18n'; -import type { GuideConfig } from '../../types'; +import type { GuideConfig } from '../../../common'; export const searchConfig: GuideConfig = { title: i18n.translate('guidedOnboarding.searchGuide.title', { diff --git a/src/plugins/guided_onboarding/public/constants/guides_config/security.ts b/src/plugins/guided_onboarding/server/helpers/guides_config/security.ts similarity index 98% rename from src/plugins/guided_onboarding/public/constants/guides_config/security.ts rename to src/plugins/guided_onboarding/server/helpers/guides_config/security.ts index b7ebd3d6078a0..37b10347eda38 100644 --- a/src/plugins/guided_onboarding/public/constants/guides_config/security.ts +++ b/src/plugins/guided_onboarding/server/helpers/guides_config/security.ts @@ -7,7 +7,7 @@ */ import { i18n } from '@kbn/i18n'; -import type { GuideConfig } from '../../types'; +import type { GuideConfig } from '../../../common'; export const securityConfig: GuideConfig = { title: i18n.translate('guidedOnboarding.securityGuide.title', { diff --git a/src/plugins/guided_onboarding/server/helpers/plugin_state_utils.ts b/src/plugins/guided_onboarding/server/helpers/plugin_state_utils.ts index f24fdf814f83b..ca3d891b147be 100644 --- a/src/plugins/guided_onboarding/server/helpers/plugin_state_utils.ts +++ b/src/plugins/guided_onboarding/server/helpers/plugin_state_utils.ts @@ -8,7 +8,7 @@ import { SavedObjectsClient } from '@kbn/core/server'; import { findActiveGuide } from './guide_state_utils'; -import { PluginState, PluginStatus } from '../../common/types'; +import type { PluginState, PluginStatus } from '../../common'; import { pluginStateSavedObjectsId, pluginStateSavedObjectsType, diff --git a/src/plugins/guided_onboarding/server/routes/config_routes.ts b/src/plugins/guided_onboarding/server/routes/config_routes.ts new file mode 100644 index 0000000000000..d9a82b2635e76 --- /dev/null +++ b/src/plugins/guided_onboarding/server/routes/config_routes.ts @@ -0,0 +1,36 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { IRouter } from '@kbn/core/server'; +import { schema } from '@kbn/config-schema'; +import type { GuideId } from '@kbn/guided-onboarding'; +import { API_BASE_PATH } from '../../common'; +import { guidesConfig } from '../helpers/guides_config'; + +export const registerGetConfigRoute = (router: IRouter) => { + // Fetch the config of the guide + router.get( + { + path: `${API_BASE_PATH}/configs/{guideId}`, + validate: { + params: schema.object({ + guideId: schema.string(), + }), + }, + }, + async (context, request, response) => { + const { guideId } = request.params; + if (guidesConfig && guideId && Object.keys(guidesConfig).includes(guideId)) { + return response.ok({ + body: { config: guidesConfig[guideId as GuideId] }, + }); + } + return response.notFound(); + } + ); +}; diff --git a/src/plugins/guided_onboarding/server/routes/guide_state_routes.ts b/src/plugins/guided_onboarding/server/routes/guide_state_routes.ts index daf4461773032..2d6a58d1e1684 100644 --- a/src/plugins/guided_onboarding/server/routes/guide_state_routes.ts +++ b/src/plugins/guided_onboarding/server/routes/guide_state_routes.ts @@ -7,7 +7,7 @@ */ import { IRouter, SavedObjectsClient } from '@kbn/core/server'; -import { API_BASE_PATH } from '../../common/constants'; +import { API_BASE_PATH } from '../../common'; import { findAllGuides } from '../helpers'; export const registerGetGuideStateRoute = (router: IRouter) => { diff --git a/src/plugins/guided_onboarding/server/routes/index.ts b/src/plugins/guided_onboarding/server/routes/index.ts index 361fd6ec797a0..a526d02ef94f6 100755 --- a/src/plugins/guided_onboarding/server/routes/index.ts +++ b/src/plugins/guided_onboarding/server/routes/index.ts @@ -9,10 +9,13 @@ import type { IRouter } from '@kbn/core/server'; import { registerGetGuideStateRoute } from './guide_state_routes'; import { registerGetPluginStateRoute, registerPutPluginStateRoute } from './plugin_state_routes'; +import { registerGetConfigRoute } from './config_routes'; export function defineRoutes(router: IRouter) { registerGetGuideStateRoute(router); registerGetPluginStateRoute(router); registerPutPluginStateRoute(router); + + registerGetConfigRoute(router); } diff --git a/src/plugins/guided_onboarding/server/routes/plugin_state_routes.ts b/src/plugins/guided_onboarding/server/routes/plugin_state_routes.ts index 169333f790912..33d52ea7ce255 100644 --- a/src/plugins/guided_onboarding/server/routes/plugin_state_routes.ts +++ b/src/plugins/guided_onboarding/server/routes/plugin_state_routes.ts @@ -10,7 +10,7 @@ import { IRouter, SavedObjectsClient } from '@kbn/core/server'; import { schema } from '@kbn/config-schema'; import { GuideState } from '@kbn/guided-onboarding'; import { getPluginState, updatePluginStatus } from '../helpers/plugin_state_utils'; -import { API_BASE_PATH } from '../../common/constants'; +import { API_BASE_PATH } from '../../common'; import { updateGuideState } from '../helpers'; export const registerGetPluginStateRoute = (router: IRouter) => { diff --git a/src/plugins/kibana_react/public/page_template/no_data_page/no_data_card/__snapshots__/no_data_card.test.tsx.snap b/src/plugins/kibana_react/public/page_template/no_data_page/no_data_card/__snapshots__/no_data_card.test.tsx.snap index b9cd02ecc6f7f..03c02c8e36560 100644 --- a/src/plugins/kibana_react/public/page_template/no_data_page/no_data_card/__snapshots__/no_data_card.test.tsx.snap +++ b/src/plugins/kibana_react/public/page_template/no_data_page/no_data_card/__snapshots__/no_data_card.test.tsx.snap @@ -138,7 +138,7 @@ exports[`NoDataCard props recommended 1`] = ` class="emotion-euiCard__betaBadgeAnchor" > diff --git a/src/plugins/kibana_usage_collection/server/collectors/management/schema.ts b/src/plugins/kibana_usage_collection/server/collectors/management/schema.ts index 150bc768601f4..0e77b705075f2 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/management/schema.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/management/schema.ts @@ -582,4 +582,8 @@ export const stackManagementSchema: MakeSchemaFrom = { type: 'boolean', _meta: { description: 'Non-default value of setting.' }, }, + 'enterpriseSearch:enableEnginesSection': { + type: 'boolean', + _meta: { description: 'Non-default value of setting.' }, + }, }; diff --git a/src/plugins/kibana_usage_collection/server/collectors/management/types.ts b/src/plugins/kibana_usage_collection/server/collectors/management/types.ts index 8a897721b6dc6..4365e2a1dd72e 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/management/types.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/management/types.ts @@ -155,4 +155,5 @@ export interface UsageStats { 'securitySolution:showRelatedIntegrations': boolean; 'visualization:visualize:legacyGaugeChartsLibrary': boolean; 'enterpriseSearch:enableBehavioralAnalyticsSection': boolean; + 'enterpriseSearch:enableEnginesSection': boolean; } diff --git a/src/plugins/kibana_utils/public/state_management/state_encoder/encode_decode_state.ts b/src/plugins/kibana_utils/public/state_management/state_encoder/encode_decode_state.ts index 3fa11164fad28..952463b2b7b37 100644 --- a/src/plugins/kibana_utils/public/state_management/state_encoder/encode_decode_state.ts +++ b/src/plugins/kibana_utils/public/state_management/state_encoder/encode_decode_state.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import rison, { RisonValue } from 'rison-node'; +import rison from '@kbn/rison'; import { isStateHash, retrieveState, persistState } from '../state_hash'; // should be: @@ -22,14 +22,14 @@ export function decodeState(expandedOrHashedState: string): State { } // should be: -// export function encodeState(expandedOrHashedState: string) -// but this leads to the chain of types mismatches up to BaseStateContainer interfaces, -// as in state containers we don't have any restrictions on state shape +// export function encodeState but this leads to the chain of +// types mismatches up to BaseStateContainer interfaces, as in state containers we don't +// have any restrictions on state shape export function encodeState(state: State, useHash: boolean): string { if (useHash) { return persistState(state); } else { - return rison.encode(state as unknown as RisonValue); + return rison.encodeUnknown(state) ?? ''; } } diff --git a/src/plugins/kibana_utils/public/state_management/state_hash/state_hash.test.ts b/src/plugins/kibana_utils/public/state_management/state_hash/state_hash.test.ts index b1b6bc3c8107d..cd850c25b71c3 100644 --- a/src/plugins/kibana_utils/public/state_management/state_hash/state_hash.test.ts +++ b/src/plugins/kibana_utils/public/state_management/state_hash/state_hash.test.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { encode as encodeRison } from 'rison-node'; +import { encode as encodeRison } from '@kbn/rison'; import { mockStorage } from '../../storage/hashed_item_store/mock'; import { createStateHash, isStateHash } from './state_hash'; diff --git a/src/plugins/saved_search/public/services/saved_searches/get_saved_searches.test.ts b/src/plugins/saved_search/public/services/saved_searches/get_saved_searches.test.ts index f71763f6a25d3..f64d0ef659f00 100644 --- a/src/plugins/saved_search/public/services/saved_searches/get_saved_searches.test.ts +++ b/src/plugins/saved_search/public/services/saved_searches/get_saved_searches.test.ts @@ -100,6 +100,7 @@ describe('getSavedSearch', () => { expect(savedObjectsClient.resolve).toHaveBeenCalled(); expect(savedSearch).toMatchInlineSnapshot(` Object { + "breakdownField": undefined, "columns": Array [ "_source", ], @@ -198,6 +199,7 @@ describe('getSavedSearch', () => { expect(savedObjectsClient.resolve).toHaveBeenCalled(); expect(savedSearch).toMatchInlineSnapshot(` Object { + "breakdownField": undefined, "columns": Array [ "_source", ], diff --git a/src/plugins/saved_search/public/services/saved_searches/saved_searches_utils.test.ts b/src/plugins/saved_search/public/services/saved_searches/saved_searches_utils.test.ts index 9f227bc1afd04..feabac408c116 100644 --- a/src/plugins/saved_search/public/services/saved_searches/saved_searches_utils.test.ts +++ b/src/plugins/saved_search/public/services/saved_searches/saved_searches_utils.test.ts @@ -41,6 +41,7 @@ describe('saved_searches_utils', () => { ) ).toMatchInlineSnapshot(` Object { + "breakdownField": undefined, "columns": Array [ "a", "b", @@ -128,6 +129,7 @@ describe('saved_searches_utils', () => { expect(toSavedSearchAttributes(savedSearch, '{}')).toMatchInlineSnapshot(` Object { + "breakdownField": undefined, "columns": Array [ "c", "d", diff --git a/src/plugins/saved_search/public/services/saved_searches/saved_searches_utils.ts b/src/plugins/saved_search/public/services/saved_searches/saved_searches_utils.ts index 5d37355ea818d..83286f455d8c4 100644 --- a/src/plugins/saved_search/public/services/saved_searches/saved_searches_utils.ts +++ b/src/plugins/saved_search/public/services/saved_searches/saved_searches_utils.ts @@ -50,6 +50,7 @@ export const fromSavedSearchAttributes = ( timeRange: attributes.timeRange, refreshInterval: attributes.refreshInterval, rowsPerPage: attributes.rowsPerPage, + breakdownField: attributes.breakdownField, }); export const toSavedSearchAttributes = ( @@ -72,4 +73,5 @@ export const toSavedSearchAttributes = ( timeRange: savedSearch.timeRange, refreshInterval: savedSearch.refreshInterval, rowsPerPage: savedSearch.rowsPerPage, + breakdownField: savedSearch.breakdownField, }); diff --git a/src/plugins/saved_search/public/services/saved_searches/types.ts b/src/plugins/saved_search/public/services/saved_searches/types.ts index 81dbe19517798..f4e5ebecd559f 100644 --- a/src/plugins/saved_search/public/services/saved_searches/types.ts +++ b/src/plugins/saved_search/public/services/saved_searches/types.ts @@ -46,6 +46,7 @@ export interface SavedSearchAttributes { refreshInterval?: RefreshInterval; rowsPerPage?: number; + breakdownField?: string; } /** @internal **/ @@ -82,4 +83,5 @@ export interface SavedSearch { refreshInterval?: RefreshInterval; rowsPerPage?: number; + breakdownField?: string; } diff --git a/src/plugins/saved_search/server/saved_objects/search.ts b/src/plugins/saved_search/server/saved_objects/search.ts index 29130ac519334..5960cd8ebdbe9 100644 --- a/src/plugins/saved_search/server/saved_objects/search.ts +++ b/src/plugins/saved_search/server/saved_objects/search.ts @@ -68,6 +68,7 @@ export function getSavedSearchObjectType( }, }, rowsPerPage: { type: 'integer', index: false, doc_values: false }, + breakdownField: { type: 'text' }, }, }, migrations: () => getAllMigrations(getSearchSourceMigrations()), diff --git a/src/plugins/telemetry/schema/oss_plugins.json b/src/plugins/telemetry/schema/oss_plugins.json index b59177259ece3..c2b0971827d14 100644 --- a/src/plugins/telemetry/schema/oss_plugins.json +++ b/src/plugins/telemetry/schema/oss_plugins.json @@ -9125,6 +9125,12 @@ "_meta": { "description": "Non-default value of setting." } + }, + "enterpriseSearch:enableEnginesSection": { + "type": "boolean", + "_meta": { + "description": "Non-default value of setting." + } } } }, diff --git a/src/plugins/telemetry_collection_manager/server/plugin.test.ts b/src/plugins/telemetry_collection_manager/server/plugin.test.ts index 5ffe8235b3930..adfe2c64a4916 100644 --- a/src/plugins/telemetry_collection_manager/server/plugin.test.ts +++ b/src/plugins/telemetry_collection_manager/server/plugin.test.ts @@ -136,6 +136,15 @@ describe('Telemetry Collection Manager', () => { ).toBeInstanceOf(TelemetrySavedObjectsClient); }); + test('caches the promise calling `getStats` for concurrent requests', async () => { + collectionStrategy.clusterDetailsGetter.mockResolvedValue([ + { clusterUuid: 'clusterUuid' }, + ]); + collectionStrategy.statsGetter.mockResolvedValue([basicStats]); + await Promise.all([setupApi.getStats(config), setupApi.getStats(config)]); + expect(collectionStrategy.statsGetter).toHaveBeenCalledTimes(1); + }); + it('calls getStats with passed refreshCache config', async () => { const getStatsCollectionConfig: jest.SpyInstance< TelemetryCollectionManagerPlugin['getStatsCollectionConfig'] @@ -270,6 +279,15 @@ describe('Telemetry Collection Manager', () => { getStatsCollectionConfig.mockRestore(); }); + + test('does not cache the promise calling `getStats` for concurrent requests', async () => { + collectionStrategy.clusterDetailsGetter.mockResolvedValue([ + { clusterUuid: 'clusterUuid' }, + ]); + collectionStrategy.statsGetter.mockResolvedValue([basicStats]); + await Promise.all([setupApi.getStats(config), setupApi.getStats(config)]); + expect(collectionStrategy.statsGetter).toHaveBeenCalledTimes(2); + }); }); describe('getOptInStats', () => { diff --git a/src/plugins/telemetry_collection_manager/server/plugin.ts b/src/plugins/telemetry_collection_manager/server/plugin.ts index 4e7a96646b1ff..d3db80ed728de 100644 --- a/src/plugins/telemetry_collection_manager/server/plugin.ts +++ b/src/plugins/telemetry_collection_manager/server/plugin.ts @@ -340,20 +340,47 @@ export class TelemetryCollectionManagerPlugin } const cacheKey = this.createCacheKey(collectionSource, clustersDetails); - const cachedUsageStatsPayload = this.cacheManager.getFromCache(cacheKey); - if (cachedUsageStatsPayload) { - return this.updateFetchedAt(cachedUsageStatsPayload); + const cachedUsageStatsPromise = + this.cacheManager.getFromCache>(cacheKey); + if (cachedUsageStatsPromise) { + return this.updateFetchedAt(await cachedUsageStatsPromise); } + const statsFromCollectionPromise = this.getStatsFromCollection( + clustersDetails, + collection, + statsCollectionConfig + ); + this.cacheManager.setCache(cacheKey, statsFromCollectionPromise); + + try { + const stats = await statsFromCollectionPromise; + return this.updateFetchedAt(stats); + } catch (err) { + this.logger.debug( + `Failed to generate the telemetry report (${err.message}). Resetting the cache...` + ); + this.cacheManager.resetCache(); + throw err; + } + } + + private async getStatsFromCollection( + clustersDetails: ClusterDetails[], + collection: CollectionStrategy, + statsCollectionConfig: StatsCollectionConfig + ) { + const context: StatsCollectionContext = { + logger: this.logger.get(collection.title), + version: this.version, + }; + const { title: collectionSource } = collection; const now = new Date().toISOString(); const stats = await collection.statsGetter(clustersDetails, statsCollectionConfig, context); - const usageStatsPayload = stats.map((stat) => ({ + return stats.map((stat) => ({ collectionSource, cacheDetails: { updatedAt: now, fetchedAt: now }, ...stat, })); - this.cacheManager.setCache(cacheKey, usageStatsPayload); - - return this.updateFetchedAt(usageStatsPayload); } } diff --git a/src/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/handlebars.ts b/src/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/handlebars.ts index 9dbeb270a9d72..14e1832c48afb 100644 --- a/src/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/handlebars.ts +++ b/src/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/handlebars.ts @@ -7,7 +7,7 @@ */ import Handlebars from '@kbn/handlebars'; -import { encode, RisonValue } from 'rison-node'; +import { encode } from '@kbn/rison'; import dateMath from '@kbn/datemath'; import moment, { Moment } from 'moment'; import numeral from '@elastic/numeral'; @@ -44,7 +44,7 @@ function createSerializationHelper( handlebars.registerHelper('json', createSerializationHelper('json', JSON.stringify)); handlebars.registerHelper( 'rison', - createSerializationHelper('rison', (v) => encode(v as RisonValue)) + createSerializationHelper('rison', (v) => encode(v)) ); handlebars.registerHelper('date', (...args) => { diff --git a/src/plugins/unified_field_list/README.md b/src/plugins/unified_field_list/README.md index 23edffd5101dc..78a6e5084691e 100755 --- a/src/plugins/unified_field_list/README.md +++ b/src/plugins/unified_field_list/README.md @@ -81,18 +81,16 @@ const { refetchFieldsExistenceInfo, isProcessing } = useExistingFieldsFetcher({ ... }); const fieldsExistenceReader = useExistingFieldsReader() -const { fieldGroups } = useGroupedFields({ - dataViewId: currentDataViewId, - allFields, - fieldsExistenceReader, +const fieldListGroupedProps = useGroupedFields({ + dataViewId: currentDataViewId, // pass `null` here for text-based queries to skip fields existence check + allFields, // pass `null` to show loading indicators + fieldsExistenceReader, // pass `undefined` for text-based queries ... }); // and now we can render a field list diff --git a/src/plugins/unified_field_list/common/utils/field_existing_utils.ts b/src/plugins/unified_field_list/common/utils/field_existing_utils.ts index fcc08a141dae1..006568bf37f2e 100644 --- a/src/plugins/unified_field_list/common/utils/field_existing_utils.ts +++ b/src/plugins/unified_field_list/common/utils/field_existing_utils.ts @@ -132,7 +132,7 @@ export function buildFieldList(indexPattern: DataView, metaFields: string[]): Fi script: field.script, // id is a special case - it doesn't show up in the meta field list, // but as it's not part of source, it has to be handled separately. - isMeta: metaFields.includes(field.name) || field.name === '_id', + isMeta: metaFields?.includes(field.name) || field.name === '_id', runtimeField: !field.isMapped ? field.runtimeField : undefined, }; }); diff --git a/src/plugins/unified_field_list/public/components/field_list/field_list_grouped.test.tsx b/src/plugins/unified_field_list/public/components/field_list/field_list_grouped.test.tsx index 59cd7e56ff390..4d1cb45fe1936 100644 --- a/src/plugins/unified_field_list/public/components/field_list/field_list_grouped.test.tsx +++ b/src/plugins/unified_field_list/public/components/field_list/field_list_grouped.test.tsx @@ -24,7 +24,7 @@ describe('UnifiedFieldList + useGroupedFields()', () => { let defaultProps: FieldListGroupedProps; let mockedServices: GroupedFieldsParams['services']; const allFields = dataView.fields; - // 5 times more fields. Added fields will be treated as empty as they are not a part of the data view. + // 5 times more fields. Added fields will be treated as Unmapped as they are not a part of the data view. const manyFields = [...new Array(5)].flatMap((_, index) => allFields.map((field) => { return new DataViewField({ ...field.toSpec(), name: `${field.name}${index || ''}` }); @@ -44,6 +44,7 @@ describe('UnifiedFieldList + useGroupedFields()', () => { defaultProps = { fieldGroups: {}, fieldsExistenceStatus: ExistenceFetchStatus.succeeded, + scrollToTopResetCounter: 0, fieldsExistInIndex: true, screenReaderDescriptionForSearchInputId: 'testId', renderFieldItem: jest.fn(({ field, itemIndex, groupIndex }) => ( @@ -268,14 +269,14 @@ describe('UnifiedFieldList + useGroupedFields()', () => { expect( wrapper.find(`#${defaultProps.screenReaderDescriptionForSearchInputId}`).first().text() - ).toBe('25 available fields. 112 empty fields. 3 meta fields.'); + ).toBe('25 available fields. 112 unmapped fields. 0 empty fields. 3 meta fields.'); expect( wrapper.find(FieldsAccordion).map((accordion) => accordion.prop('paginatedFields').length) - ).toStrictEqual([25, 0, 0]); + ).toStrictEqual([25, 0, 0, 0]); await act(async () => { await wrapper - .find('[data-test-subj="fieldListGroupedEmptyFields"]') + .find('[data-test-subj="fieldListGroupedUnmappedFields"]') .find('button') .first() .simulate('click'); @@ -284,11 +285,11 @@ describe('UnifiedFieldList + useGroupedFields()', () => { expect( wrapper.find(FieldsAccordion).map((accordion) => accordion.prop('paginatedFields').length) - ).toStrictEqual([25, 50, 0]); + ).toStrictEqual([25, 50, 0, 0]); await act(async () => { await wrapper - .find('[data-test-subj="fieldListGroupedMetaFields"]') + .find('[data-test-subj="fieldListGroupedEmptyFields"]') .find('button') .first() .simulate('click'); @@ -297,7 +298,7 @@ describe('UnifiedFieldList + useGroupedFields()', () => { expect( wrapper.find(FieldsAccordion).map((accordion) => accordion.prop('paginatedFields').length) - ).toStrictEqual([25, 88, 0]); + ).toStrictEqual([25, 88, 0, 0]); }); it('renders correctly when filtered', async () => { @@ -315,7 +316,7 @@ describe('UnifiedFieldList + useGroupedFields()', () => { expect( wrapper.find(`#${defaultProps.screenReaderDescriptionForSearchInputId}`).first().text() - ).toBe('25 available fields. 112 empty fields. 3 meta fields.'); + ).toBe('25 available fields. 112 unmapped fields. 0 empty fields. 3 meta fields.'); await act(async () => { await wrapper.setProps({ @@ -329,7 +330,7 @@ describe('UnifiedFieldList + useGroupedFields()', () => { expect( wrapper.find(`#${defaultProps.screenReaderDescriptionForSearchInputId}`).first().text() - ).toBe('2 available fields. 8 empty fields. 0 meta fields.'); + ).toBe('2 available fields. 8 unmapped fields. 0 empty fields. 0 meta fields.'); await act(async () => { await wrapper.setProps({ @@ -343,7 +344,7 @@ describe('UnifiedFieldList + useGroupedFields()', () => { expect( wrapper.find(`#${defaultProps.screenReaderDescriptionForSearchInputId}`).first().text() - ).toBe('0 available fields. 12 empty fields. 3 meta fields.'); + ).toBe('0 available fields. 12 unmapped fields. 0 empty fields. 3 meta fields.'); }); it('renders correctly when non-supported fields are filtered out', async () => { @@ -361,7 +362,7 @@ describe('UnifiedFieldList + useGroupedFields()', () => { expect( wrapper.find(`#${defaultProps.screenReaderDescriptionForSearchInputId}`).first().text() - ).toBe('25 available fields. 112 empty fields. 3 meta fields.'); + ).toBe('25 available fields. 112 unmapped fields. 0 empty fields. 3 meta fields.'); await act(async () => { await wrapper.setProps({ @@ -375,7 +376,7 @@ describe('UnifiedFieldList + useGroupedFields()', () => { expect( wrapper.find(`#${defaultProps.screenReaderDescriptionForSearchInputId}`).first().text() - ).toBe('23 available fields. 104 empty fields. 3 meta fields.'); + ).toBe('23 available fields. 104 unmapped fields. 0 empty fields. 3 meta fields.'); }); it('renders correctly when selected fields are present', async () => { @@ -393,7 +394,7 @@ describe('UnifiedFieldList + useGroupedFields()', () => { expect( wrapper.find(`#${defaultProps.screenReaderDescriptionForSearchInputId}`).first().text() - ).toBe('25 available fields. 112 empty fields. 3 meta fields.'); + ).toBe('25 available fields. 112 unmapped fields. 0 empty fields. 3 meta fields.'); await act(async () => { await wrapper.setProps({ @@ -408,6 +409,30 @@ describe('UnifiedFieldList + useGroupedFields()', () => { expect( wrapper.find(`#${defaultProps.screenReaderDescriptionForSearchInputId}`).first().text() - ).toBe('2 selected fields. 25 available fields. 112 empty fields. 3 meta fields.'); + ).toBe( + '2 selected fields. 25 available fields. 112 unmapped fields. 0 empty fields. 3 meta fields.' + ); + }); + + it('renders correctly when popular fields limit and custom selected fields are present', async () => { + const hookParams = { + dataViewId: dataView.id!, + allFields: manyFields, + popularFieldsLimit: 10, + sortedSelectedFields: [manyFields[0], manyFields[1]], + }; + const wrapper = await mountGroupedList({ + listProps: { + ...defaultProps, + fieldsExistenceStatus: ExistenceFetchStatus.succeeded, + }, + hookParams, + }); + + expect( + wrapper.find(`#${defaultProps.screenReaderDescriptionForSearchInputId}`).first().text() + ).toBe( + '2 selected fields. 10 popular fields. 25 available fields. 112 unmapped fields. 0 empty fields. 3 meta fields.' + ); }); }); diff --git a/src/plugins/unified_field_list/public/components/field_list/field_list_grouped.tsx b/src/plugins/unified_field_list/public/components/field_list/field_list_grouped.tsx index 5510ddb2b1d43..94a76d9b6a6dc 100644 --- a/src/plugins/unified_field_list/public/components/field_list/field_list_grouped.tsx +++ b/src/plugins/unified_field_list/public/components/field_list/field_list_grouped.tsx @@ -7,14 +7,14 @@ */ import { partition, throttle } from 'lodash'; -import React, { useState, Fragment, useCallback, useMemo } from 'react'; +import React, { Fragment, useCallback, useEffect, useMemo, useState } from 'react'; import { i18n } from '@kbn/i18n'; import { EuiScreenReaderOnly, EuiSpacer } from '@elastic/eui'; import { type DataViewField } from '@kbn/data-views-plugin/common'; import { NoFieldsCallout } from './no_fields_callout'; -import { FieldsAccordion, type FieldsAccordionProps } from './fields_accordion'; +import { FieldsAccordion, type FieldsAccordionProps, getFieldKey } from './fields_accordion'; import type { FieldListGroups, FieldListItem } from '../../types'; -import { ExistenceFetchStatus } from '../../types'; +import { ExistenceFetchStatus, FieldsGroup, FieldsGroupNames } from '../../types'; import './field_list_grouped.scss'; const PAGINATION_SIZE = 50; @@ -33,6 +33,7 @@ export interface FieldListGroupedProps { fieldsExistenceStatus: ExistenceFetchStatus; fieldsExistInIndex: boolean; renderFieldItem: FieldsAccordionProps['renderFieldItem']; + scrollToTopResetCounter: number; screenReaderDescriptionForSearchInputId?: string; 'data-test-subj'?: string; } @@ -42,6 +43,7 @@ function InnerFieldListGrouped({ fieldsExistenceStatus, fieldsExistInIndex, renderFieldItem, + scrollToTopResetCounter, screenReaderDescriptionForSearchInputId, 'data-test-subj': dataTestSubject = 'fieldListGrouped', }: FieldListGroupedProps) { @@ -60,6 +62,14 @@ function InnerFieldListGrouped({ ) ); + useEffect(() => { + // Reset the scroll if we have made material changes to the field list + if (scrollContainer && scrollToTopResetCounter) { + scrollContainer.scrollTop = 0; + setPageSize(PAGINATION_SIZE); + } + }, [scrollToTopResetCounter, scrollContainer]); + const lazyScroll = useCallback(() => { if (scrollContainer) { const nearBottom = @@ -93,9 +103,12 @@ function InnerFieldListGrouped({ ); }, [pageSize, fieldGroupsToShow, accordionState]); + const hasSpecialFields = Boolean(fieldGroupsToCollapse[0]?.[1]?.fields?.length); + return (
    { if (el && !el.dataset.dynamicScroll) { el.dataset.dynamicScroll = 'true'; @@ -114,9 +127,7 @@ function InnerFieldListGrouped({ > {hasSyncedExistingFields ? [ - fieldGroups.SelectedFields && - (!fieldGroups.SelectedFields?.hideIfEmpty || - fieldGroups.SelectedFields?.fields?.length > 0) && + shouldIncludeGroupDescriptionInAria(fieldGroups.SelectedFields) && i18n.translate( 'unifiedFieldList.fieldListGrouped.fieldSearchForSelectedFieldsLiveRegion', { @@ -127,6 +138,17 @@ function InnerFieldListGrouped({ }, } ), + shouldIncludeGroupDescriptionInAria(fieldGroups.PopularFields) && + i18n.translate( + 'unifiedFieldList.fieldListGrouped.fieldSearchForPopularFieldsLiveRegion', + { + defaultMessage: + '{popularFields} popular {popularFields, plural, one {field} other {fields}}.', + values: { + popularFields: fieldGroups.PopularFields?.fields?.length || 0, + }, + } + ), fieldGroups.AvailableFields?.fields && i18n.translate( 'unifiedFieldList.fieldListGrouped.fieldSearchForAvailableFieldsLiveRegion', @@ -138,9 +160,18 @@ function InnerFieldListGrouped({ }, } ), - fieldGroups.EmptyFields && - (!fieldGroups.EmptyFields?.hideIfEmpty || - fieldGroups.EmptyFields?.fields?.length > 0) && + shouldIncludeGroupDescriptionInAria(fieldGroups.UnmappedFields) && + i18n.translate( + 'unifiedFieldList.fieldListGrouped.fieldSearchForUnmappedFieldsLiveRegion', + { + defaultMessage: + '{unmappedFields} unmapped {unmappedFields, plural, one {field} other {fields}}.', + values: { + unmappedFields: fieldGroups.UnmappedFields?.fields?.length || 0, + }, + } + ), + shouldIncludeGroupDescriptionInAria(fieldGroups.EmptyFields) && i18n.translate( 'unifiedFieldList.fieldListGrouped.fieldSearchForEmptyFieldsLiveRegion', { @@ -151,9 +182,7 @@ function InnerFieldListGrouped({ }, } ), - fieldGroups.MetaFields && - (!fieldGroups.MetaFields?.hideIfEmpty || - fieldGroups.MetaFields?.fields?.length > 0) && + shouldIncludeGroupDescriptionInAria(fieldGroups.MetaFields) && i18n.translate( 'unifiedFieldList.fieldListGrouped.fieldSearchForMetaFieldsLiveRegion', { @@ -171,16 +200,26 @@ function InnerFieldListGrouped({
    )} -
      - {fieldGroupsToCollapse.flatMap(([, { fields }]) => - fields.map((field, index) => ( - - {renderFieldItem({ field, itemIndex: index, groupIndex: 0, hideDetails: true })} - - )) - )} -
    - + {hasSpecialFields && ( + <> +
      + {fieldGroupsToCollapse.flatMap(([key, { fields }]) => + fields.map((field, index) => ( + + {renderFieldItem({ + field, + itemIndex: index, + groupIndex: 0, + groupName: key as FieldsGroupNames, + hideDetails: true, + })} + + )) + )} +
    + + + )} {fieldGroupsToShow.map(([key, fieldGroup], index) => { const hidden = Boolean(fieldGroup.hideIfEmpty) && !fieldGroup.fields.length; if (hidden) { @@ -199,6 +238,7 @@ function InnerFieldListGrouped({ isFiltered={fieldGroup.fieldCount !== fieldGroup.fields.length} paginatedFields={paginatedFields[key]} groupIndex={index + 1} + groupName={key as FieldsGroupNames} onToggle={(open) => { setAccordionState((s) => ({ ...s, @@ -224,6 +264,7 @@ function InnerFieldListGrouped({ isAffectedByFieldFilter={fieldGroup.fieldCount !== fieldGroup.fields.length} fieldsExistInIndex={!!fieldsExistInIndex} defaultNoFieldsMessage={fieldGroup.defaultNoFieldsMessage} + data-test-subj={`${dataTestSubject}${key}NoFieldsCallout`} /> )} renderFieldItem={renderFieldItem} @@ -243,3 +284,13 @@ const FieldListGrouped = React.memo(InnerFieldListGrouped) as GenericFieldListGr // Necessary for React.lazy // eslint-disable-next-line import/no-default-export export default FieldListGrouped; + +function shouldIncludeGroupDescriptionInAria( + group: FieldsGroup | undefined +): boolean { + if (!group) { + return false; + } + // has some fields or an empty list should be still shown + return group.fields?.length > 0 || !group.hideIfEmpty; +} diff --git a/src/plugins/unified_field_list/public/components/field_list/fields_accordion.test.tsx b/src/plugins/unified_field_list/public/components/field_list/fields_accordion.test.tsx index 2804c1bbe5ee1..6c94f8a8e8335 100644 --- a/src/plugins/unified_field_list/public/components/field_list/fields_accordion.test.tsx +++ b/src/plugins/unified_field_list/public/components/field_list/fields_accordion.test.tsx @@ -11,7 +11,7 @@ import { stubLogstashDataView as dataView } from '@kbn/data-views-plugin/common/ import { EuiLoadingSpinner, EuiNotificationBadge, EuiText } from '@elastic/eui'; import { mountWithIntl } from '@kbn/test-jest-helpers'; import { FieldsAccordion, FieldsAccordionProps } from './fields_accordion'; -import { FieldListItem } from '../../types'; +import { FieldListItem, FieldsGroupNames } from '../../types'; describe('UnifiedFieldList ', () => { let defaultProps: FieldsAccordionProps; @@ -21,7 +21,8 @@ describe('UnifiedFieldList ', () => { defaultProps = { initialIsOpen: true, onToggle: jest.fn(), - groupIndex: 0, + groupIndex: 1, + groupName: FieldsGroupNames.AvailableFields, id: 'id', label: 'label-test', hasLoaded: true, diff --git a/src/plugins/unified_field_list/public/components/field_list/fields_accordion.tsx b/src/plugins/unified_field_list/public/components/field_list/fields_accordion.tsx index 5222cf1b0e678..8b7ca22bff676 100644 --- a/src/plugins/unified_field_list/public/components/field_list/fields_accordion.tsx +++ b/src/plugins/unified_field_list/public/components/field_list/fields_accordion.tsx @@ -18,7 +18,7 @@ import { } from '@elastic/eui'; import classNames from 'classnames'; import { type DataViewField } from '@kbn/data-views-plugin/common'; -import type { FieldListItem } from '../../types'; +import { type FieldListItem, FieldsGroupNames } from '../../types'; import './fields_accordion.scss'; export interface FieldsAccordionProps { @@ -32,12 +32,14 @@ export interface FieldsAccordionProps { hideDetails?: boolean; isFiltered: boolean; groupIndex: number; + groupName: FieldsGroupNames; paginatedFields: T[]; renderFieldItem: (params: { field: T; hideDetails?: boolean; itemIndex: number; groupIndex: number; + groupName: FieldsGroupNames; }) => JSX.Element; renderCallout: () => JSX.Element; showExistenceFetchError?: boolean; @@ -55,6 +57,7 @@ function InnerFieldsAccordion({ hideDetails, isFiltered, groupIndex, + groupName, paginatedFields, renderFieldItem, renderCallout, @@ -99,6 +102,9 @@ function InnerFieldsAccordion({ content={i18n.translate('unifiedFieldList.fieldsAccordion.existenceErrorLabel', { defaultMessage: "Field information can't be loaded", })} + iconProps={{ + 'data-test-subj': `${id}-fetchWarning`, + }} /> ); } @@ -128,7 +134,7 @@ function InnerFieldsAccordion({ ); } - return ; + return ; }, [showExistenceFetchError, showExistenceFetchTimeout, hasLoaded, isFiltered, id, fieldsCount]); return ( @@ -146,8 +152,8 @@ function InnerFieldsAccordion({
      {paginatedFields && paginatedFields.map((field, index) => ( - - {renderFieldItem({ field, itemIndex: index, groupIndex, hideDetails })} + + {renderFieldItem({ field, itemIndex: index, groupIndex, groupName, hideDetails })} ))}
    @@ -159,3 +165,6 @@ function InnerFieldsAccordion({ } export const FieldsAccordion = React.memo(InnerFieldsAccordion) as typeof InnerFieldsAccordion; + +export const getFieldKey = (field: FieldListItem): string => + `${field.name}-${field.displayName}-${field.type}`; diff --git a/src/plugins/unified_field_list/public/components/field_list/no_fields_callout.test.tsx b/src/plugins/unified_field_list/public/components/field_list/no_fields_callout.test.tsx index 03936a89877ba..5a18a261d136d 100644 --- a/src/plugins/unified_field_list/public/components/field_list/no_fields_callout.test.tsx +++ b/src/plugins/unified_field_list/public/components/field_list/no_fields_callout.test.tsx @@ -16,6 +16,7 @@ describe('UnifiedFieldList ', () => { expect(component).toMatchInlineSnapshot(` @@ -26,6 +27,7 @@ describe('UnifiedFieldList ', () => { expect(component).toMatchInlineSnapshot(` @@ -38,6 +40,7 @@ describe('UnifiedFieldList ', () => { expect(component).toMatchInlineSnapshot(` @@ -51,6 +54,7 @@ describe('UnifiedFieldList ', () => { expect(component).toMatchInlineSnapshot(` @@ -78,6 +82,7 @@ describe('UnifiedFieldList ', () => { expect(component).toMatchInlineSnapshot(` @@ -108,6 +113,7 @@ describe('UnifiedFieldList ', () => { expect(component).toMatchInlineSnapshot(` @@ -139,6 +145,7 @@ describe('UnifiedFieldList ', () => { expect(component).toMatchInlineSnapshot(` diff --git a/src/plugins/unified_field_list/public/components/field_list/no_fields_callout.tsx b/src/plugins/unified_field_list/public/components/field_list/no_fields_callout.tsx index 3d24b400da3cb..3eca7573d9110 100644 --- a/src/plugins/unified_field_list/public/components/field_list/no_fields_callout.tsx +++ b/src/plugins/unified_field_list/public/components/field_list/no_fields_callout.tsx @@ -23,12 +23,14 @@ export const NoFieldsCallout = ({ isAffectedByFieldFilter = false, isAffectedByTimerange = false, isAffectedByGlobalFilter = false, + 'data-test-subj': dataTestSubject = 'noFieldsCallout', }: { fieldsExistInIndex: boolean; isAffectedByFieldFilter?: boolean; defaultNoFieldsMessage?: string; isAffectedByTimerange?: boolean; isAffectedByGlobalFilter?: boolean; + 'data-test-subj'?: string; }) => { if (!fieldsExistInIndex) { return ( @@ -38,6 +40,7 @@ export const NoFieldsCallout = ({ title={i18n.translate('unifiedFieldList.fieldList.noFieldsCallout.noFieldsLabel', { defaultMessage: 'No fields exist in this data view.', })} + data-test-subj={`${dataTestSubject}-noFieldsExist`} /> ); } @@ -53,6 +56,7 @@ export const NoFieldsCallout = ({ }) : defaultNoFieldsMessage } + data-test-subj={`${dataTestSubject}-noFieldsMatch`} > {(isAffectedByTimerange || isAffectedByFieldFilter || isAffectedByGlobalFilter) && ( <> diff --git a/src/plugins/unified_field_list/public/components/field_stats/field_stats.test.tsx b/src/plugins/unified_field_list/public/components/field_stats/field_stats.test.tsx index 312abc2bb323f..317fe9082d28e 100644 --- a/src/plugins/unified_field_list/public/components/field_stats/field_stats.test.tsx +++ b/src/plugins/unified_field_list/public/components/field_stats/field_stats.test.tsx @@ -8,6 +8,7 @@ import React from 'react'; import { act } from 'react-dom/test-utils'; +import { ReactWrapper } from 'enzyme'; import { EuiLoadingSpinner, EuiProgress } from '@elastic/eui'; import { coreMock } from '@kbn/core/public/mocks'; import { mountWithIntl } from '@kbn/test-jest-helpers'; @@ -120,6 +121,18 @@ describe('UnifiedFieldList ', () => { }); }); + async function mountComponent(component: React.ReactElement): Promise { + let wrapper: ReactWrapper; + await act(async () => { + wrapper = await mountWithIntl(component); + // wait for lazy modules if any + await new Promise((resolve) => setTimeout(resolve, 0)); + await wrapper.update(); + }); + + return wrapper!; + } + beforeEach(() => { (loadFieldStats as jest.Mock).mockReset(); (loadFieldStats as jest.Mock).mockImplementation(() => Promise.resolve({})); @@ -134,7 +147,7 @@ describe('UnifiedFieldList ', () => { }); }); - const wrapper = mountWithIntl( + const wrapper = await mountComponent( ', () => { /> ); - await wrapper.update(); - expect(loadFieldStats).toHaveBeenCalledWith({ abortController: new AbortController(), services: { data: mockedServices.data }, @@ -260,33 +271,27 @@ describe('UnifiedFieldList ', () => { }); it('should not request field stats for range fields', async () => { - const wrapper = await mountWithIntl( + const wrapper = await mountComponent( f.name === 'ip_range')!} /> ); - await wrapper.update(); - expect(loadFieldStats).toHaveBeenCalled(); expect(wrapper.text()).toBe('Analysis is not available for this field.'); }); it('should not request field stats for geo fields', async () => { - const wrapper = await mountWithIntl( + const wrapper = await mountComponent( f.name === 'geo_shape')!} /> ); - await wrapper.update(); - expect(loadFieldStats).toHaveBeenCalled(); expect(wrapper.text()).toBe('Analysis is not available for this field.'); }); it('should render a message if no data is found', async () => { - const wrapper = await mountWithIntl(); - - await wrapper.update(); + const wrapper = await mountComponent(); expect(loadFieldStats).toHaveBeenCalled(); @@ -302,9 +307,7 @@ describe('UnifiedFieldList ', () => { }); }); - const wrapper = mountWithIntl(); - - await wrapper.update(); + const wrapper = await mountComponent(); await act(async () => { resolveFunction!({ @@ -330,7 +333,7 @@ describe('UnifiedFieldList ', () => { }); }); - const wrapper = mountWithIntl( + const wrapper = await mountComponent( ', () => { /> ); - await wrapper.update(); - expect(loadFieldStats).toHaveBeenCalledWith({ abortController: new AbortController(), services: { data: mockedServices.data }, @@ -433,7 +434,7 @@ describe('UnifiedFieldList ', () => { }); }); - const wrapper = mountWithIntl( + const wrapper = await mountComponent( ', () => { /> ); - await wrapper.update(); - expect(wrapper.find(EuiLoadingSpinner)).toHaveLength(1); await act(async () => { @@ -507,7 +506,7 @@ describe('UnifiedFieldList ', () => { }); }); - const wrapper = mountWithIntl( + const wrapper = await mountComponent( ', () => { /> ); - await wrapper.update(); - expect(loadFieldStats).toHaveBeenCalledWith({ abortController: new AbortController(), services: { data: mockedServices.data }, @@ -615,7 +612,7 @@ describe('UnifiedFieldList ', () => { const field = dataView.fields.find((f) => f.name === 'machine.ram')!; - const wrapper = mountWithIntl( + const wrapper = await mountComponent( ', () => { /> ); - await wrapper.update(); - expect(loadFieldStats).toHaveBeenCalledWith({ abortController: new AbortController(), services: { data: mockedServices.data }, diff --git a/src/plugins/unified_field_list/public/components/field_stats/field_stats.tsx b/src/plugins/unified_field_list/public/components/field_stats/field_stats.tsx index eafdcc0dab69a..99c31fc9f64e1 100755 --- a/src/plugins/unified_field_list/public/components/field_stats/field_stats.tsx +++ b/src/plugins/unified_field_list/public/components/field_stats/field_stats.tsx @@ -378,33 +378,36 @@ const FieldStatsComponent: React.FC = ({ if (histogram && histogram.buckets.length && topValues && topValues.buckets.length) { title = ( - { - setShowingHistogram(optionId === 'histogram'); - }} - idSelected={showingHistogram ? 'histogram' : 'topValues'} - /> + <> + { + setShowingHistogram(optionId === 'histogram'); + }} + idSelected={showingHistogram ? 'histogram' : 'topValues'} + /> + + ); } else if (field.type === 'date') { title = ( diff --git a/src/plugins/unified_field_list/public/hooks/__snapshots__/use_grouped_fields.test.tsx.snap b/src/plugins/unified_field_list/public/hooks/__snapshots__/use_grouped_fields.test.tsx.snap new file mode 100644 index 0000000000000..d3c95c363695d --- /dev/null +++ b/src/plugins/unified_field_list/public/hooks/__snapshots__/use_grouped_fields.test.tsx.snap @@ -0,0 +1,259 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`UnifiedFieldList useGroupedFields() should work correctly for no data 1`] = ` +Object { + "AvailableFields": Object { + "defaultNoFieldsMessage": "There are no available fields that contain data.", + "fieldCount": 0, + "fields": Array [], + "hideDetails": false, + "isAffectedByGlobalFilter": false, + "isAffectedByTimeFilter": true, + "isInitiallyOpen": true, + "showInAccordion": true, + "title": "Available fields", + }, + "EmptyFields": Object { + "defaultNoFieldsMessage": "There are no empty fields.", + "fieldCount": 0, + "fields": Array [], + "helpText": "Fields that don't have any values based on your filters.", + "hideDetails": false, + "hideIfEmpty": false, + "isAffectedByGlobalFilter": false, + "isAffectedByTimeFilter": false, + "isInitiallyOpen": false, + "showInAccordion": true, + "title": "Empty fields", + }, + "MetaFields": Object { + "defaultNoFieldsMessage": "There are no meta fields.", + "fieldCount": 0, + "fields": Array [], + "hideDetails": false, + "hideIfEmpty": false, + "isAffectedByGlobalFilter": false, + "isAffectedByTimeFilter": false, + "isInitiallyOpen": false, + "showInAccordion": true, + "title": "Meta fields", + }, + "PopularFields": Object { + "fieldCount": 0, + "fields": Array [], + "helpText": "Fields that your organization frequently uses, from most to least popular.", + "hideDetails": false, + "hideIfEmpty": true, + "isAffectedByGlobalFilter": false, + "isAffectedByTimeFilter": true, + "isInitiallyOpen": true, + "showInAccordion": true, + "title": "Popular fields", + }, + "SelectedFields": Object { + "fieldCount": 0, + "fields": Array [], + "hideDetails": false, + "hideIfEmpty": true, + "isAffectedByGlobalFilter": false, + "isAffectedByTimeFilter": true, + "isInitiallyOpen": true, + "showInAccordion": true, + "title": "Selected fields", + }, + "SpecialFields": Object { + "fieldCount": 0, + "fields": Array [], + "hideDetails": true, + "isAffectedByGlobalFilter": false, + "isAffectedByTimeFilter": false, + "isInitiallyOpen": false, + "showInAccordion": false, + "title": "", + }, + "UnmappedFields": Object { + "fieldCount": 0, + "fields": Array [], + "helpText": "Fields that aren't explicitly mapped to a field data type.", + "hideDetails": false, + "hideIfEmpty": true, + "isAffectedByGlobalFilter": false, + "isAffectedByTimeFilter": true, + "isInitiallyOpen": false, + "showInAccordion": true, + "title": "Unmapped fields", + }, +} +`; + +exports[`UnifiedFieldList useGroupedFields() should work correctly in loading state 1`] = ` +Object { + "AvailableFields": Object { + "defaultNoFieldsMessage": "There are no available fields that contain data.", + "fieldCount": 0, + "fields": Array [], + "hideDetails": false, + "isAffectedByGlobalFilter": false, + "isAffectedByTimeFilter": true, + "isInitiallyOpen": true, + "showInAccordion": true, + "title": "Available fields", + }, + "EmptyFields": Object { + "defaultNoFieldsMessage": "There are no empty fields.", + "fieldCount": 0, + "fields": Array [], + "helpText": "Fields that don't have any values based on your filters.", + "hideDetails": false, + "hideIfEmpty": false, + "isAffectedByGlobalFilter": false, + "isAffectedByTimeFilter": false, + "isInitiallyOpen": false, + "showInAccordion": true, + "title": "Empty fields", + }, + "MetaFields": Object { + "defaultNoFieldsMessage": "There are no meta fields.", + "fieldCount": 0, + "fields": Array [], + "hideDetails": false, + "hideIfEmpty": false, + "isAffectedByGlobalFilter": false, + "isAffectedByTimeFilter": false, + "isInitiallyOpen": false, + "showInAccordion": true, + "title": "Meta fields", + }, + "PopularFields": Object { + "fieldCount": 0, + "fields": Array [], + "helpText": "Fields that your organization frequently uses, from most to least popular.", + "hideDetails": false, + "hideIfEmpty": true, + "isAffectedByGlobalFilter": false, + "isAffectedByTimeFilter": true, + "isInitiallyOpen": true, + "showInAccordion": true, + "title": "Popular fields", + }, + "SelectedFields": Object { + "fieldCount": 0, + "fields": Array [], + "hideDetails": false, + "hideIfEmpty": true, + "isAffectedByGlobalFilter": false, + "isAffectedByTimeFilter": true, + "isInitiallyOpen": true, + "showInAccordion": true, + "title": "Selected fields", + }, + "SpecialFields": Object { + "fieldCount": 0, + "fields": Array [], + "hideDetails": true, + "isAffectedByGlobalFilter": false, + "isAffectedByTimeFilter": false, + "isInitiallyOpen": false, + "showInAccordion": false, + "title": "", + }, + "UnmappedFields": Object { + "fieldCount": 0, + "fields": Array [], + "helpText": "Fields that aren't explicitly mapped to a field data type.", + "hideDetails": false, + "hideIfEmpty": true, + "isAffectedByGlobalFilter": false, + "isAffectedByTimeFilter": true, + "isInitiallyOpen": false, + "showInAccordion": true, + "title": "Unmapped fields", + }, +} +`; + +exports[`UnifiedFieldList useGroupedFields() should work correctly when global filters are set 1`] = ` +Object { + "AvailableFields": Object { + "defaultNoFieldsMessage": "There are no available fields that contain data.", + "fieldCount": 0, + "fields": Array [], + "hideDetails": false, + "isAffectedByGlobalFilter": true, + "isAffectedByTimeFilter": true, + "isInitiallyOpen": true, + "showInAccordion": true, + "title": "Available fields", + }, + "EmptyFields": Object { + "defaultNoFieldsMessage": "There are no empty fields.", + "fieldCount": 0, + "fields": Array [], + "helpText": "Fields that don't have any values based on your filters.", + "hideDetails": false, + "hideIfEmpty": false, + "isAffectedByGlobalFilter": false, + "isAffectedByTimeFilter": false, + "isInitiallyOpen": false, + "showInAccordion": true, + "title": "Empty fields", + }, + "MetaFields": Object { + "defaultNoFieldsMessage": "There are no meta fields.", + "fieldCount": 0, + "fields": Array [], + "hideDetails": false, + "hideIfEmpty": false, + "isAffectedByGlobalFilter": false, + "isAffectedByTimeFilter": false, + "isInitiallyOpen": false, + "showInAccordion": true, + "title": "Meta fields", + }, + "PopularFields": Object { + "fieldCount": 0, + "fields": Array [], + "helpText": "Fields that your organization frequently uses, from most to least popular.", + "hideDetails": false, + "hideIfEmpty": true, + "isAffectedByGlobalFilter": true, + "isAffectedByTimeFilter": true, + "isInitiallyOpen": true, + "showInAccordion": true, + "title": "Popular fields", + }, + "SelectedFields": Object { + "fieldCount": 0, + "fields": Array [], + "hideDetails": false, + "hideIfEmpty": true, + "isAffectedByGlobalFilter": true, + "isAffectedByTimeFilter": true, + "isInitiallyOpen": true, + "showInAccordion": true, + "title": "Selected fields", + }, + "SpecialFields": Object { + "fieldCount": 0, + "fields": Array [], + "hideDetails": true, + "isAffectedByGlobalFilter": false, + "isAffectedByTimeFilter": false, + "isInitiallyOpen": false, + "showInAccordion": false, + "title": "", + }, + "UnmappedFields": Object { + "fieldCount": 0, + "fields": Array [], + "helpText": "Fields that aren't explicitly mapped to a field data type.", + "hideDetails": false, + "hideIfEmpty": true, + "isAffectedByGlobalFilter": true, + "isAffectedByTimeFilter": true, + "isInitiallyOpen": false, + "showInAccordion": true, + "title": "Unmapped fields", + }, +} +`; diff --git a/src/plugins/unified_field_list/public/hooks/use_existing_fields.ts b/src/plugins/unified_field_list/public/hooks/use_existing_fields.ts index ebf12d4609500..583ca32ce7508 100644 --- a/src/plugins/unified_field_list/public/hooks/use_existing_fields.ts +++ b/src/plugins/unified_field_list/public/hooks/use_existing_fields.ts @@ -15,7 +15,6 @@ import { DataPublicPluginStart, DataViewsContract, getEsQueryConfig, - UI_SETTINGS, } from '@kbn/data-plugin/public'; import { type DataView } from '@kbn/data-plugin/common'; import { loadFieldExisting } from '../services/field_existing'; @@ -32,11 +31,12 @@ export interface ExistingFieldsInfo { } export interface ExistingFieldsFetcherParams { + disableAutoFetching?: boolean; dataViews: DataView[]; - fromDate: string; - toDate: string; - query: Query | AggregateQuery; - filters: Filter[]; + fromDate: string | undefined; // fetching will be skipped if `undefined` + toDate: string | undefined; + query: Query | AggregateQuery | undefined; + filters: Filter[] | undefined; services: { core: Pick; data: DataPublicPluginStart; @@ -89,7 +89,7 @@ export const useExistingFieldsFetcher = ( dataViewId: string | undefined; fetchId: string; }): Promise => { - if (!dataViewId) { + if (!dataViewId || !query || !fromDate || !toDate) { return; } @@ -123,7 +123,7 @@ export const useExistingFieldsFetcher = ( dslQuery: await buildSafeEsQuery( dataView, query, - filters, + filters || [], getEsQueryConfig(core.uiSettings) ), fromDate, @@ -137,11 +137,11 @@ export const useExistingFieldsFetcher = ( const existingFieldNames = result?.existingFieldNames || []; - const metaFields = core.uiSettings.get(UI_SETTINGS.META_FIELDS) || []; if ( - !existingFieldNames.filter((fieldName) => !metaFields.includes?.(fieldName)).length && + onNoData && numberOfFetches === 1 && - onNoData + !existingFieldNames.filter((fieldName) => !dataView?.metaFields?.includes(fieldName)) + .length ) { onNoData(dataViewId); } @@ -173,12 +173,17 @@ export const useExistingFieldsFetcher = ( async (dataViewId?: string) => { const fetchId = generateId(); lastFetchId = fetchId; + + const options = { + fetchId, + dataViewId, + ...params, + }; // refetch only for the specified data view if (dataViewId) { await fetchFieldsExistenceInfo({ - fetchId, + ...options, dataViewId, - ...params, }); return; } @@ -186,9 +191,8 @@ export const useExistingFieldsFetcher = ( await Promise.all( params.dataViews.map((dataView) => fetchFieldsExistenceInfo({ - fetchId, + ...options, dataViewId: dataView.id, - ...params, }) ) ); @@ -205,8 +209,10 @@ export const useExistingFieldsFetcher = ( ); useEffect(() => { - refetchFieldsExistenceInfo(); - }, [refetchFieldsExistenceInfo]); + if (!params.disableAutoFetching) { + refetchFieldsExistenceInfo(); + } + }, [refetchFieldsExistenceInfo, params.disableAutoFetching]); useEffect(() => { return () => { diff --git a/src/plugins/unified_field_list/public/hooks/use_grouped_fields.test.tsx b/src/plugins/unified_field_list/public/hooks/use_grouped_fields.test.tsx index d4d6d3cdc906f..df4b3f684647f 100644 --- a/src/plugins/unified_field_list/public/hooks/use_grouped_fields.test.tsx +++ b/src/plugins/unified_field_list/public/hooks/use_grouped_fields.test.tsx @@ -20,6 +20,12 @@ import { ExistenceFetchStatus, FieldListGroups, FieldsGroupNames } from '../type describe('UnifiedFieldList useGroupedFields()', () => { let mockedServices: GroupedFieldsParams['services']; const allFields = dataView.fields; + // Added fields will be treated as Unmapped as they are not a part of the data view. + const allFieldsIncludingUnmapped = [...new Array(2)].flatMap((_, index) => + allFields.map((field) => { + return new DataViewField({ ...field.toSpec(), name: `${field.name}${index || ''}` }); + }) + ); const anotherDataView = createStubDataView({ spec: { id: 'another-data-view', @@ -39,14 +45,43 @@ describe('UnifiedFieldList useGroupedFields()', () => { }); }); + it('should work correctly in loading state', async () => { + const props: GroupedFieldsParams = { + dataViewId: dataView.id!, + allFields: null, + services: mockedServices, + }; + const { result, waitForNextUpdate, rerender } = renderHook(useGroupedFields, { + initialProps: props, + }); + + await waitForNextUpdate(); + + expect(result.current.fieldGroups).toMatchSnapshot(); + expect(result.current.fieldsExistenceStatus).toBe(ExistenceFetchStatus.unknown); + expect(result.current.fieldsExistInIndex).toBe(false); + expect(result.current.scrollToTopResetCounter).toBeTruthy(); + + rerender({ + ...props, + dataViewId: null, // for text-based queries + allFields: null, + }); + + expect(result.current.fieldsExistenceStatus).toBe(ExistenceFetchStatus.unknown); + expect(result.current.fieldsExistInIndex).toBe(true); + expect(result.current.scrollToTopResetCounter).toBeTruthy(); + }); + it('should work correctly for no data', async () => { - const { result, waitForNextUpdate } = renderHook(() => - useGroupedFields({ - dataViewId: dataView.id!, - allFields: [], - services: mockedServices, - }) - ); + const props: GroupedFieldsParams = { + dataViewId: dataView.id!, + allFields: [], + services: mockedServices, + }; + const { result, waitForNextUpdate, rerender } = renderHook(useGroupedFields, { + initialProps: props, + }); await waitForNextUpdate(); @@ -59,20 +94,36 @@ describe('UnifiedFieldList useGroupedFields()', () => { ).toStrictEqual([ 'SpecialFields-0', 'SelectedFields-0', + 'PopularFields-0', 'AvailableFields-0', + 'UnmappedFields-0', 'EmptyFields-0', 'MetaFields-0', ]); + + expect(fieldGroups).toMatchSnapshot(); + expect(result.current.fieldsExistenceStatus).toBe(ExistenceFetchStatus.succeeded); + expect(result.current.fieldsExistInIndex).toBe(false); + + rerender({ + ...props, + dataViewId: null, // for text-based queries + allFields: [], + }); + + expect(result.current.fieldsExistenceStatus).toBe(ExistenceFetchStatus.succeeded); + expect(result.current.fieldsExistInIndex).toBe(true); }); it('should work correctly with fields', async () => { - const { result, waitForNextUpdate } = renderHook(() => - useGroupedFields({ - dataViewId: dataView.id!, - allFields, - services: mockedServices, - }) - ); + const props: GroupedFieldsParams = { + dataViewId: dataView.id!, + allFields, + services: mockedServices, + }; + const { result, waitForNextUpdate, rerender } = renderHook(useGroupedFields, { + initialProps: props, + }); await waitForNextUpdate(); @@ -85,48 +136,116 @@ describe('UnifiedFieldList useGroupedFields()', () => { ).toStrictEqual([ 'SpecialFields-0', 'SelectedFields-0', + 'PopularFields-0', 'AvailableFields-25', + 'UnmappedFields-0', 'EmptyFields-0', 'MetaFields-3', ]); + + expect(result.current.fieldsExistenceStatus).toBe(ExistenceFetchStatus.succeeded); + expect(result.current.fieldsExistInIndex).toBe(true); + + rerender({ + ...props, + dataViewId: null, // for text-based queries + allFields, + }); + + expect(result.current.fieldsExistenceStatus).toBe(ExistenceFetchStatus.succeeded); + expect(result.current.fieldsExistInIndex).toBe(true); }); it('should work correctly when filtered', async () => { - const { result, waitForNextUpdate } = renderHook(() => - useGroupedFields({ - dataViewId: dataView.id!, - allFields, - services: mockedServices, - onFilterField: (field: DataViewField) => field.name.startsWith('@'), - }) - ); + const props: GroupedFieldsParams = { + dataViewId: dataView.id!, + allFields: allFieldsIncludingUnmapped, + services: mockedServices, + }; + const { result, waitForNextUpdate, rerender } = renderHook(useGroupedFields, { + initialProps: props, + }); await waitForNextUpdate(); - const fieldGroups = result.current.fieldGroups; + let fieldGroups = result.current.fieldGroups; + const scrollToTopResetCounter1 = result.current.scrollToTopResetCounter; expect( Object.keys(fieldGroups!).map( - (key) => `${key}-${fieldGroups![key as FieldsGroupNames]?.fields.length}` + (key) => + `${key}-${fieldGroups![key as FieldsGroupNames]?.fields.length}-${ + fieldGroups![key as FieldsGroupNames]?.fieldCount + }` ) ).toStrictEqual([ - 'SpecialFields-0', - 'SelectedFields-0', - 'AvailableFields-2', - 'EmptyFields-0', - 'MetaFields-0', + 'SpecialFields-0-0', + 'SelectedFields-0-0', + 'PopularFields-0-0', + 'AvailableFields-25-25', + 'UnmappedFields-28-28', + 'EmptyFields-0-0', + 'MetaFields-3-3', + ]); + + rerender({ + ...props, + onFilterField: (field: DataViewField) => field.name.startsWith('@'), + }); + + fieldGroups = result.current.fieldGroups; + + expect( + Object.keys(fieldGroups!).map( + (key) => + `${key}-${fieldGroups![key as FieldsGroupNames]?.fields.length}-${ + fieldGroups![key as FieldsGroupNames]?.fieldCount + }` + ) + ).toStrictEqual([ + 'SpecialFields-0-0', + 'SelectedFields-0-0', + 'PopularFields-0-0', + 'AvailableFields-2-25', + 'UnmappedFields-2-28', + 'EmptyFields-0-0', + 'MetaFields-0-3', ]); + + expect(result.current.scrollToTopResetCounter).not.toBe(scrollToTopResetCounter1); + }); + + it('should not change the scroll position if fields list is extended', async () => { + const props: GroupedFieldsParams = { + dataViewId: dataView.id!, + allFields, + services: mockedServices, + }; + const { result, waitForNextUpdate, rerender } = renderHook(useGroupedFields, { + initialProps: props, + }); + + await waitForNextUpdate(); + + const scrollToTopResetCounter1 = result.current.scrollToTopResetCounter; + + rerender({ + ...props, + allFields: allFieldsIncludingUnmapped, + }); + + expect(result.current.scrollToTopResetCounter).toBe(scrollToTopResetCounter1); }); it('should work correctly when custom unsupported fields are skipped', async () => { - const { result, waitForNextUpdate } = renderHook(() => - useGroupedFields({ + const { result, waitForNextUpdate } = renderHook(useGroupedFields, { + initialProps: { dataViewId: dataView.id!, allFields, services: mockedServices, onSupportedFieldFilter: (field: DataViewField) => field.aggregatable, - }) - ); + }, + }); await waitForNextUpdate(); @@ -139,22 +258,24 @@ describe('UnifiedFieldList useGroupedFields()', () => { ).toStrictEqual([ 'SpecialFields-0', 'SelectedFields-0', + 'PopularFields-0', 'AvailableFields-23', + 'UnmappedFields-0', 'EmptyFields-0', 'MetaFields-3', ]); }); it('should work correctly when selected fields are present', async () => { - const { result, waitForNextUpdate } = renderHook(() => - useGroupedFields({ + const { result, waitForNextUpdate } = renderHook(useGroupedFields, { + initialProps: { dataViewId: dataView.id!, allFields, services: mockedServices, onSelectedFieldFilter: (field: DataViewField) => ['bytes', 'extension', '_id', '@timestamp'].includes(field.name), - }) - ); + }, + }); await waitForNextUpdate(); @@ -167,20 +288,22 @@ describe('UnifiedFieldList useGroupedFields()', () => { ).toStrictEqual([ 'SpecialFields-0', 'SelectedFields-4', + 'PopularFields-0', 'AvailableFields-25', + 'UnmappedFields-0', 'EmptyFields-0', 'MetaFields-3', ]); }); it('should work correctly for text-based queries (no data view)', async () => { - const { result } = renderHook(() => - useGroupedFields({ + const { result } = renderHook(useGroupedFields, { + initialProps: { dataViewId: null, - allFields, + allFields: allFieldsIncludingUnmapped, services: mockedServices, - }) - ); + }, + }); const fieldGroups = result.current.fieldGroups; @@ -188,24 +311,36 @@ describe('UnifiedFieldList useGroupedFields()', () => { Object.keys(fieldGroups!).map( (key) => `${key}-${fieldGroups![key as FieldsGroupNames]?.fields.length}` ) - ).toStrictEqual(['SpecialFields-0', 'SelectedFields-0', 'AvailableFields-28', 'MetaFields-0']); + ).toStrictEqual([ + 'SpecialFields-0', + 'SelectedFields-0', + 'PopularFields-0', + 'AvailableFields-56', // even unmapped fields fall into Available + 'UnmappedFields-0', + 'MetaFields-0', + ]); + + expect(result.current.fieldsExistenceStatus).toBe(ExistenceFetchStatus.succeeded); + expect(result.current.fieldsExistInIndex).toBe(true); }); it('should work correctly when details are overwritten', async () => { - const { result, waitForNextUpdate } = renderHook(() => - useGroupedFields({ + const onOverrideFieldGroupDetails: GroupedFieldsParams['onOverrideFieldGroupDetails'] = + jest.fn((groupName) => { + if (groupName === FieldsGroupNames.SelectedFields) { + return { + helpText: 'test', + }; + } + }); + const { result, waitForNextUpdate } = renderHook(useGroupedFields, { + initialProps: { dataViewId: dataView.id!, allFields, services: mockedServices, - onOverrideFieldGroupDetails: (groupName) => { - if (groupName === FieldsGroupNames.SelectedFields) { - return { - helpText: 'test', - }; - } - }, - }) - ); + onOverrideFieldGroupDetails, + }, + }); await waitForNextUpdate(); @@ -213,6 +348,7 @@ describe('UnifiedFieldList useGroupedFields()', () => { expect(fieldGroups[FieldsGroupNames.SelectedFields]?.helpText).toBe('test'); expect(fieldGroups[FieldsGroupNames.AvailableFields]?.helpText).not.toBe('test'); + expect(onOverrideFieldGroupDetails).toHaveBeenCalled(); }); it('should work correctly when changing a data view and existence info is available only for one of them', async () => { @@ -248,11 +384,16 @@ describe('UnifiedFieldList useGroupedFields()', () => { ).toStrictEqual([ 'SpecialFields-0', 'SelectedFields-0', + 'PopularFields-0', 'AvailableFields-2', + 'UnmappedFields-0', 'EmptyFields-23', 'MetaFields-3', ]); + expect(result.current.fieldsExistenceStatus).toBe(ExistenceFetchStatus.succeeded); + expect(result.current.fieldsExistInIndex).toBe(true); + rerender({ ...props, dataViewId: anotherDataView.id!, @@ -267,6 +408,133 @@ describe('UnifiedFieldList useGroupedFields()', () => { Object.keys(fieldGroups!).map( (key) => `${key}-${fieldGroups![key as FieldsGroupNames]?.fields.length}` ) - ).toStrictEqual(['SpecialFields-0', 'SelectedFields-0', 'AvailableFields-8', 'MetaFields-0']); + ).toStrictEqual([ + 'SpecialFields-0', + 'SelectedFields-0', + 'PopularFields-0', + 'AvailableFields-8', + 'UnmappedFields-0', + 'MetaFields-0', + ]); + + expect(result.current.fieldsExistenceStatus).toBe(ExistenceFetchStatus.unknown); + expect(result.current.fieldsExistInIndex).toBe(true); + }); + + it('should work correctly when popular fields limit is present', async () => { + // `bytes` is popular, but we are skipping it here to test that it would not be shown under Popular and Available + const onSupportedFieldFilter = jest.fn((field) => field.name !== 'bytes'); + + const { result, waitForNextUpdate } = renderHook(useGroupedFields, { + initialProps: { + dataViewId: dataView.id!, + allFields, + popularFieldsLimit: 10, + services: mockedServices, + onSupportedFieldFilter, + }, + }); + + await waitForNextUpdate(); + + const fieldGroups = result.current.fieldGroups; + + expect( + Object.keys(fieldGroups!).map( + (key) => `${key}-${fieldGroups![key as FieldsGroupNames]?.fields.length}` + ) + ).toStrictEqual([ + 'SpecialFields-0', + 'SelectedFields-0', + 'PopularFields-3', + 'AvailableFields-24', + 'UnmappedFields-0', + 'EmptyFields-0', + 'MetaFields-3', + ]); + + expect(fieldGroups.PopularFields?.fields.map((field) => field.name).join(',')).toBe( + '@timestamp,time,ssl' + ); + }); + + it('should work correctly when global filters are set', async () => { + const { result, waitForNextUpdate } = renderHook(useGroupedFields, { + initialProps: { + dataViewId: dataView.id!, + allFields: [], + isAffectedByGlobalFilter: true, + services: mockedServices, + }, + }); + + await waitForNextUpdate(); + + const fieldGroups = result.current.fieldGroups; + expect(fieldGroups).toMatchSnapshot(); + }); + + it('should work correctly and show unmapped fields separately', async () => { + const { result, waitForNextUpdate } = renderHook(useGroupedFields, { + initialProps: { + dataViewId: dataView.id!, + allFields: allFieldsIncludingUnmapped, + services: mockedServices, + }, + }); + + await waitForNextUpdate(); + + const fieldGroups = result.current.fieldGroups; + + expect( + Object.keys(fieldGroups!).map( + (key) => `${key}-${fieldGroups![key as FieldsGroupNames]?.fields.length}` + ) + ).toStrictEqual([ + 'SpecialFields-0', + 'SelectedFields-0', + 'PopularFields-0', + 'AvailableFields-25', + 'UnmappedFields-28', + 'EmptyFields-0', + 'MetaFields-3', + ]); + }); + + it('should work correctly when custom selected fields are provided', async () => { + const customSortedFields = [ + allFieldsIncludingUnmapped[allFieldsIncludingUnmapped.length - 1], + allFields[2], + allFields[0], + ]; + const { result, waitForNextUpdate } = renderHook(useGroupedFields, { + initialProps: { + dataViewId: dataView.id!, + allFields, + sortedSelectedFields: customSortedFields, + services: mockedServices, + }, + }); + + await waitForNextUpdate(); + + const fieldGroups = result.current.fieldGroups; + + expect( + Object.keys(fieldGroups!).map( + (key) => `${key}-${fieldGroups![key as FieldsGroupNames]?.fields.length}` + ) + ).toStrictEqual([ + 'SpecialFields-0', + 'SelectedFields-3', + 'PopularFields-0', + 'AvailableFields-25', + 'UnmappedFields-0', + 'EmptyFields-0', + 'MetaFields-3', + ]); + + expect(fieldGroups.SelectedFields?.fields).toBe(customSortedFields); }); }); diff --git a/src/plugins/unified_field_list/public/hooks/use_grouped_fields.ts b/src/plugins/unified_field_list/public/hooks/use_grouped_fields.ts index cfa5407a238cc..39d1258ee62d8 100644 --- a/src/plugins/unified_field_list/public/hooks/use_grouped_fields.ts +++ b/src/plugins/unified_field_list/public/hooks/use_grouped_fields.ts @@ -17,16 +17,20 @@ import { type FieldsGroup, type FieldListItem, FieldsGroupNames, + ExistenceFetchStatus, } from '../types'; import { type ExistingFieldsReader } from './use_existing_fields'; export interface GroupedFieldsParams { dataViewId: string | null; // `null` is for text-based queries - allFields: T[]; + allFields: T[] | null; // `null` is for loading indicator services: { dataViews: DataViewsContract; }; - fieldsExistenceReader?: ExistingFieldsReader; + fieldsExistenceReader?: ExistingFieldsReader; // use `undefined` for text-based queries + isAffectedByGlobalFilter?: boolean; + popularFieldsLimit?: number; + sortedSelectedFields?: T[]; onOverrideFieldGroupDetails?: ( groupName: FieldsGroupNames ) => Partial | undefined | null; @@ -37,6 +41,9 @@ export interface GroupedFieldsParams { export interface GroupedFieldsResult { fieldGroups: FieldListGroups; + scrollToTopResetCounter: number; + fieldsExistenceStatus: ExistenceFetchStatus; + fieldsExistInIndex: boolean; } export function useGroupedFields({ @@ -44,12 +51,16 @@ export function useGroupedFields({ allFields, services, fieldsExistenceReader, + isAffectedByGlobalFilter = false, + popularFieldsLimit, + sortedSelectedFields, onOverrideFieldGroupDetails, onSupportedFieldFilter, onSelectedFieldFilter, onFilterField, }: GroupedFieldsParams): GroupedFieldsResult { const [dataView, setDataView] = useState(null); + const isAffectedByTimeFilter = Boolean(dataView?.timeFieldName); const fieldsExistenceInfoUnavailable: boolean = dataViewId ? fieldsExistenceReader?.isFieldsExistenceInfoUnavailable(dataViewId) ?? false : true; @@ -68,33 +79,59 @@ export function useGroupedFields({ // if field existence information changed, reload the data view too }, [dataViewId, services.dataViews, setDataView, hasFieldDataHandler]); + // important when switching from a known dataViewId to no data view (like in text-based queries) + useEffect(() => { + if (dataView && !dataViewId) { + setDataView(null); + } + }, [dataView, setDataView, dataViewId]); + + // eslint-disable-next-line react-hooks/exhaustive-deps + const scrollToTopResetCounter: number = useMemo(() => Date.now(), [dataViewId, onFilterField]); + const unfilteredFieldGroups: FieldListGroups = useMemo(() => { const containsData = (field: T) => { - if (!dataViewId || !dataView) { - return true; - } - const overallField = dataView.getFieldByName?.(field.name); - return Boolean(overallField && hasFieldDataHandler(dataViewId, overallField.name)); + return dataViewId ? hasFieldDataHandler(dataViewId, field.name) : true; }; - const fields = allFields || []; - const allSupportedTypesFields = onSupportedFieldFilter - ? fields.filter(onSupportedFieldFilter) - : fields; - const sortedFields = [...allSupportedTypesFields].sort(sortFields); + const selectedFields = sortedSelectedFields || []; + const sortedFields = [...(allFields || [])].sort(sortFields); const groupedFields = { ...getDefaultFieldGroups(), ...groupBy(sortedFields, (field) => { + if (!sortedSelectedFields && onSelectedFieldFilter && onSelectedFieldFilter(field)) { + selectedFields.push(field); + } + if (onSupportedFieldFilter && !onSupportedFieldFilter(field)) { + return 'skippedFields'; + } if (field.type === 'document') { return 'specialFields'; - } else if (dataView?.metaFields?.includes(field.name)) { + } + if (dataView?.metaFields?.includes(field.name)) { return 'metaFields'; - } else if (containsData(field)) { + } + if (dataView?.getFieldByName && !dataView.getFieldByName(field.name)) { + return 'unmappedFields'; + } + if (containsData(field) || fieldsExistenceInfoUnavailable) { return 'availableFields'; - } else return 'emptyFields'; + } + return 'emptyFields'; }), }; - const selectedFields = onSelectedFieldFilter ? sortedFields.filter(onSelectedFieldFilter) : []; + + const popularFields = popularFieldsLimit + ? sortedFields + .filter( + (field) => + field.count && + field.type !== '_source' && + (!onSupportedFieldFilter || onSupportedFieldFilter(field)) + ) + .sort((a: T, b: T) => (b.count || 0) - (a.count || 0)) // sort by popularity score + .slice(0, popularFieldsLimit) + : []; let fieldGroupDefinitions: FieldListGroups = { SpecialFields: { @@ -115,8 +152,25 @@ export function useGroupedFields({ title: i18n.translate('unifiedFieldList.useGroupedFields.selectedFieldsLabel', { defaultMessage: 'Selected fields', }), - isAffectedByGlobalFilter: false, - isAffectedByTimeFilter: true, + isAffectedByGlobalFilter, + isAffectedByTimeFilter, + hideDetails: false, + hideIfEmpty: true, + }, + PopularFields: { + fields: popularFields, + fieldCount: popularFields.length, + isInitiallyOpen: true, + showInAccordion: true, + title: i18n.translate('unifiedFieldList.useGroupedFields.popularFieldsLabel', { + defaultMessage: 'Popular fields', + }), + helpText: i18n.translate('unifiedFieldList.useGroupedFields.popularFieldsLabelHelp', { + defaultMessage: + 'Fields that your organization frequently uses, from most to least popular.', + }), + isAffectedByGlobalFilter, + isAffectedByTimeFilter, hideDetails: false, hideIfEmpty: true, }, @@ -133,8 +187,8 @@ export function useGroupedFields({ : i18n.translate('unifiedFieldList.useGroupedFields.availableFieldsLabel', { defaultMessage: 'Available fields', }), - isAffectedByGlobalFilter: false, - isAffectedByTimeFilter: true, + isAffectedByGlobalFilter, + isAffectedByTimeFilter, // Show details on timeout but not failure // hideDetails: fieldsExistenceInfoUnavailable && !existenceFetchTimeout, // TODO: is this check still necessary? hideDetails: fieldsExistenceInfoUnavailable, @@ -145,6 +199,22 @@ export function useGroupedFields({ } ), }, + UnmappedFields: { + fields: groupedFields.unmappedFields, + fieldCount: groupedFields.unmappedFields.length, + isAffectedByGlobalFilter, + isAffectedByTimeFilter, + isInitiallyOpen: false, + showInAccordion: true, + hideDetails: false, + hideIfEmpty: true, + title: i18n.translate('unifiedFieldList.useGroupedFields.unmappedFieldsLabel', { + defaultMessage: 'Unmapped fields', + }), + helpText: i18n.translate('unifiedFieldList.useGroupedFields.unmappedFieldsLabelHelp', { + defaultMessage: "Fields that aren't explicitly mapped to a field data type.", + }), + }, EmptyFields: { fields: groupedFields.emptyFields, fieldCount: groupedFields.emptyFields.length, @@ -157,15 +227,15 @@ export function useGroupedFields({ title: i18n.translate('unifiedFieldList.useGroupedFields.emptyFieldsLabel', { defaultMessage: 'Empty fields', }), + helpText: i18n.translate('unifiedFieldList.useGroupedFields.emptyFieldsLabelHelp', { + defaultMessage: "Fields that don't have any values based on your filters.", + }), defaultNoFieldsMessage: i18n.translate( 'unifiedFieldList.useGroupedFields.noEmptyDataLabel', { defaultMessage: `There are no empty fields.`, } ), - helpText: i18n.translate('unifiedFieldList.useGroupedFields.emptyFieldsLabelHelp', { - defaultMessage: 'Empty fields did not contain any values based on your filters.', - }), }, MetaFields: { fields: groupedFields.metaFields, @@ -220,6 +290,10 @@ export function useGroupedFields({ dataViewId, hasFieldDataHandler, fieldsExistenceInfoUnavailable, + isAffectedByGlobalFilter, + isAffectedByTimeFilter, + popularFieldsLimit, + sortedSelectedFields, ]); const fieldGroups: FieldListGroups = useMemo(() => { @@ -235,22 +309,39 @@ export function useGroupedFields({ ) as FieldListGroups; }, [unfilteredFieldGroups, onFilterField]); - return useMemo( - () => ({ + const hasDataLoaded = Boolean(allFields); + const allFieldsLength = allFields?.length; + + const fieldsExistInIndex = useMemo(() => { + return dataViewId ? Boolean(allFieldsLength) : true; + }, [dataViewId, allFieldsLength]); + + const fieldsExistenceStatus = useMemo(() => { + if (!hasDataLoaded) { + return ExistenceFetchStatus.unknown; // to show loading indicator in the list + } + if (!dataViewId || !fieldsExistenceReader) { + // ex. for text-based queries + return ExistenceFetchStatus.succeeded; + } + return fieldsExistenceReader.getFieldsExistenceStatus(dataViewId); + }, [dataViewId, hasDataLoaded, fieldsExistenceReader]); + + return useMemo(() => { + return { fieldGroups, - }), - [fieldGroups] - ); + scrollToTopResetCounter, + fieldsExistInIndex, + fieldsExistenceStatus, + }; + }, [fieldGroups, scrollToTopResetCounter, fieldsExistInIndex, fieldsExistenceStatus]); } +const collator = new Intl.Collator(undefined, { + sensitivity: 'base', +}); function sortFields(fieldA: T, fieldB: T) { - return (fieldA.displayName || fieldA.name).localeCompare( - fieldB.displayName || fieldB.name, - undefined, - { - sensitivity: 'base', - } - ); + return collator.compare(fieldA.displayName || fieldA.name, fieldB.displayName || fieldB.name); } function hasFieldDataByDefault(): boolean { @@ -263,5 +354,7 @@ function getDefaultFieldGroups() { availableFields: [], emptyFields: [], metaFields: [], + unmappedFields: [], + skippedFields: [], }; } diff --git a/src/plugins/unified_field_list/public/hooks/use_query_subscriber.ts b/src/plugins/unified_field_list/public/hooks/use_query_subscriber.ts index 9b42db6301f8f..44101d206a2de 100644 --- a/src/plugins/unified_field_list/public/hooks/use_query_subscriber.ts +++ b/src/plugins/unified_field_list/public/hooks/use_query_subscriber.ts @@ -9,6 +9,7 @@ import { useEffect, useState } from 'react'; import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; import type { AggregateQuery, Query, Filter } from '@kbn/es-query'; +import { getResolvedDateRange } from '../utils/get_resolved_date_range'; /** * Hook params @@ -23,32 +24,68 @@ export interface QuerySubscriberParams { export interface QuerySubscriberResult { query: Query | AggregateQuery | undefined; filters: Filter[] | undefined; + fromDate: string | undefined; + toDate: string | undefined; } /** - * Memorizes current query and filters + * Memorizes current query, filters and absolute date range * @param data + * @public */ export const useQuerySubscriber = ({ data }: QuerySubscriberParams) => { + const timefilter = data.query.timefilter.timefilter; const [result, setResult] = useState(() => { const state = data.query.getState(); + const dateRange = getResolvedDateRange(timefilter); return { query: state?.query, filters: state?.filters, + fromDate: dateRange.fromDate, + toDate: dateRange.toDate, }; }); useEffect(() => { - const subscription = data.query.state$.subscribe(({ state }) => { + const subscription = data.search.session.state$.subscribe((sessionState) => { + const dateRange = getResolvedDateRange(timefilter); setResult((prevState) => ({ ...prevState, - query: state.query, - filters: state.filters, + fromDate: dateRange.fromDate, + toDate: dateRange.toDate, })); }); + return () => subscription.unsubscribe(); + }, [setResult, timefilter, data.search.session.state$]); + + useEffect(() => { + const subscription = data.query.state$.subscribe(({ state, changes }) => { + if (changes.query || changes.filters) { + setResult((prevState) => ({ + ...prevState, + query: state.query, + filters: state.filters, + })); + } + }); + return () => subscription.unsubscribe(); }, [setResult, data.query.state$]); return result; }; + +/** + * Checks if query result is ready to be used + * @param result + * @public + */ +export const hasQuerySubscriberData = ( + result: QuerySubscriberResult +): result is { + query: Query | AggregateQuery; + filters: Filter[]; + fromDate: string; + toDate: string; +} => Boolean(result.query && result.filters && result.fromDate && result.toDate); diff --git a/src/plugins/unified_field_list/public/index.ts b/src/plugins/unified_field_list/public/index.ts index e1a315401e0bc..68fddef0ffc16 100755 --- a/src/plugins/unified_field_list/public/index.ts +++ b/src/plugins/unified_field_list/public/index.ts @@ -76,6 +76,7 @@ export { export { useQuerySubscriber, + hasQuerySubscriberData, type QuerySubscriberResult, type QuerySubscriberParams, } from './hooks/use_query_subscriber'; diff --git a/src/plugins/unified_field_list/public/types.ts b/src/plugins/unified_field_list/public/types.ts index d2c80286f8dea..c28452ebc6f25 100755 --- a/src/plugins/unified_field_list/public/types.ts +++ b/src/plugins/unified_field_list/public/types.ts @@ -29,14 +29,17 @@ export interface FieldListItem { name: DataViewField['name']; type?: DataViewField['type']; displayName?: DataViewField['displayName']; + count?: DataViewField['count']; } export enum FieldsGroupNames { SpecialFields = 'SpecialFields', SelectedFields = 'SelectedFields', + PopularFields = 'PopularFields', AvailableFields = 'AvailableFields', EmptyFields = 'EmptyFields', MetaFields = 'MetaFields', + UnmappedFields = 'UnmappedFields', } export interface FieldsGroupDetails { diff --git a/src/plugins/unified_field_list/public/utils/get_resolved_date_range.ts b/src/plugins/unified_field_list/public/utils/get_resolved_date_range.ts new file mode 100644 index 0000000000000..3939c49d7f514 --- /dev/null +++ b/src/plugins/unified_field_list/public/utils/get_resolved_date_range.ts @@ -0,0 +1,22 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { type TimefilterContract } from '@kbn/data-plugin/public'; + +/** + * Get resolved time range by using now provider + * @param timefilter + */ +export const getResolvedDateRange = (timefilter: TimefilterContract) => { + const { from, to } = timefilter.getTime(); + const { min, max } = timefilter.calculateBounds({ + from, + to, + }); + return { fromDate: min?.toISOString() || from, toDate: max?.toISOString() || to }; +}; diff --git a/src/plugins/unified_histogram/kibana.json b/src/plugins/unified_histogram/kibana.json index f89f9c9d4c714..5be043637ed33 100755 --- a/src/plugins/unified_histogram/kibana.json +++ b/src/plugins/unified_histogram/kibana.json @@ -11,5 +11,5 @@ "ui": true, "requiredPlugins": [], "optionalPlugins": [], - "requiredBundles": ["charts", "data"] + "requiredBundles": ["data", "dataViews", "embeddable", "kibanaUtils", "inspector"] } diff --git a/src/plugins/unified_histogram/public/__mocks__/data_view_with_timefield.ts b/src/plugins/unified_histogram/public/__mocks__/data_view_with_timefield.ts index 158d697d67c71..b0ec2fcf84ebb 100644 --- a/src/plugins/unified_histogram/public/__mocks__/data_view_with_timefield.ts +++ b/src/plugins/unified_histogram/public/__mocks__/data_view_with_timefield.ts @@ -12,12 +12,14 @@ import { buildDataViewMock } from './data_view'; const fields = [ { name: '_index', + displayName: '_index', type: 'string', scripted: false, filterable: true, }, { name: 'timestamp', + displayName: 'timestamp', type: 'date', scripted: false, filterable: true, @@ -26,12 +28,14 @@ const fields = [ }, { name: 'message', + displayName: 'message', type: 'string', scripted: false, filterable: false, }, { name: 'extension', + displayName: 'extension', type: 'string', scripted: false, filterable: true, @@ -39,6 +43,7 @@ const fields = [ }, { name: 'bytes', + displayName: 'bytes', type: 'number', scripted: false, filterable: true, @@ -46,6 +51,7 @@ const fields = [ }, { name: 'scripted', + displayName: 'scripted', type: 'number', scripted: true, filterable: false, diff --git a/src/plugins/unified_histogram/public/__mocks__/services.ts b/src/plugins/unified_histogram/public/__mocks__/services.ts index e827596d88feb..1ce16ad8fae85 100644 --- a/src/plugins/unified_histogram/public/__mocks__/services.ts +++ b/src/plugins/unified_histogram/public/__mocks__/services.ts @@ -25,4 +25,5 @@ export const unifiedHistogramServicesMock = { useChartsTheme: jest.fn(() => EUI_CHARTS_THEME_LIGHT.theme), useChartsBaseTheme: jest.fn(() => EUI_CHARTS_THEME_LIGHT.theme), }, + lens: { EmbeddableComponent: jest.fn(() => null) }, } as unknown as UnifiedHistogramServices; diff --git a/src/plugins/unified_histogram/public/chart/breakdown_field_selector.test.tsx b/src/plugins/unified_histogram/public/chart/breakdown_field_selector.test.tsx new file mode 100644 index 0000000000000..2b6b8bd7c537f --- /dev/null +++ b/src/plugins/unified_histogram/public/chart/breakdown_field_selector.test.tsx @@ -0,0 +1,73 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 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 { EuiComboBox } from '@elastic/eui'; +import { mountWithIntl } from '@kbn/test-jest-helpers'; +import React from 'react'; +import { UnifiedHistogramBreakdownContext } from '..'; +import { dataViewWithTimefieldMock } from '../__mocks__/data_view_with_timefield'; +import { BreakdownFieldSelector } from './breakdown_field_selector'; +import { fieldSupportsBreakdown } from './field_supports_breakdown'; + +describe('BreakdownFieldSelector', () => { + it('should pass fields that support breakdown as options to the EuiComboBox', () => { + const onBreakdownFieldChange = jest.fn(); + const breakdown: UnifiedHistogramBreakdownContext = { + field: undefined, + }; + const wrapper = mountWithIntl( + + ); + const comboBox = wrapper.find(EuiComboBox); + expect(comboBox.prop('options')).toEqual( + dataViewWithTimefieldMock.fields + .filter(fieldSupportsBreakdown) + .map((field) => ({ label: field.displayName, value: field.name })) + .sort((a, b) => a.label.toLowerCase().localeCompare(b.label.toLowerCase())) + ); + }); + + it('should pass selectedOptions to the EuiComboBox if breakdown.field is defined', () => { + const onBreakdownFieldChange = jest.fn(); + const field = dataViewWithTimefieldMock.fields.find((f) => f.name === 'extension')!; + const breakdown: UnifiedHistogramBreakdownContext = { field }; + const wrapper = mountWithIntl( + + ); + const comboBox = wrapper.find(EuiComboBox); + expect(comboBox.prop('selectedOptions')).toEqual([ + { label: field.displayName, value: field.name }, + ]); + }); + + it('should call onBreakdownFieldChange with the selected field when the user selects a field', () => { + const onBreakdownFieldChange = jest.fn(); + const breakdown: UnifiedHistogramBreakdownContext = { + field: undefined, + }; + const wrapper = mountWithIntl( + + ); + const comboBox = wrapper.find(EuiComboBox); + const selectedField = dataViewWithTimefieldMock.fields.find((f) => f.name === 'extension')!; + comboBox.prop('onChange')!([{ label: selectedField.displayName, value: selectedField.name }]); + expect(onBreakdownFieldChange).toHaveBeenCalledWith(selectedField); + }); +}); diff --git a/src/plugins/unified_histogram/public/chart/breakdown_field_selector.tsx b/src/plugins/unified_histogram/public/chart/breakdown_field_selector.tsx new file mode 100644 index 0000000000000..ef2a14e4423b6 --- /dev/null +++ b/src/plugins/unified_histogram/public/chart/breakdown_field_selector.tsx @@ -0,0 +1,89 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 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 { EuiComboBox, EuiComboBoxOptionOption, EuiToolTip, useEuiTheme } from '@elastic/eui'; +import { css } from '@emotion/react'; +import { DataView, DataViewField } from '@kbn/data-views-plugin/common'; +import { i18n } from '@kbn/i18n'; +import React, { useCallback, useState } from 'react'; +import { UnifiedHistogramBreakdownContext } from '../types'; +import { fieldSupportsBreakdown } from './field_supports_breakdown'; + +export interface BreakdownFieldSelectorProps { + dataView: DataView; + breakdown: UnifiedHistogramBreakdownContext; + onBreakdownFieldChange?: (breakdownField: DataViewField | undefined) => void; +} + +export const BreakdownFieldSelector = ({ + dataView, + breakdown, + onBreakdownFieldChange, +}: BreakdownFieldSelectorProps) => { + const fieldOptions = dataView.fields + .filter(fieldSupportsBreakdown) + .map((field) => ({ label: field.displayName, value: field.name })) + .sort((a, b) => a.label.toLowerCase().localeCompare(b.label.toLowerCase())); + + const selectedFields = breakdown.field + ? [{ label: breakdown.field.displayName, value: breakdown.field.name }] + : []; + + const onFieldChange = useCallback( + (newOptions: EuiComboBoxOptionOption[]) => { + const field = newOptions.length + ? dataView.fields.find((currentField) => currentField.name === newOptions[0].value) + : undefined; + + onBreakdownFieldChange?.(field); + }, + [dataView.fields, onBreakdownFieldChange] + ); + + const [fieldPopoverDisabled, setFieldPopoverDisabled] = useState(false); + const disableFieldPopover = useCallback(() => setFieldPopoverDisabled(true), []); + const enableFieldPopover = useCallback( + () => setTimeout(() => setFieldPopoverDisabled(false)), + [] + ); + + const { euiTheme } = useEuiTheme(); + const breakdownCss = css` + width: 100%; + max-width: ${euiTheme.base * 22}px; + `; + + return ( + + + + ); +}; diff --git a/src/plugins/unified_histogram/public/chart/build_chart_data.test.ts b/src/plugins/unified_histogram/public/chart/build_bucket_interval.test.ts similarity index 69% rename from src/plugins/unified_histogram/public/chart/build_chart_data.test.ts rename to src/plugins/unified_histogram/public/chart/build_bucket_interval.test.ts index 6c920a4a1a5ab..072f7a811babe 100644 --- a/src/plugins/unified_histogram/public/chart/build_chart_data.test.ts +++ b/src/plugins/unified_histogram/public/chart/build_bucket_interval.test.ts @@ -9,9 +9,9 @@ import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; import { dataViewWithTimefieldMock } from '../__mocks__/data_view_with_timefield'; import { calculateBounds } from '@kbn/data-plugin/public'; -import { buildChartData } from './build_chart_data'; +import { buildBucketInterval } from './build_bucket_interval'; -describe('buildChartData', () => { +describe('buildBucketInterval', () => { const getOptions = () => { const response = { took: 0, @@ -72,54 +72,29 @@ describe('buildChartData', () => { dataView, timeInterval: 'auto', response, + timeRange: { + from: '1991-03-29T08:04:00.694Z', + to: '2021-03-29T07:04:00.695Z', + }, }; }; - const expectedChartData = { - xAxisOrderedValues: [1664996400000, 1664998200000, 1665000000000, 1665001800000, 1665003600000], - xAxisFormat: { id: 'date', params: { pattern: 'HH:mm:ss.SSS' } }, - xAxisLabel: 'timestamp per 0 milliseconds', - yAxisFormat: { id: 'number' }, - ordered: { - date: true, - interval: 'P0D', - intervalESUnit: 'ms', - intervalESValue: 0, - min: '1991-03-29T08:04:00.694Z', - max: '2021-03-29T07:04:00.695Z', - }, - yAxisLabel: 'Count', - values: [ - { x: 1664996400000, y: 6 }, - { x: 1664998200000, y: 2 }, - { x: 1665000000000, y: 3 }, - { x: 1665001800000, y: 8 }, - { x: 1665003600000, y: 10 }, - ], - }; - - it('should return the correct data', () => { - const { bucketInterval, chartData } = buildChartData(getOptions()); - expect(bucketInterval!.toString()).toEqual('P0D'); - expect(JSON.stringify(chartData)).toEqual(JSON.stringify(expectedChartData)); - }); - it('should return an empty object if response or timeInterval is undefined', () => { expect( - buildChartData({ + buildBucketInterval({ ...getOptions(), response: undefined, timeInterval: undefined, }) ).toEqual({}); expect( - buildChartData({ + buildBucketInterval({ ...getOptions(), response: undefined, }) ).toEqual({}); expect( - buildChartData({ + buildBucketInterval({ ...getOptions(), timeInterval: undefined, }) diff --git a/src/plugins/unified_histogram/public/chart/build_chart_data.ts b/src/plugins/unified_histogram/public/chart/build_bucket_interval.ts similarity index 68% rename from src/plugins/unified_histogram/public/chart/build_chart_data.ts rename to src/plugins/unified_histogram/public/chart/build_bucket_interval.ts index 03b208802ac4d..b3c9671662dbc 100644 --- a/src/plugins/unified_histogram/public/chart/build_chart_data.ts +++ b/src/plugins/unified_histogram/public/chart/build_bucket_interval.ts @@ -9,42 +9,38 @@ import type { SearchResponse } from '@elastic/elasticsearch/lib/api/types'; import { DataPublicPluginStart, search, tabifyAggResponse } from '@kbn/data-plugin/public'; import type { DataView } from '@kbn/data-views-plugin/common'; +import type { TimeRange } from '@kbn/es-query'; import type { UnifiedHistogramBucketInterval } from '../types'; -import { buildPointSeriesData } from './build_point_series_data'; import { getChartAggConfigs } from './get_chart_agg_configs'; -import { getDimensions } from './get_dimensions'; /** * Convert the response from the chart request into a format that can be used * by the unified histogram chart. The returned object should be used to update - * {@link UnifiedHistogramChartContext.bucketInterval} and {@link UnifiedHistogramChartContext.data}. + * time range interval of histogram. */ -export const buildChartData = ({ +export const buildBucketInterval = ({ data, dataView, timeInterval, + timeRange, response, }: { data: DataPublicPluginStart; dataView: DataView; timeInterval?: string; + timeRange: TimeRange; response?: SearchResponse; }) => { if (!timeInterval || !response) { return {}; } - const chartAggConfigs = getChartAggConfigs({ dataView, timeInterval, data }); + const chartAggConfigs = getChartAggConfigs({ dataView, timeInterval, timeRange, data }); const bucketAggConfig = chartAggConfigs.aggs[1]; - const tabifiedData = tabifyAggResponse(chartAggConfigs, response); - const dimensions = getDimensions(chartAggConfigs, data); - const bucketInterval = search.aggs.isDateHistogramBucketAggConfig(bucketAggConfig) + + tabifyAggResponse(chartAggConfigs, response); + + return search.aggs.isDateHistogramBucketAggConfig(bucketAggConfig) ? (bucketAggConfig?.buckets?.getInterval() as UnifiedHistogramBucketInterval) : undefined; - const chartData = buildPointSeriesData(tabifiedData, dimensions!); - - return { - bucketInterval, - chartData, - }; }; diff --git a/src/plugins/unified_histogram/public/chart/build_point_series_data.test.ts b/src/plugins/unified_histogram/public/chart/build_point_series_data.test.ts deleted file mode 100644 index 3a7f81aa4cd40..0000000000000 --- a/src/plugins/unified_histogram/public/chart/build_point_series_data.test.ts +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { buildPointSeriesData } from './build_point_series_data'; -import moment from 'moment'; -import type { Unit } from '@kbn/datemath'; - -describe('buildPointSeriesData', () => { - test('with valid data', () => { - const table = { - type: 'datatable', - columns: [ - { - id: 'col-0-2', - name: 'order_date per 30 days', - meta: { - type: 'date', - field: 'order_date', - index: 'kibana_sample_data_ecommerce', - params: { id: 'date', params: { pattern: 'YYYY-MM-DD' } }, - source: 'esaggs', - sourceParams: { - dataViewId: 'ff959d40-b880-11e8-a6d9-e546fe2bba5f', - id: '2', - enabled: true, - type: 'date_histogram', - params: { - field: 'order_date', - timeRange: { from: 'now-15y', to: 'now' }, - useNormalizedEsInterval: true, - scaleMetricValues: false, - interval: 'auto', - used_interval: '30d', - drop_partials: false, - min_doc_count: 1, - extended_bounds: {}, - }, - schema: 'segment', - }, - }, - }, - { - id: 'col-1-1', - name: 'Count', - meta: { - type: 'number', - index: 'kibana_sample_data_ecommerce', - params: { id: 'number' }, - source: 'esaggs', - sourceParams: { - dataViewId: 'ff959d40-b880-11e8-a6d9-e546fe2bba5f', - id: '1', - enabled: true, - type: 'count', - params: {}, - schema: 'metric', - }, - }, - }, - ], - rows: [{ 'col-0-2': 1625176800000, 'col-1-1': 2139 }], - }; - const dimensions = { - x: { - accessor: 0, - label: 'order_date per 30 days', - format: { id: 'date', params: { pattern: 'YYYY-MM-DD' } }, - params: { - date: true, - interval: moment.duration(30, 'd'), - intervalESValue: 30, - intervalESUnit: 'd' as Unit, - format: 'YYYY-MM-DD', - bounds: { - min: moment('2006-07-29T11:08:13.078Z'), - max: moment('2021-07-29T11:08:13.078Z'), - }, - }, - }, - y: { accessor: 1, format: { id: 'number' }, label: 'Count' }, - } as const; - expect(buildPointSeriesData(table, dimensions)).toMatchInlineSnapshot(` - Object { - "ordered": Object { - "date": true, - "interval": "P30D", - "intervalESUnit": "d", - "intervalESValue": 30, - "max": "2021-07-29T11:08:13.078Z", - "min": "2006-07-29T11:08:13.078Z", - }, - "values": Array [ - Object { - "x": 1625176800000, - "y": 2139, - }, - ], - "xAxisFormat": Object { - "id": "date", - "params": Object { - "pattern": "YYYY-MM-DD", - }, - }, - "xAxisLabel": "order_date per 30 days", - "xAxisOrderedValues": Array [ - 1625176800000, - ], - "yAxisFormat": Object { - "id": "number", - }, - "yAxisLabel": "Count", - } - `); - }); -}); diff --git a/src/plugins/unified_histogram/public/chart/build_point_series_data.ts b/src/plugins/unified_histogram/public/chart/build_point_series_data.ts deleted file mode 100644 index dc9d97fd0708f..0000000000000 --- a/src/plugins/unified_histogram/public/chart/build_point_series_data.ts +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { uniq } from 'lodash'; -import type { UnifiedHistogramChartData, Dimensions, Table } from '../types'; - -export const buildPointSeriesData = ( - table: Table, - dimensions: Dimensions -): UnifiedHistogramChartData => { - const { x, y } = dimensions; - const xAccessor = table.columns[x.accessor].id; - const yAccessor = table.columns[y.accessor].id; - const chart = {} as UnifiedHistogramChartData; - - chart.xAxisOrderedValues = uniq(table.rows.map((r) => r[xAccessor] as number)); - chart.xAxisFormat = x.format; - chart.xAxisLabel = table.columns[x.accessor].name; - chart.yAxisFormat = y.format; - const { intervalESUnit, intervalESValue, interval, bounds } = x.params; - chart.ordered = { - date: true, - interval, - intervalESUnit, - intervalESValue, - min: bounds.min, - max: bounds.max, - }; - - chart.yAxisLabel = table.columns[y.accessor].name; - - chart.values = table.rows - .filter((row) => row && row[yAccessor] !== 'NaN') - .map((row) => ({ - x: row[xAccessor] as number, - y: row[yAccessor] as number, - })); - - return chart; -}; diff --git a/src/plugins/unified_histogram/public/chart/chart.test.tsx b/src/plugins/unified_histogram/public/chart/chart.test.tsx index 41de0687acfa6..21682cb919d3c 100644 --- a/src/plugins/unified_histogram/public/chart/chart.test.tsx +++ b/src/plugins/unified_histogram/public/chart/chart.test.tsx @@ -9,70 +9,50 @@ import React, { ReactElement } from 'react'; import { act } from 'react-dom/test-utils'; import { mountWithIntl } from '@kbn/test-jest-helpers'; -import type { UnifiedHistogramChartData, UnifiedHistogramFetchStatus } from '../types'; +import type { DataView } from '@kbn/data-views-plugin/public'; +import type { UnifiedHistogramFetchStatus } from '../types'; import { Chart } from './chart'; import type { ReactWrapper } from 'enzyme'; import { unifiedHistogramServicesMock } from '../__mocks__/services'; +import { searchSourceInstanceMock } from '@kbn/data-plugin/common/search/search_source/mocks'; +import { of } from 'rxjs'; import { HitsCounter } from '../hits_counter'; +import { dataViewWithTimefieldMock } from '../__mocks__/data_view_with_timefield'; +import { dataViewMock } from '../__mocks__/data_view'; +import { BreakdownFieldSelector } from './breakdown_field_selector'; +import { Histogram } from './histogram'; async function mountComponent({ noChart, noHits, + noBreakdown, chartHidden = false, appendHistogram, onEditVisualization = jest.fn(), + dataView = dataViewWithTimefieldMock, }: { noChart?: boolean; noHits?: boolean; + noBreakdown?: boolean; chartHidden?: boolean; appendHistogram?: ReactElement; + dataView?: DataView; onEditVisualization?: null | (() => void); } = {}) { const services = unifiedHistogramServicesMock; services.data.query.timefilter.timefilter.getAbsoluteTime = () => { return { from: '2020-05-14T11:05:13.590', to: '2020-05-14T11:20:13.590' }; }; - - const chartData = { - xAxisOrderedValues: [ - 1623880800000, 1623967200000, 1624053600000, 1624140000000, 1624226400000, 1624312800000, - 1624399200000, 1624485600000, 1624572000000, 1624658400000, 1624744800000, 1624831200000, - 1624917600000, 1625004000000, 1625090400000, - ], - xAxisFormat: { id: 'date', params: { pattern: 'YYYY-MM-DD' } }, - xAxisLabel: 'order_date per day', - yAxisFormat: { id: 'number' }, - ordered: { - date: true, - interval: { - asMilliseconds: jest.fn(), - }, - intervalESUnit: 'd', - intervalESValue: 1, - min: '2021-03-18T08:28:56.411Z', - max: '2021-07-01T07:28:56.411Z', - }, - yAxisLabel: 'Count', - values: [ - { x: 1623880800000, y: 134 }, - { x: 1623967200000, y: 152 }, - { x: 1624053600000, y: 141 }, - { x: 1624140000000, y: 138 }, - { x: 1624226400000, y: 142 }, - { x: 1624312800000, y: 157 }, - { x: 1624399200000, y: 149 }, - { x: 1624485600000, y: 146 }, - { x: 1624572000000, y: 170 }, - { x: 1624658400000, y: 137 }, - { x: 1624744800000, y: 150 }, - { x: 1624831200000, y: 144 }, - { x: 1624917600000, y: 147 }, - { x: 1625004000000, y: 137 }, - { x: 1625090400000, y: 66 }, - ], - } as unknown as UnifiedHistogramChartData; + (services.data.query.queryString.getDefaultQuery as jest.Mock).mockReturnValue({ + language: 'kuery', + query: '', + }); + (searchSourceInstanceMock.fetch$ as jest.Mock).mockImplementation( + jest.fn().mockReturnValue(of({ rawResponse: { hits: { total: noHits ? 0 : 2 } } })) + ); const props = { + dataView, services: unifiedHistogramServicesMock, hits: noHits ? undefined @@ -91,8 +71,8 @@ async function mountComponent({ description: 'test', scale: 2, }, - data: chartData, }, + breakdown: noBreakdown ? undefined : { field: undefined }, appendHistogram, onEditVisualization: onEditVisualization || undefined, onResetChartHeight: jest.fn(), @@ -105,7 +85,7 @@ async function mountComponent({ instance = mountWithIntl(); // wait for initial async loading to complete await new Promise((r) => setTimeout(r, 0)); - await instance.update(); + instance.update(); }); return instance; } @@ -158,13 +138,13 @@ describe('Chart', () => { const fn = jest.fn(); const component = await mountComponent({ onEditVisualization: fn }); await act(async () => { - await component + component .find('[data-test-subj="unifiedHistogramEditVisualization"]') .first() .simulate('click'); }); - - expect(fn).toHaveBeenCalled(); + const lensAttributes = component.find(Histogram).prop('lensAttributes'); + expect(fn).toHaveBeenCalledWith(lensAttributes); }); it('should render HitsCounter when hits is defined', async () => { @@ -182,4 +162,29 @@ describe('Chart', () => { const component = await mountComponent({ appendHistogram }); expect(component.find('[data-test-subj="appendHistogram"]').exists()).toBeTruthy(); }); + + it('should not render chart if data view is not time based', async () => { + const component = await mountComponent({ dataView: dataViewMock }); + expect(component.find('[data-test-subj="unifiedHistogramChart"]').exists()).toBeFalsy(); + }); + + it('should render chart if data view is time based', async () => { + const component = await mountComponent(); + expect(component.find('[data-test-subj="unifiedHistogramChart"]').exists()).toBeTruthy(); + }); + + it('should render BreakdownFieldSelector when chart is visible and breakdown is defined', async () => { + const component = await mountComponent(); + expect(component.find(BreakdownFieldSelector).exists()).toBeTruthy(); + }); + + it('should not render BreakdownFieldSelector when chart is hidden', async () => { + const component = await mountComponent({ chartHidden: true }); + expect(component.find(BreakdownFieldSelector).exists()).toBeFalsy(); + }); + + it('should not render BreakdownFieldSelector when chart is visible and breakdown is undefined', async () => { + const component = await mountComponent({ noBreakdown: true }); + expect(component.find(BreakdownFieldSelector).exists()).toBeFalsy(); + }); }); diff --git a/src/plugins/unified_histogram/public/chart/chart.tsx b/src/plugins/unified_histogram/public/chart/chart.tsx index 0f6c47f8a532e..b1970cd26e365 100644 --- a/src/plugins/unified_histogram/public/chart/chart.tsx +++ b/src/plugins/unified_histogram/public/chart/chart.tsx @@ -6,9 +6,8 @@ * Side Public License, v 1. */ -import type { ReactElement } from 'react'; -import React, { memo, useCallback, useEffect, useRef, useState } from 'react'; -import moment from 'moment'; +import { ReactElement, useMemo } from 'react'; +import React, { memo } from 'react'; import { EuiButtonIcon, EuiContextMenu, @@ -16,31 +15,48 @@ import { EuiFlexItem, EuiPopover, EuiToolTip, - useEuiBreakpoint, - useEuiTheme, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { css } from '@emotion/react'; +import { DataView, DataViewField, DataViewType } from '@kbn/data-views-plugin/public'; +import type { TypedLensByValueInput } from '@kbn/lens-plugin/public'; import { HitsCounter } from '../hits_counter'; import { Histogram } from './histogram'; import { useChartPanels } from './use_chart_panels'; import type { + UnifiedHistogramBreakdownContext, UnifiedHistogramChartContext, + UnifiedHistogramFetchStatus, UnifiedHistogramHitsContext, + UnifiedHistogramChartLoadEvent, + UnifiedHistogramRequestContext, UnifiedHistogramServices, } from '../types'; +import { BreakdownFieldSelector } from './breakdown_field_selector'; +import { useTotalHits } from './use_total_hits'; +import { useRequestParams } from './use_request_params'; +import { useChartStyles } from './use_chart_styles'; +import { useChartActions } from './use_chart_actions'; +import { useRefetchId } from './use_refetch_id'; +import { getLensAttributes } from './get_lens_attributes'; export interface ChartProps { className?: string; services: UnifiedHistogramServices; + dataView: DataView; + lastReloadRequestTime?: number; + request?: UnifiedHistogramRequestContext; hits?: UnifiedHistogramHitsContext; chart?: UnifiedHistogramChartContext; + breakdown?: UnifiedHistogramBreakdownContext; appendHitsCounter?: ReactElement; appendHistogram?: ReactElement; - onEditVisualization?: () => void; + onEditVisualization?: (lensAttributes: TypedLensByValueInput['attributes']) => void; onResetChartHeight?: () => void; onChartHiddenChange?: (chartHidden: boolean) => void; onTimeIntervalChange?: (timeInterval: string) => void; + onBreakdownFieldChange?: (breakdownField: DataViewField | undefined) => void; + onTotalHitsChange?: (status: UnifiedHistogramFetchStatus, result?: number | Error) => void; + onChartLoad?: (event: UnifiedHistogramChartLoadEvent) => void; } const HistogramMemoized = memo(Histogram); @@ -48,89 +64,124 @@ const HistogramMemoized = memo(Histogram); export function Chart({ className, services, + dataView, + lastReloadRequestTime, + request, hits, chart, + breakdown, appendHitsCounter, appendHistogram, - onEditVisualization, + onEditVisualization: originalOnEditVisualization, onResetChartHeight, onChartHiddenChange, onTimeIntervalChange, + onBreakdownFieldChange, + onTotalHitsChange, + onChartLoad, }: ChartProps) { - const { data } = services; - const [showChartOptionsPopover, setShowChartOptionsPopover] = useState(false); - - const chartRef = useRef<{ element: HTMLElement | null; moveFocus: boolean }>({ - element: null, - moveFocus: false, + const { + showChartOptionsPopover, + chartRef, + toggleChartOptions, + closeChartOptions, + toggleHideChart, + } = useChartActions({ + chart, + onChartHiddenChange, }); - const onShowChartOptions = useCallback(() => { - setShowChartOptionsPopover(!showChartOptionsPopover); - }, [showChartOptionsPopover]); + const panels = useChartPanels({ + chart, + toggleHideChart, + onTimeIntervalChange, + closePopover: closeChartOptions, + onResetChartHeight, + }); - const closeChartOptions = useCallback(() => { - setShowChartOptionsPopover(false); - }, [setShowChartOptionsPopover]); + const chartVisible = !!( + chart && + !chart.hidden && + dataView.id && + dataView.type !== DataViewType.ROLLUP && + dataView.isTimeBased() + ); - useEffect(() => { - if (chartRef.current.moveFocus && chartRef.current.element) { - chartRef.current.element.focus(); - } - }, [chart?.hidden]); + const { filters, query, relativeTimeRange } = useRequestParams({ + services, + lastReloadRequestTime, + request, + }); - const toggleHideChart = useCallback(() => { - const chartHidden = !chart?.hidden; - chartRef.current.moveFocus = !chartHidden; - onChartHiddenChange?.(chartHidden); - }, [chart?.hidden, onChartHiddenChange]); + const refetchId = useRefetchId({ + dataView, + lastReloadRequestTime, + request, + hits, + chart, + chartVisible, + breakdown, + filters, + query, + relativeTimeRange, + }); - const timefilterUpdateHandler = useCallback( - (ranges: { from: number; to: number }) => { - data.query.timefilter.timefilter.setTime({ - from: moment(ranges.from).toISOString(), - to: moment(ranges.to).toISOString(), - mode: 'absolute', - }); - }, - [data] + // We need to update the absolute time range whenever the refetchId changes + const timeRange = useMemo( + () => services.data.query.timefilter.timefilter.getAbsoluteTime(), + // eslint-disable-next-line react-hooks/exhaustive-deps + [services.data.query.timefilter.timefilter, refetchId] ); - const panels = useChartPanels({ + useTotalHits({ + services, + dataView, + lastReloadRequestTime, + request, + hits, chart, - toggleHideChart, - onTimeIntervalChange: (timeInterval) => onTimeIntervalChange?.(timeInterval), - closePopover: () => setShowChartOptionsPopover(false), - onResetChartHeight, + chartVisible, + breakdown, + filters, + query, + timeRange, + refetchId, + onTotalHitsChange, }); - const { euiTheme } = useEuiTheme(); - const resultCountCss = css` - padding: ${euiTheme.size.s}; - min-height: ${euiTheme.base * 3}px; - `; - const resultCountTitleCss = css` - ${useEuiBreakpoint(['xs', 's'])} { - margin-bottom: 0 !important; - } - `; - const resultCountToggleCss = css` - ${useEuiBreakpoint(['xs', 's'])} { - align-items: flex-end; - } - `; - const timechartCss = css` - flex-grow: 1; - display: flex; - flex-direction: column; - position: relative; + const { + resultCountCss, + resultCountInnerCss, + resultCountTitleCss, + resultCountToggleCss, + histogramCss, + breakdownFieldSelectorGroupCss, + breakdownFieldSelectorItemCss, + chartToolButtonCss, + } = useChartStyles(chartVisible); - // SASSTODO: the visualizing component should have an option or a modifier - .series > rect { - fill-opacity: 0.5; - stroke-width: 1; - } - `; + const lensAttributes = useMemo( + () => + getLensAttributes({ + title: chart?.title, + filters, + query, + dataView, + timeInterval: chart?.timeInterval, + breakdownField: breakdown?.field, + }), + [breakdown?.field, chart?.timeInterval, chart?.title, dataView, filters, query] + ); + + const onEditVisualization = useMemo( + () => + originalOnEditVisualization + ? () => { + originalOnEditVisualization(lensAttributes); + } + : undefined, + [lensAttributes, originalOnEditVisualization] + ); return ( - + } {chart && ( - - + + + {chartVisible && breakdown && ( + + + + )} {onEditVisualization && ( - + )} - + - {chart && !chart.hidden && ( + {chartVisible && (
    (chartRef.current.element = element)} @@ -212,12 +283,19 @@ export function Chart({ aria-label={i18n.translate('unifiedHistogram.histogramOfFoundDocumentsAriaLabel', { defaultMessage: 'Histogram of found documents', })} - css={timechartCss} + css={histogramCss} >
    {appendHistogram} diff --git a/src/plugins/unified_histogram/public/chart/consts.ts b/src/plugins/unified_histogram/public/chart/consts.ts new file mode 100644 index 0000000000000..d2af2ed4ee33a --- /dev/null +++ b/src/plugins/unified_histogram/public/chart/consts.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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export const REQUEST_DEBOUNCE_MS = 100; diff --git a/src/plugins/unified_histogram/public/chart/field_supports_breakdown.test.ts b/src/plugins/unified_histogram/public/chart/field_supports_breakdown.test.ts new file mode 100644 index 0000000000000..b38b42cf2a249 --- /dev/null +++ b/src/plugins/unified_histogram/public/chart/field_supports_breakdown.test.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 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 { fieldSupportsBreakdown } from './field_supports_breakdown'; + +describe('fieldSupportsBreakdown', () => { + it('should return false if field is not aggregatable', () => { + expect( + fieldSupportsBreakdown({ aggregatable: false, scripted: false, type: 'string' } as any) + ).toBe(false); + }); + + it('should return false if field is scripted', () => { + expect( + fieldSupportsBreakdown({ aggregatable: true, scripted: true, type: 'string' } as any) + ).toBe(false); + }); + + it('should return false if field type is not supported', () => { + expect( + fieldSupportsBreakdown({ aggregatable: true, scripted: false, type: 'unsupported' } as any) + ).toBe(false); + }); + + it('should return true if field is aggregatable and type is supported', () => { + expect( + fieldSupportsBreakdown({ aggregatable: true, scripted: false, type: 'string' } as any) + ).toBe(true); + }); +}); diff --git a/src/plugins/unified_histogram/public/chart/field_supports_breakdown.ts b/src/plugins/unified_histogram/public/chart/field_supports_breakdown.ts new file mode 100644 index 0000000000000..302a5950fefcb --- /dev/null +++ b/src/plugins/unified_histogram/public/chart/field_supports_breakdown.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 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 { DataViewField } from '@kbn/data-views-plugin/public'; + +const supportedTypes = new Set(['string', 'boolean', 'number', 'ip']); + +export const fieldSupportsBreakdown = (field: DataViewField) => + supportedTypes.has(field.type) && field.aggregatable && !field.scripted; diff --git a/src/plugins/unified_histogram/public/chart/get_chart_agg_config.test.ts b/src/plugins/unified_histogram/public/chart/get_chart_agg_config.test.ts index 3b4f470ba6119..ef5ce1b677153 100644 --- a/src/plugins/unified_histogram/public/chart/get_chart_agg_config.test.ts +++ b/src/plugins/unified_histogram/public/chart/get_chart_agg_config.test.ts @@ -14,7 +14,15 @@ describe('getChartAggConfigs', () => { test('is working', () => { const dataView = dataViewWithTimefieldMock; const dataMock = dataPluginMock.createStartContract(); - const aggsConfig = getChartAggConfigs({ dataView, timeInterval: 'auto', data: dataMock }); + const aggsConfig = getChartAggConfigs({ + dataView, + timeInterval: 'auto', + data: dataMock, + timeRange: { + from: '2022-10-05T16:00:00.000-03:00', + to: '2022-10-05T18:00:00.000-03:00', + }, + }); expect(aggsConfig!.aggs).toMatchInlineSnapshot(` Array [ @@ -38,6 +46,10 @@ describe('getChartAggConfigs', () => { "interval": "auto", "min_doc_count": 1, "scaleMetricValues": false, + "timeRange": Object { + "from": "2022-10-05T16:00:00.000-03:00", + "to": "2022-10-05T18:00:00.000-03:00", + }, "useNormalizedEsInterval": true, "used_interval": "0ms", }, diff --git a/src/plugins/unified_histogram/public/chart/get_chart_agg_configs.ts b/src/plugins/unified_histogram/public/chart/get_chart_agg_configs.ts index 93ef7f3dd9188..d68330a22a45d 100644 --- a/src/plugins/unified_histogram/public/chart/get_chart_agg_configs.ts +++ b/src/plugins/unified_histogram/public/chart/get_chart_agg_configs.ts @@ -8,6 +8,7 @@ import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; import type { DataView } from '@kbn/data-views-plugin/common'; +import type { TimeRange } from '@kbn/es-query'; /** * Helper function to get the agg configs required for the unified histogram chart request @@ -15,10 +16,12 @@ import type { DataView } from '@kbn/data-views-plugin/common'; export function getChartAggConfigs({ dataView, timeInterval, + timeRange, data, }: { dataView: DataView; timeInterval: string; + timeRange: TimeRange; data: DataPublicPluginStart; }) { const visStateAggs = [ @@ -32,7 +35,7 @@ export function getChartAggConfigs({ params: { field: dataView.timeFieldName!, interval: timeInterval, - timeRange: data.query.timefilter.timefilter.getTime(), + timeRange, }, }, ]; diff --git a/src/plugins/unified_histogram/public/chart/get_dimensions.test.ts b/src/plugins/unified_histogram/public/chart/get_dimensions.test.ts deleted file mode 100644 index fd26fa20ce793..0000000000000 --- a/src/plugins/unified_histogram/public/chart/get_dimensions.test.ts +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; -import { getDimensions } from './get_dimensions'; -import { dataViewWithTimefieldMock } from '../__mocks__/data_view_with_timefield'; -import { calculateBounds } from '@kbn/data-plugin/public'; -import { getChartAggConfigs } from './get_chart_agg_configs'; - -test('getDimensions', () => { - const dataView = dataViewWithTimefieldMock; - const dataMock = dataPluginMock.createStartContract(); - dataMock.query.timefilter.timefilter.getTime = () => { - return { from: '1991-03-29T08:04:00.694Z', to: '2021-03-29T07:04:00.695Z' }; - }; - dataMock.query.timefilter.timefilter.calculateBounds = (timeRange) => { - return calculateBounds(timeRange); - }; - const aggsConfig = getChartAggConfigs({ dataView, timeInterval: 'auto', data: dataMock }); - const actual = getDimensions(aggsConfig!, dataMock); - expect(actual).toMatchInlineSnapshot(` - Object { - "x": Object { - "accessor": 0, - "format": Object { - "id": "date", - "params": Object { - "pattern": "HH:mm:ss.SSS", - }, - }, - "label": "timestamp per 0 milliseconds", - "params": Object { - "bounds": Object { - "max": "2021-03-29T07:04:00.695Z", - "min": "1991-03-29T08:04:00.694Z", - }, - "date": true, - "format": "HH:mm:ss.SSS", - "interval": "P0D", - "intervalESUnit": "ms", - "intervalESValue": 0, - }, - }, - "y": Object { - "accessor": 1, - "format": Object { - "id": "number", - }, - "label": "Count", - }, - } - `); -}); diff --git a/src/plugins/unified_histogram/public/chart/get_dimensions.ts b/src/plugins/unified_histogram/public/chart/get_dimensions.ts deleted file mode 100644 index 94ed3d4540d21..0000000000000 --- a/src/plugins/unified_histogram/public/chart/get_dimensions.ts +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import moment from 'moment'; -import dateMath from '@kbn/datemath'; -import { DataPublicPluginStart, search, IAggConfigs } from '@kbn/data-plugin/public'; -import type { Dimensions, HistogramParamsBounds } from '../types'; - -export function getDimensions( - aggs: IAggConfigs, - data: DataPublicPluginStart -): Dimensions | undefined { - const [metric, agg] = aggs.aggs; - const { from, to } = data.query.timefilter.timefilter.getTime(); - agg.params.timeRange = { - from: dateMath.parse(from), - to: dateMath.parse(to, { roundUp: true }), - }; - const bounds = agg.params.timeRange - ? (data.query.timefilter.timefilter.calculateBounds( - agg.params.timeRange - ) as HistogramParamsBounds) - : null; - const buckets = search.aggs.isDateHistogramBucketAggConfig(agg) ? agg.buckets : undefined; - - if (!buckets || !bounds) { - return; - } - - const { esUnit, esValue } = buckets.getInterval(); - return { - x: { - accessor: 0, - label: agg.makeLabel(), - format: agg.toSerializedFieldFormat(), - params: { - date: true, - interval: moment.duration(esValue, esUnit), - intervalESValue: esValue, - intervalESUnit: esUnit, - format: buckets.getScaledDateFormat(), - bounds, - }, - }, - y: { - accessor: 1, - format: metric.toSerializedFieldFormat(), - label: metric.makeLabel(), - }, - }; -} diff --git a/src/plugins/unified_histogram/public/chart/get_lens_attributes.test.ts b/src/plugins/unified_histogram/public/chart/get_lens_attributes.test.ts new file mode 100644 index 0000000000000..3e0ac936a6573 --- /dev/null +++ b/src/plugins/unified_histogram/public/chart/get_lens_attributes.test.ts @@ -0,0 +1,480 @@ +/* + * Copyright 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 { getLensAttributes } from './get_lens_attributes'; +import { AggregateQuery, Filter, FilterStateStore, Query } from '@kbn/es-query'; +import type { DataView, DataViewField } from '@kbn/data-views-plugin/public'; +import { dataViewWithTimefieldMock } from '../__mocks__/data_view_with_timefield'; + +describe('getLensAttributes', () => { + const dataView: DataView = dataViewWithTimefieldMock; + const filters: Filter[] = [ + { + meta: { + index: dataView.id, + negate: false, + disabled: false, + alias: null, + type: 'phrase', + key: 'extension', + params: { + query: 'js', + }, + }, + query: { + match: { + extension: { + query: 'js', + type: 'phrase', + }, + }, + }, + $state: { + store: FilterStateStore.APP_STATE, + }, + }, + ]; + const query: Query | AggregateQuery = { language: 'kuery', query: 'extension : css' }; + const timeInterval = 'auto'; + + it('should return correct attributes', () => { + const breakdownField: DataViewField | undefined = undefined; + expect( + getLensAttributes({ title: 'test', filters, query, dataView, timeInterval, breakdownField }) + ).toMatchInlineSnapshot(` + Object { + "references": Array [ + Object { + "id": "index-pattern-with-timefield-id", + "name": "indexpattern-datasource-current-indexpattern", + "type": "index-pattern", + }, + Object { + "id": "index-pattern-with-timefield-id", + "name": "indexpattern-datasource-layer-unifiedHistogram", + "type": "index-pattern", + }, + ], + "state": Object { + "datasourceStates": Object { + "formBased": Object { + "layers": Object { + "unifiedHistogram": Object { + "columnOrder": Array [ + "date_column", + "count_column", + ], + "columns": Object { + "count_column": Object { + "dataType": "number", + "isBucketed": false, + "label": "Count of records", + "operationType": "count", + "params": Object { + "format": Object { + "id": "number", + "params": Object { + "decimals": 0, + }, + }, + }, + "scale": "ratio", + "sourceField": "___records___", + }, + "date_column": Object { + "dataType": "date", + "isBucketed": true, + "label": "timestamp", + "operationType": "date_histogram", + "params": Object { + "interval": "auto", + }, + "scale": "interval", + "sourceField": "timestamp", + }, + }, + }, + }, + }, + }, + "filters": Array [ + Object { + "$state": Object { + "store": "appState", + }, + "meta": Object { + "alias": null, + "disabled": false, + "index": "index-pattern-with-timefield-id", + "key": "extension", + "negate": false, + "params": Object { + "query": "js", + }, + "type": "phrase", + }, + "query": Object { + "match": Object { + "extension": Object { + "query": "js", + "type": "phrase", + }, + }, + }, + }, + ], + "query": Object { + "language": "kuery", + "query": "extension : css", + }, + "visualization": Object { + "axisTitlesVisibilitySettings": Object { + "x": false, + "yLeft": false, + "yRight": false, + }, + "fittingFunction": "None", + "gridlinesVisibilitySettings": Object { + "x": true, + "yLeft": true, + "yRight": false, + }, + "layers": Array [ + Object { + "accessors": Array [ + "count_column", + ], + "layerId": "unifiedHistogram", + "layerType": "data", + "seriesType": "bar_stacked", + "xAccessor": "date_column", + "yConfig": Array [ + Object { + "forAccessor": "count_column", + }, + ], + }, + ], + "legend": Object { + "isVisible": true, + "position": "right", + }, + "preferredSeriesType": "bar_stacked", + "showCurrentTimeMarker": true, + "tickLabelsVisibilitySettings": Object { + "x": true, + "yLeft": true, + "yRight": false, + }, + "valueLabels": "hide", + }, + }, + "title": "test", + "visualizationType": "lnsXY", + } + `); + }); + + it('should return correct attributes with breakdown field', () => { + const breakdownField: DataViewField | undefined = dataView.fields.find( + (f) => f.name === 'extension' + ); + expect( + getLensAttributes({ title: 'test', filters, query, dataView, timeInterval, breakdownField }) + ).toMatchInlineSnapshot(` + Object { + "references": Array [ + Object { + "id": "index-pattern-with-timefield-id", + "name": "indexpattern-datasource-current-indexpattern", + "type": "index-pattern", + }, + Object { + "id": "index-pattern-with-timefield-id", + "name": "indexpattern-datasource-layer-unifiedHistogram", + "type": "index-pattern", + }, + ], + "state": Object { + "datasourceStates": Object { + "formBased": Object { + "layers": Object { + "unifiedHistogram": Object { + "columnOrder": Array [ + "breakdown_column", + "date_column", + "count_column", + ], + "columns": Object { + "breakdown_column": Object { + "dataType": "string", + "isBucketed": true, + "label": "Top 3 values of extension", + "operationType": "terms", + "params": Object { + "missingBucket": false, + "orderBy": Object { + "columnId": "count_column", + "type": "column", + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": Object { + "id": "terms", + }, + "size": 3, + }, + "scale": "ordinal", + "sourceField": "extension", + }, + "count_column": Object { + "dataType": "number", + "isBucketed": false, + "label": "Count of records", + "operationType": "count", + "params": Object { + "format": Object { + "id": "number", + "params": Object { + "decimals": 0, + }, + }, + }, + "scale": "ratio", + "sourceField": "___records___", + }, + "date_column": Object { + "dataType": "date", + "isBucketed": true, + "label": "timestamp", + "operationType": "date_histogram", + "params": Object { + "interval": "auto", + }, + "scale": "interval", + "sourceField": "timestamp", + }, + }, + }, + }, + }, + }, + "filters": Array [ + Object { + "$state": Object { + "store": "appState", + }, + "meta": Object { + "alias": null, + "disabled": false, + "index": "index-pattern-with-timefield-id", + "key": "extension", + "negate": false, + "params": Object { + "query": "js", + }, + "type": "phrase", + }, + "query": Object { + "match": Object { + "extension": Object { + "query": "js", + "type": "phrase", + }, + }, + }, + }, + ], + "query": Object { + "language": "kuery", + "query": "extension : css", + }, + "visualization": Object { + "axisTitlesVisibilitySettings": Object { + "x": false, + "yLeft": false, + "yRight": false, + }, + "fittingFunction": "None", + "gridlinesVisibilitySettings": Object { + "x": true, + "yLeft": true, + "yRight": false, + }, + "layers": Array [ + Object { + "accessors": Array [ + "count_column", + ], + "layerId": "unifiedHistogram", + "layerType": "data", + "seriesType": "bar_stacked", + "splitAccessor": "breakdown_column", + "xAccessor": "date_column", + }, + ], + "legend": Object { + "isVisible": true, + "position": "right", + }, + "preferredSeriesType": "bar_stacked", + "showCurrentTimeMarker": true, + "tickLabelsVisibilitySettings": Object { + "x": true, + "yLeft": true, + "yRight": false, + }, + "valueLabels": "hide", + }, + }, + "title": "test", + "visualizationType": "lnsXY", + } + `); + }); + + it('should return correct attributes with unsupported breakdown field', () => { + const breakdownField: DataViewField | undefined = dataView.fields.find( + (f) => f.name === 'scripted' + ); + expect( + getLensAttributes({ title: 'test', filters, query, dataView, timeInterval, breakdownField }) + ).toMatchInlineSnapshot(` + Object { + "references": Array [ + Object { + "id": "index-pattern-with-timefield-id", + "name": "indexpattern-datasource-current-indexpattern", + "type": "index-pattern", + }, + Object { + "id": "index-pattern-with-timefield-id", + "name": "indexpattern-datasource-layer-unifiedHistogram", + "type": "index-pattern", + }, + ], + "state": Object { + "datasourceStates": Object { + "formBased": Object { + "layers": Object { + "unifiedHistogram": Object { + "columnOrder": Array [ + "date_column", + "count_column", + ], + "columns": Object { + "count_column": Object { + "dataType": "number", + "isBucketed": false, + "label": "Count of records", + "operationType": "count", + "params": Object { + "format": Object { + "id": "number", + "params": Object { + "decimals": 0, + }, + }, + }, + "scale": "ratio", + "sourceField": "___records___", + }, + "date_column": Object { + "dataType": "date", + "isBucketed": true, + "label": "timestamp", + "operationType": "date_histogram", + "params": Object { + "interval": "auto", + }, + "scale": "interval", + "sourceField": "timestamp", + }, + }, + }, + }, + }, + }, + "filters": Array [ + Object { + "$state": Object { + "store": "appState", + }, + "meta": Object { + "alias": null, + "disabled": false, + "index": "index-pattern-with-timefield-id", + "key": "extension", + "negate": false, + "params": Object { + "query": "js", + }, + "type": "phrase", + }, + "query": Object { + "match": Object { + "extension": Object { + "query": "js", + "type": "phrase", + }, + }, + }, + }, + ], + "query": Object { + "language": "kuery", + "query": "extension : css", + }, + "visualization": Object { + "axisTitlesVisibilitySettings": Object { + "x": false, + "yLeft": false, + "yRight": false, + }, + "fittingFunction": "None", + "gridlinesVisibilitySettings": Object { + "x": true, + "yLeft": true, + "yRight": false, + }, + "layers": Array [ + Object { + "accessors": Array [ + "count_column", + ], + "layerId": "unifiedHistogram", + "layerType": "data", + "seriesType": "bar_stacked", + "xAccessor": "date_column", + "yConfig": Array [ + Object { + "forAccessor": "count_column", + }, + ], + }, + ], + "legend": Object { + "isVisible": true, + "position": "right", + }, + "preferredSeriesType": "bar_stacked", + "showCurrentTimeMarker": true, + "tickLabelsVisibilitySettings": Object { + "x": true, + "yLeft": true, + "yRight": false, + }, + "valueLabels": "hide", + }, + }, + "title": "test", + "visualizationType": "lnsXY", + } + `); + }); +}); diff --git a/src/plugins/unified_histogram/public/chart/get_lens_attributes.ts b/src/plugins/unified_histogram/public/chart/get_lens_attributes.ts new file mode 100644 index 0000000000000..dc6f9216b4e56 --- /dev/null +++ b/src/plugins/unified_histogram/public/chart/get_lens_attributes.ts @@ -0,0 +1,180 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { DataView, DataViewField } from '@kbn/data-views-plugin/public'; +import type { AggregateQuery, Filter, Query } from '@kbn/es-query'; +import { i18n } from '@kbn/i18n'; +import type { + CountIndexPatternColumn, + DateHistogramIndexPatternColumn, + GenericIndexPatternColumn, + TermsIndexPatternColumn, + TypedLensByValueInput, +} from '@kbn/lens-plugin/public'; +import { fieldSupportsBreakdown } from './field_supports_breakdown'; + +export const getLensAttributes = ({ + title, + filters, + query, + dataView, + timeInterval, + breakdownField, +}: { + title?: string; + filters: Filter[]; + query: Query | AggregateQuery; + dataView: DataView; + timeInterval: string | undefined; + breakdownField: DataViewField | undefined; +}) => { + const showBreakdown = breakdownField && fieldSupportsBreakdown(breakdownField); + + let columnOrder = ['date_column', 'count_column']; + + if (showBreakdown) { + columnOrder = ['breakdown_column', ...columnOrder]; + } + + let columns: Record = { + date_column: { + dataType: 'date', + isBucketed: true, + label: dataView.timeFieldName ?? '', + operationType: 'date_histogram', + scale: 'interval', + sourceField: dataView.timeFieldName, + params: { + interval: timeInterval ?? 'auto', + }, + } as DateHistogramIndexPatternColumn, + count_column: { + dataType: 'number', + isBucketed: false, + label: i18n.translate('unifiedHistogram.countColumnLabel', { + defaultMessage: 'Count of records', + }), + operationType: 'count', + scale: 'ratio', + sourceField: '___records___', + params: { + format: { + id: 'number', + params: { + decimals: 0, + }, + }, + }, + } as CountIndexPatternColumn, + }; + + if (showBreakdown) { + columns = { + ...columns, + breakdown_column: { + dataType: 'string', + isBucketed: true, + label: i18n.translate('unifiedHistogram.breakdownColumnLabel', { + defaultMessage: 'Top 3 values of {fieldName}', + values: { fieldName: breakdownField?.displayName }, + }), + operationType: 'terms', + scale: 'ordinal', + sourceField: breakdownField.name, + params: { + size: 3, + orderBy: { + type: 'column', + columnId: 'count_column', + }, + orderDirection: 'desc', + otherBucket: true, + missingBucket: false, + parentFormat: { + id: 'terms', + }, + }, + } as TermsIndexPatternColumn, + }; + } + + return { + title: + title ?? + i18n.translate('unifiedHistogram.lensTitle', { + defaultMessage: 'Edit visualization', + }), + references: [ + { + id: dataView.id ?? '', + name: 'indexpattern-datasource-current-indexpattern', + type: 'index-pattern', + }, + { + id: dataView.id ?? '', + name: 'indexpattern-datasource-layer-unifiedHistogram', + type: 'index-pattern', + }, + ], + state: { + datasourceStates: { + formBased: { + layers: { + unifiedHistogram: { columnOrder, columns }, + }, + }, + }, + filters, + query: 'language' in query ? query : { language: 'kuery', query: '' }, + visualization: { + layers: [ + { + accessors: ['count_column'], + layerId: 'unifiedHistogram', + layerType: 'data', + seriesType: 'bar_stacked', + xAccessor: 'date_column', + ...(showBreakdown + ? { splitAccessor: 'breakdown_column' } + : { + yConfig: [ + { + forAccessor: 'count_column', + }, + ], + }), + }, + ], + legend: { + isVisible: true, + position: 'right', + }, + preferredSeriesType: 'bar_stacked', + valueLabels: 'hide', + fittingFunction: 'None', + showCurrentTimeMarker: true, + axisTitlesVisibilitySettings: { + x: false, + yLeft: false, + yRight: false, + }, + gridlinesVisibilitySettings: { + x: true, + yLeft: true, + yRight: false, + }, + tickLabelsVisibilitySettings: { + x: true, + yLeft: true, + yRight: false, + }, + }, + }, + visualizationType: 'lnsXY', + } as TypedLensByValueInput['attributes']; +}; diff --git a/src/plugins/unified_histogram/public/chart/histogram.test.tsx b/src/plugins/unified_histogram/public/chart/histogram.test.tsx index 3e1213978e385..03652a63f5456 100644 --- a/src/plugins/unified_histogram/public/chart/histogram.test.tsx +++ b/src/plugins/unified_histogram/public/chart/histogram.test.tsx @@ -6,55 +6,37 @@ * Side Public License, v 1. */ import { mountWithIntl } from '@kbn/test-jest-helpers'; -import type { UnifiedHistogramChartData, UnifiedHistogramFetchStatus } from '../types'; -import { Histogram } from './histogram'; +import { getLensProps, Histogram } from './histogram'; import React from 'react'; import { unifiedHistogramServicesMock } from '../__mocks__/services'; +import { dataViewWithTimefieldMock } from '../__mocks__/data_view_with_timefield'; +import { createDefaultInspectorAdapters } from '@kbn/expressions-plugin/common'; +import { UnifiedHistogramFetchStatus } from '../types'; +import { getLensAttributes } from './get_lens_attributes'; +import { REQUEST_DEBOUNCE_MS } from './consts'; +import { act } from 'react-dom/test-utils'; +import * as buildBucketInterval from './build_bucket_interval'; +import * as useTimeRange from './use_time_range'; +import { RequestStatus } from '@kbn/inspector-plugin/public'; -const chartData = { - xAxisOrderedValues: [ - 1623880800000, 1623967200000, 1624053600000, 1624140000000, 1624226400000, 1624312800000, - 1624399200000, 1624485600000, 1624572000000, 1624658400000, 1624744800000, 1624831200000, - 1624917600000, 1625004000000, 1625090400000, - ], - xAxisFormat: { id: 'date', params: { pattern: 'YYYY-MM-DD' } }, - xAxisLabel: 'order_date per day', - yAxisFormat: { id: 'number' }, - ordered: { - date: true, - interval: { - asMilliseconds: jest.fn(), +const mockBucketInterval = { description: '1 minute', scale: undefined, scaled: false }; +jest.spyOn(buildBucketInterval, 'buildBucketInterval').mockReturnValue(mockBucketInterval); +jest.spyOn(useTimeRange, 'useTimeRange'); + +const getMockLensAttributes = () => + getLensAttributes({ + title: 'test', + filters: [], + query: { + language: 'kuery', + query: '', }, - intervalESUnit: 'd', - intervalESValue: 1, - min: '2021-03-18T08:28:56.411Z', - max: '2021-07-01T07:28:56.411Z', - }, - yAxisLabel: 'Count', - values: [ - { x: 1623880800000, y: 134 }, - { x: 1623967200000, y: 152 }, - { x: 1624053600000, y: 141 }, - { x: 1624140000000, y: 138 }, - { x: 1624226400000, y: 142 }, - { x: 1624312800000, y: 157 }, - { x: 1624399200000, y: 149 }, - { x: 1624485600000, y: 146 }, - { x: 1624572000000, y: 170 }, - { x: 1624658400000, y: 137 }, - { x: 1624744800000, y: 150 }, - { x: 1624831200000, y: 144 }, - { x: 1624917600000, y: 147 }, - { x: 1625004000000, y: 137 }, - { x: 1625090400000, y: 66 }, - ], -} as unknown as UnifiedHistogramChartData; + dataView: dataViewWithTimefieldMock, + timeInterval: 'auto', + breakdownField: dataViewWithTimefieldMock.getFieldByName('extension'), + }); -function mountComponent( - status: UnifiedHistogramFetchStatus, - data: UnifiedHistogramChartData | null = chartData, - error?: Error -) { +function mountComponent() { const services = unifiedHistogramServicesMock; services.data.query.timefilter.timefilter.getAbsoluteTime = () => { return { from: '2020-05-14T11:05:13.590', to: '2020-05-14T11:20:13.590' }; @@ -64,44 +46,212 @@ function mountComponent( const props = { services: unifiedHistogramServicesMock, + request: { + searchSessionId: '123', + }, + hits: { + status: UnifiedHistogramFetchStatus.loading, + total: undefined, + }, chart: { - status, hidden: false, timeInterval: 'auto', - bucketInterval: { - scaled: true, - description: 'test', - scale: 2, - }, - data: data ?? undefined, - error, }, timefilterUpdateHandler, + dataView: dataViewWithTimefieldMock, + timeRange: { + from: '2020-05-14T11:05:13.590', + to: '2020-05-14T11:20:13.590', + }, + lastReloadRequestTime: 42, + lensAttributes: getMockLensAttributes(), + onTotalHitsChange: jest.fn(), + onChartLoad: jest.fn(), }; - return mountWithIntl(); + return { + props, + component: mountWithIntl(), + }; } describe('Histogram', () => { it('renders correctly', () => { - const component = mountComponent('complete'); + const { component } = mountComponent(); expect(component.find('[data-test-subj="unifiedHistogramChart"]').exists()).toBe(true); }); - it('renders error correctly', () => { - const component = mountComponent('error', null, new Error('Loading error')); - expect(component.find('[data-test-subj="unifiedHistogramChart"]').exists()).toBe(false); - expect(component.find('[data-test-subj="unifiedHistogramErrorChartContainer"]').exists()).toBe( - true + it('should render lens.EmbeddableComponent with debounced props', async () => { + const { component, props } = mountComponent(); + const embeddable = unifiedHistogramServicesMock.lens.EmbeddableComponent; + expect(component.find(embeddable).exists()).toBe(true); + let lensProps = component.find(embeddable).props(); + const originalProps = getLensProps({ + timeRange: props.timeRange, + attributes: getMockLensAttributes(), + request: props.request, + lastReloadRequestTime: props.lastReloadRequestTime, + onLoad: lensProps.onLoad, + }); + expect(lensProps).toEqual(originalProps); + component.setProps({ lastReloadRequestTime: 43 }).update(); + lensProps = component.find(embeddable).props(); + expect(lensProps).toEqual(originalProps); + await act(async () => { + await new Promise((resolve) => setTimeout(resolve, REQUEST_DEBOUNCE_MS)); + }); + component.update(); + lensProps = component.find(embeddable).props(); + expect(lensProps).toEqual({ ...originalProps, lastReloadRequestTime: 43 }); + }); + + it('should execute onLoad correctly', async () => { + const { component, props } = mountComponent(); + const embeddable = unifiedHistogramServicesMock.lens.EmbeddableComponent; + const onLoad = component.find(embeddable).props().onLoad; + const adapters = createDefaultInspectorAdapters(); + adapters.tables.tables.unifiedHistogram = { meta: { statistics: { totalCount: 100 } } } as any; + const rawResponse = { + took: 0, + timed_out: false, + _shards: { + total: 1, + successful: 1, + skipped: 0, + failed: 0, + }, + hits: { + total: 100, + max_score: null, + hits: [], + }, + aggregations: { + '2': { + buckets: [ + { + key_as_string: '2022-10-05T16:00:00.000-03:00', + key: 1664996400000, + doc_count: 20, + }, + { + key_as_string: '2022-10-05T16:30:00.000-03:00', + key: 1664998200000, + doc_count: 20, + }, + { + key_as_string: '2022-10-05T17:00:00.000-03:00', + key: 1665000000000, + doc_count: 20, + }, + { + key_as_string: '2022-10-05T17:30:00.000-03:00', + key: 1665001800000, + doc_count: 20, + }, + { + key_as_string: '2022-10-05T18:00:00.000-03:00', + key: 1665003600000, + doc_count: 20, + }, + ], + }, + }, + }; + jest + .spyOn(adapters.requests, 'getRequests') + .mockReturnValue([{ response: { json: { rawResponse } } } as any]); + onLoad(true, undefined); + expect(props.onTotalHitsChange).toHaveBeenLastCalledWith( + UnifiedHistogramFetchStatus.loading, + undefined + ); + expect(props.onChartLoad).toHaveBeenLastCalledWith({ complete: false, adapters: {} }); + expect(buildBucketInterval.buildBucketInterval).not.toHaveBeenCalled(); + expect(useTimeRange.useTimeRange).toHaveBeenLastCalledWith( + expect.objectContaining({ bucketInterval: undefined }) + ); + act(() => { + onLoad(false, adapters); + }); + expect(props.onTotalHitsChange).toHaveBeenLastCalledWith( + UnifiedHistogramFetchStatus.complete, + 100 + ); + expect(props.onChartLoad).toHaveBeenLastCalledWith({ complete: true, adapters }); + expect(buildBucketInterval.buildBucketInterval).toHaveBeenCalled(); + expect(useTimeRange.useTimeRange).toHaveBeenLastCalledWith( + expect.objectContaining({ bucketInterval: mockBucketInterval }) ); - expect( - component.find('[data-test-subj="unifiedHistogramErrorChartText"]').get(1).props.children - ).toBe('Loading error'); }); - it('renders loading state correctly', () => { - const component = mountComponent('loading', null); - expect(component.find('[data-test-subj="unifiedHistogramChart"]').exists()).toBe(true); - expect(component.find('[data-test-subj="unifiedHistogramChartLoading"]').exists()).toBe(true); + it('should execute onLoad correctly when the request has a failure status', async () => { + const { component, props } = mountComponent(); + const embeddable = unifiedHistogramServicesMock.lens.EmbeddableComponent; + const onLoad = component.find(embeddable).props().onLoad; + const adapters = createDefaultInspectorAdapters(); + jest + .spyOn(adapters.requests, 'getRequests') + .mockReturnValue([{ status: RequestStatus.ERROR } as any]); + onLoad(false, adapters); + expect(props.onTotalHitsChange).toHaveBeenLastCalledWith( + UnifiedHistogramFetchStatus.error, + undefined + ); + expect(props.onChartLoad).toHaveBeenLastCalledWith({ complete: false, adapters }); + }); + + it('should execute onLoad correctly when the response has shard failures', async () => { + const { component, props } = mountComponent(); + const embeddable = unifiedHistogramServicesMock.lens.EmbeddableComponent; + const onLoad = component.find(embeddable).props().onLoad; + const adapters = createDefaultInspectorAdapters(); + const rawResponse = { + _shards: { + total: 1, + successful: 0, + skipped: 0, + failed: 1, + failures: [], + }, + }; + jest + .spyOn(adapters.requests, 'getRequests') + .mockReturnValue([{ response: { json: { rawResponse } } } as any]); + onLoad(false, adapters); + expect(props.onTotalHitsChange).toHaveBeenLastCalledWith( + UnifiedHistogramFetchStatus.error, + undefined + ); + expect(props.onChartLoad).toHaveBeenLastCalledWith({ complete: false, adapters }); + }); + + it('should not recreate onLoad in debounced lens props when hits.total changes', async () => { + const { component, props } = mountComponent(); + const embeddable = unifiedHistogramServicesMock.lens.EmbeddableComponent; + const onLoad = component.find(embeddable).props().onLoad; + onLoad(true, undefined); + expect(props.onTotalHitsChange).toHaveBeenLastCalledWith( + UnifiedHistogramFetchStatus.loading, + undefined + ); + component + .setProps({ + hits: { + status: UnifiedHistogramFetchStatus.complete, + total: 100, + }, + }) + .update(); + expect(component.find(embeddable).props().onLoad).toBe(onLoad); + await act(async () => { + await new Promise((resolve) => setTimeout(resolve, REQUEST_DEBOUNCE_MS)); + }); + component.update(); + expect(component.find(embeddable).props().onLoad).toBe(onLoad); + onLoad(true, undefined); + expect(props.onTotalHitsChange).toHaveBeenLastCalledWith( + UnifiedHistogramFetchStatus.loading, + 100 + ); }); }); diff --git a/src/plugins/unified_histogram/public/chart/histogram.tsx b/src/plugins/unified_histogram/public/chart/histogram.tsx index a201258e49bf2..c30c6a1410985 100644 --- a/src/plugins/unified_histogram/public/chart/histogram.tsx +++ b/src/plugins/unified_histogram/public/chart/histogram.tsx @@ -6,351 +6,187 @@ * Side Public License, v 1. */ -import moment, { unitOfTime } from 'moment-timezone'; -import React, { useCallback, useMemo } from 'react'; -import { - EuiFlexGroup, - EuiFlexItem, - EuiIcon, - EuiIconTip, - EuiLoadingChart, - EuiSpacer, - EuiText, - useEuiTheme, -} from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n-react'; -import dateMath from '@kbn/datemath'; -import type { - BrushEndListener, - ElementClickListener, - XYBrushEvent, - XYChartElementEvent, -} from '@elastic/charts'; -import { - Axis, - Chart, - HistogramBarSeries, - Position, - ScaleType, - Settings, - TooltipType, -} from '@elastic/charts'; -import type { IUiSettingsClient } from '@kbn/core/public'; -import { i18n } from '@kbn/i18n'; -import { - CurrentTime, - Endzones, - getAdjustedInterval, - renderEndzoneTooltip, -} from '@kbn/charts-plugin/public'; -import { LEGACY_TIME_AXIS, MULTILAYER_TIME_AXIS_STYLE } from '@kbn/charts-plugin/common'; +import { useEuiTheme } from '@elastic/eui'; import { css } from '@emotion/react'; -import type { UnifiedHistogramChartContext, UnifiedHistogramServices } from '../types'; +import React, { useCallback, useEffect, useRef, useState } from 'react'; +import type { DataView } from '@kbn/data-views-plugin/public'; +import type { DefaultInspectorAdapters } from '@kbn/expressions-plugin/common'; +import type { IKibanaSearchResponse } from '@kbn/data-plugin/public'; +import type { estypes } from '@elastic/elasticsearch'; +import type { TimeRange } from '@kbn/es-query'; +import useDebounce from 'react-use/lib/useDebounce'; +import { ViewMode } from '@kbn/embeddable-plugin/public'; +import type { TypedLensByValueInput } from '@kbn/lens-plugin/public'; +import { RequestStatus } from '@kbn/inspector-plugin/public'; +import { + UnifiedHistogramBucketInterval, + UnifiedHistogramChartContext, + UnifiedHistogramFetchStatus, + UnifiedHistogramHitsContext, + UnifiedHistogramChartLoadEvent, + UnifiedHistogramRequestContext, + UnifiedHistogramServices, +} from '../types'; +import { buildBucketInterval } from './build_bucket_interval'; +import { useTimeRange } from './use_time_range'; +import { REQUEST_DEBOUNCE_MS } from './consts'; export interface HistogramProps { services: UnifiedHistogramServices; + dataView: DataView; + lastReloadRequestTime: number | undefined; + request?: UnifiedHistogramRequestContext; + hits?: UnifiedHistogramHitsContext; chart: UnifiedHistogramChartContext; - timefilterUpdateHandler: (ranges: { from: number; to: number }) => void; -} - -function getTimezone(uiSettings: IUiSettingsClient) { - if (uiSettings.isDefault('dateFormat:tz')) { - const detectedTimezone = moment.tz.guess(); - if (detectedTimezone) return detectedTimezone; - else return moment().format('Z'); - } else { - return uiSettings.get('dateFormat:tz', 'Browser'); - } + timeRange: TimeRange; + lensAttributes: TypedLensByValueInput['attributes']; + onTotalHitsChange?: (status: UnifiedHistogramFetchStatus, result?: number | Error) => void; + onChartLoad?: (event: UnifiedHistogramChartLoadEvent) => void; } export function Histogram({ - services: { data, theme, uiSettings, fieldFormats }, - chart: { status, timeInterval, bucketInterval, data: chartData, error }, - timefilterUpdateHandler, + services: { data, lens, uiSettings }, + dataView, + lastReloadRequestTime, + request, + hits, + chart: { timeInterval }, + timeRange, + lensAttributes: attributes, + onTotalHitsChange, + onChartLoad, }: HistogramProps) { - const chartTheme = theme.useChartsTheme(); - const chartBaseTheme = theme.useChartsBaseTheme(); - const timeZone = getTimezone(uiSettings); + const [bucketInterval, setBucketInterval] = useState(); + const { timeRangeText, timeRangeDisplay } = useTimeRange({ + uiSettings, + bucketInterval, + timeRange, + timeInterval, + }); - const onBrushEnd = useCallback( - ({ x }: XYBrushEvent) => { - if (!x) { + // Keep track of previous hits in a ref to avoid recreating the + // onLoad callback when the hits change, which triggers a Lens reload + const previousHits = useRef(hits?.total); + + useEffect(() => { + previousHits.current = hits?.total; + }, [hits?.total]); + + const onLoad = useCallback( + (isLoading: boolean, adapters: Partial | undefined) => { + const lensRequest = adapters?.requests?.getRequests()[0]; + const requestFailed = lensRequest?.status === RequestStatus.ERROR; + const json = lensRequest?.response?.json as + | IKibanaSearchResponse + | undefined; + const response = json?.rawResponse; + + // Lens will swallow shard failures and return `isLoading: false` because it displays + // its own errors, but this causes us to emit onTotalHitsChange(UnifiedHistogramFetchStatus.complete, 0). + // This is incorrect, so we check for request failures and shard failures here, and emit an error instead. + if (requestFailed || response?._shards.failed) { + onTotalHitsChange?.(UnifiedHistogramFetchStatus.error, undefined); + onChartLoad?.({ complete: false, adapters: adapters ?? {} }); return; } - const [from, to] = x; - timefilterUpdateHandler({ from, to }); - }, - [timefilterUpdateHandler] - ); - const onElementClick = useCallback( - (xInterval: number): ElementClickListener => - ([elementData]) => { - const startRange = (elementData as XYChartElementEvent)[0].x; + const totalHits = adapters?.tables?.tables?.unifiedHistogram?.meta?.statistics?.totalCount; - const range = { - from: startRange, - to: startRange + xInterval, - }; + onTotalHitsChange?.( + isLoading ? UnifiedHistogramFetchStatus.loading : UnifiedHistogramFetchStatus.complete, + totalHits ?? previousHits.current + ); - timefilterUpdateHandler(range); - }, - [timefilterUpdateHandler] - ); + if (response) { + const newBucketInterval = buildBucketInterval({ + data, + dataView, + timeInterval, + timeRange, + response, + }); - const { timefilter } = data.query.timefilter; - const { from, to } = timefilter.getAbsoluteTime(); - const dateFormat = useMemo(() => uiSettings.get('dateFormat'), [uiSettings]); - - const toMoment = useCallback( - (datetime: moment.Moment | undefined) => { - if (!datetime) { - return ''; - } - if (!dateFormat) { - return String(datetime); + setBucketInterval(newBucketInterval); } - return datetime.format(dateFormat); + + onChartLoad?.({ complete: !isLoading, adapters: adapters ?? {} }); }, - [dateFormat] + [data, dataView, onChartLoad, onTotalHitsChange, timeInterval, timeRange] ); - const timeRangeText = useMemo(() => { - const timeRange = { - from: dateMath.parse(from), - to: dateMath.parse(to, { roundUp: true }), - }; - const intervalText = i18n.translate('unifiedHistogram.histogramTimeRangeIntervalDescription', { - defaultMessage: '(interval: {value})', - values: { - value: `${ - timeInterval === 'auto' - ? `${i18n.translate('unifiedHistogram.histogramTimeRangeIntervalAuto', { - defaultMessage: 'Auto', - })} - ` - : '' - }${bucketInterval?.description}`, - }, - }); - return `${toMoment(timeRange.from)} - ${toMoment(timeRange.to)} ${intervalText}`; - }, [from, to, timeInterval, bucketInterval?.description, toMoment]); - const { euiTheme } = useEuiTheme(); const chartCss = css` + position: relative; flex-grow: 1; - padding: 0 ${euiTheme.size.s} ${euiTheme.size.s} ${euiTheme.size.s}; - `; - if (!chartData && status === 'loading') { - const chartLoadingCss = css` - display: flex; - flex-direction: column; - justify-content: center; - flex: 1 0 100%; - text-align: center; + & > div { height: 100%; - width: 100%; - `; - - return ( -
    -
    - - - - - -
    -
    - ); - } - - if (status === 'error' && error) { - const chartErrorContainerCss = css` - padding: 0 ${euiTheme.size.s} 0 ${euiTheme.size.s}; - `; - const chartErrorIconCss = css` - padding-top: 0.5 * ${euiTheme.size.xs}; - `; - const chartErrorCss = css` - margin-left: ${euiTheme.size.xs} !important; - `; - const chartErrorTextCss = css` - margin-top: ${euiTheme.size.s}; - `; - - return ( -
    - - - - - - - - - - - - {error.message} - -
    - ); - } - - if (!chartData) { - return null; - } - - const formatXValue = (val: string) => { - const xAxisFormat = chartData.xAxisFormat.params!.pattern; - return moment(val).format(xAxisFormat); - }; - - const isDarkMode = uiSettings.get('theme:darkMode'); - - /* - * Deprecation: [interval] on [date_histogram] is deprecated, use [fixed_interval] or [calendar_interval]. - * see https://github.com/elastic/kibana/issues/27410 - * TODO: Once the Discover query has been update, we should change the below to use the new field - */ - const { intervalESValue, intervalESUnit, interval } = chartData.ordered; - const xInterval = interval.asMilliseconds(); - - const xValues = chartData.xAxisOrderedValues; - const lastXValue = xValues[xValues.length - 1]; - - const domain = chartData.ordered; - const domainStart = domain.min.valueOf(); - const domainEnd = domain.max.valueOf(); - - const domainMin = Math.min(chartData.values[0]?.x, domainStart); - const domainMax = Math.max(domainEnd - xInterval, lastXValue); - - const xDomain = { - min: domainMin, - max: domainMax, - minInterval: getAdjustedInterval( - xValues, - intervalESValue, - intervalESUnit as unitOfTime.Base, - timeZone - ), - }; - const tooltipProps = { - headerFormatter: renderEndzoneTooltip(xInterval, domainStart, domainEnd, formatXValue), - type: TooltipType.VerticalCursor, - }; - - const xAxisFormatter = fieldFormats.deserialize(chartData.yAxisFormat); - - const useLegacyTimeAxis = uiSettings.get(LEGACY_TIME_AXIS, false); + } + + & .echLegend .echLegendList { + padding-right: ${euiTheme.size.s}; + } + + & > .euiLoadingChart { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + } + `; - const toolTipTitle = i18n.translate('unifiedHistogram.timeIntervalWithValueWarning', { - defaultMessage: 'Warning', - }); + const [debouncedProps, setDebouncedProps] = useState( + getLensProps({ + timeRange, + attributes, + request, + lastReloadRequestTime, + onLoad, + }) + ); - const toolTipContent = i18n.translate('unifiedHistogram.bucketIntervalTooltip', { - defaultMessage: - 'This interval creates {bucketsDescription} to show in the selected time range, so it has been scaled to {bucketIntervalDescription}.', - values: { - bucketsDescription: - bucketInterval!.scale && bucketInterval!.scale > 1 - ? i18n.translate('unifiedHistogram.bucketIntervalTooltip.tooLargeBucketsText', { - defaultMessage: 'buckets that are too large', - }) - : i18n.translate('unifiedHistogram.bucketIntervalTooltip.tooManyBucketsText', { - defaultMessage: 'too many buckets', - }), - bucketIntervalDescription: bucketInterval?.description, + useDebounce( + () => { + setDebouncedProps( + getLensProps({ timeRange, attributes, request, lastReloadRequestTime, onLoad }) + ); }, - }); - - const timeRangeCss = css` - padding: 0 ${euiTheme.size.s} 0 ${euiTheme.size.s}; - `; - let timeRange = ( - - {timeRangeText} - + REQUEST_DEBOUNCE_MS, + [attributes, lastReloadRequestTime, onLoad, request, timeRange] ); - if (bucketInterval?.scaled) { - const timeRangeWrapperCss = css` - flex-grow: 0; - `; - timeRange = ( - - {timeRange} - - - - - ); - } return ( - + <>
    - - - xAxisFormatter.convert(value)} - /> - - - - - +
    - {timeRange} -
    + {timeRangeDisplay} + ); } + +export const getLensProps = ({ + timeRange, + attributes, + request, + lastReloadRequestTime, + onLoad, +}: { + timeRange: TimeRange; + attributes: TypedLensByValueInput['attributes']; + request: UnifiedHistogramRequestContext | undefined; + lastReloadRequestTime: number | undefined; + onLoad: (isLoading: boolean, adapters: Partial | undefined) => void; +}) => ({ + id: 'unifiedHistogramLensComponent', + viewMode: ViewMode.VIEW, + timeRange, + attributes, + noPadding: true, + searchSessionId: request?.searchSessionId, + executionContext: { + description: 'fetch chart data and total hits', + }, + lastReloadRequestTime, + onLoad, +}); diff --git a/src/plugins/unified_histogram/public/chart/index.ts b/src/plugins/unified_histogram/public/chart/index.ts index e50532f3bfec2..6a6d2d65f6f92 100644 --- a/src/plugins/unified_histogram/public/chart/index.ts +++ b/src/plugins/unified_histogram/public/chart/index.ts @@ -7,5 +7,3 @@ */ export { Chart } from './chart'; -export { getChartAggConfigs } from './get_chart_agg_configs'; -export { buildChartData } from './build_chart_data'; diff --git a/src/plugins/unified_histogram/public/chart/use_chart_actions.test.ts b/src/plugins/unified_histogram/public/chart/use_chart_actions.test.ts new file mode 100644 index 0000000000000..5967f01fd543b --- /dev/null +++ b/src/plugins/unified_histogram/public/chart/use_chart_actions.test.ts @@ -0,0 +1,82 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { renderHook } from '@testing-library/react-hooks'; +import { act } from 'react-test-renderer'; +import { UnifiedHistogramChartContext } from '..'; +import { useChartActions } from './use_chart_actions'; + +describe('useChartActions', () => { + const render = () => { + const chart: UnifiedHistogramChartContext = { + hidden: false, + timeInterval: 'auto', + }; + const onChartHiddenChange = jest.fn((hidden: boolean) => { + chart.hidden = hidden; + }); + return { + chart, + onChartHiddenChange, + hook: renderHook(() => useChartActions({ chart, onChartHiddenChange })), + }; + }; + + it('should toggle chart options', () => { + const { hook } = render(); + expect(hook.result.current.showChartOptionsPopover).toBe(false); + act(() => { + hook.result.current.toggleChartOptions(); + }); + expect(hook.result.current.showChartOptionsPopover).toBe(true); + act(() => { + hook.result.current.toggleChartOptions(); + }); + expect(hook.result.current.showChartOptionsPopover).toBe(false); + }); + + it('should close chart options', () => { + const { hook } = render(); + act(() => { + hook.result.current.toggleChartOptions(); + }); + expect(hook.result.current.showChartOptionsPopover).toBe(true); + act(() => { + hook.result.current.closeChartOptions(); + }); + expect(hook.result.current.showChartOptionsPopover).toBe(false); + }); + + it('should toggle hide chart', () => { + const { chart, onChartHiddenChange, hook } = render(); + act(() => { + hook.result.current.toggleHideChart(); + }); + expect(chart.hidden).toBe(true); + expect(onChartHiddenChange).toBeCalledWith(true); + act(() => { + hook.result.current.toggleHideChart(); + }); + expect(chart.hidden).toBe(false); + expect(onChartHiddenChange).toBeCalledWith(false); + }); + + it('should focus chart element', () => { + const { chart, hook } = render(); + hook.result.current.chartRef.current.element = document.createElement('div'); + hook.result.current.chartRef.current.element.focus = jest.fn(); + chart.hidden = true; + hook.rerender(); + act(() => { + hook.result.current.toggleHideChart(); + }); + hook.rerender(); + expect(hook.result.current.chartRef.current.moveFocus).toBe(true); + expect(hook.result.current.chartRef.current.element.focus).toBeCalled(); + }); +}); diff --git a/src/plugins/unified_histogram/public/chart/use_chart_actions.ts b/src/plugins/unified_histogram/public/chart/use_chart_actions.ts new file mode 100644 index 0000000000000..85b876e0862c1 --- /dev/null +++ b/src/plugins/unified_histogram/public/chart/use_chart_actions.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 { useCallback, useEffect, useRef, useState } from 'react'; +import type { UnifiedHistogramChartContext } from '../types'; + +export const useChartActions = ({ + chart, + onChartHiddenChange, +}: { + chart: UnifiedHistogramChartContext | undefined; + onChartHiddenChange?: (chartHidden: boolean) => void; +}) => { + const [showChartOptionsPopover, setShowChartOptionsPopover] = useState(false); + + const toggleChartOptions = useCallback(() => { + setShowChartOptionsPopover(!showChartOptionsPopover); + }, [showChartOptionsPopover]); + + const closeChartOptions = useCallback(() => { + setShowChartOptionsPopover(false); + }, [setShowChartOptionsPopover]); + + const chartRef = useRef<{ element: HTMLElement | null; moveFocus: boolean }>({ + element: null, + moveFocus: false, + }); + + useEffect(() => { + if (chartRef.current.moveFocus && chartRef.current.element) { + chartRef.current.element.focus(); + } + }, [chart?.hidden]); + + const toggleHideChart = useCallback(() => { + const chartHidden = !chart?.hidden; + chartRef.current.moveFocus = !chartHidden; + onChartHiddenChange?.(chartHidden); + }, [chart?.hidden, onChartHiddenChange]); + + return { + showChartOptionsPopover, + chartRef, + toggleChartOptions, + closeChartOptions, + toggleHideChart, + }; +}; diff --git a/src/plugins/unified_histogram/public/chart/use_chart_panels.test.ts b/src/plugins/unified_histogram/public/chart/use_chart_panels.test.ts index 71e2d3e4a705a..aec3f1a8e291f 100644 --- a/src/plugins/unified_histogram/public/chart/use_chart_panels.test.ts +++ b/src/plugins/unified_histogram/public/chart/use_chart_panels.test.ts @@ -19,7 +19,6 @@ describe('test useChartPanels', () => { closePopover: jest.fn(), onResetChartHeight: jest.fn(), chart: { - status: 'complete', hidden: true, timeInterval: 'auto', }, @@ -39,7 +38,6 @@ describe('test useChartPanels', () => { closePopover: jest.fn(), onResetChartHeight: jest.fn(), chart: { - status: 'complete', hidden: false, timeInterval: 'auto', }, @@ -59,7 +57,6 @@ describe('test useChartPanels', () => { onTimeIntervalChange: jest.fn(), closePopover: jest.fn(), chart: { - status: 'complete', hidden: false, timeInterval: 'auto', }, @@ -78,7 +75,6 @@ describe('test useChartPanels', () => { closePopover: jest.fn(), onResetChartHeight, chart: { - status: 'complete', hidden: false, timeInterval: 'auto', }, diff --git a/src/plugins/unified_histogram/public/chart/use_chart_panels.ts b/src/plugins/unified_histogram/public/chart/use_chart_panels.ts index dd6f162b352f6..8f2874baa624e 100644 --- a/src/plugins/unified_histogram/public/chart/use_chart_panels.ts +++ b/src/plugins/unified_histogram/public/chart/use_chart_panels.ts @@ -23,7 +23,7 @@ export function useChartPanels({ }: { chart?: UnifiedHistogramChartContext; toggleHideChart: () => void; - onTimeIntervalChange: (timeInterval: string) => void; + onTimeIntervalChange?: (timeInterval: string) => void; closePopover: () => void; onResetChartHeight?: () => void; }) { @@ -107,7 +107,7 @@ export function useChartPanels({ label: display, icon: val === chart.timeInterval ? 'check' : 'empty', onClick: () => { - onTimeIntervalChange(val); + onTimeIntervalChange?.(val); closePopover(); }, 'data-test-subj': `unifiedHistogramTimeInterval-${display}`, diff --git a/src/plugins/unified_histogram/public/chart/use_chart_styles.tsx b/src/plugins/unified_histogram/public/chart/use_chart_styles.tsx new file mode 100644 index 0000000000000..c019c7cef981e --- /dev/null +++ b/src/plugins/unified_histogram/public/chart/use_chart_styles.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 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 { useEuiBreakpoint, useEuiTheme } from '@elastic/eui'; +import { css } from '@emotion/react'; + +export const useChartStyles = (chartVisible: boolean) => { + const { euiTheme } = useEuiTheme(); + const resultCountCss = css` + padding: ${euiTheme.size.s} ${euiTheme.size.s} ${chartVisible ? 0 : euiTheme.size.s} + ${euiTheme.size.s}; + min-height: ${euiTheme.base * 2.5}px; + `; + const resultCountInnerCss = css` + ${useEuiBreakpoint(['xs', 's'])} { + align-items: center; + } + `; + const resultCountTitleCss = css` + flex-basis: auto; + + ${useEuiBreakpoint(['xs', 's'])} { + margin-bottom: 0 !important; + } + `; + const resultCountToggleCss = css` + flex-basis: auto; + min-width: 0; + + ${useEuiBreakpoint(['xs', 's'])} { + align-items: flex-end; + } + `; + const histogramCss = css` + flex-grow: 1; + display: flex; + flex-direction: column; + position: relative; + + // SASSTODO: the visualizing component should have an option or a modifier + .series > rect { + fill-opacity: 0.5; + stroke-width: 1; + } + `; + const breakdownFieldSelectorGroupCss = css` + width: 100%; + `; + const breakdownFieldSelectorItemCss = css` + min-width: 0; + align-items: flex-end; + padding-left: ${euiTheme.size.s}; + `; + const chartToolButtonCss = css` + display: flex; + justify-content: center; + padding-left: ${euiTheme.size.s}; + `; + + return { + resultCountCss, + resultCountInnerCss, + resultCountTitleCss, + resultCountToggleCss, + histogramCss, + breakdownFieldSelectorGroupCss, + breakdownFieldSelectorItemCss, + chartToolButtonCss, + }; +}; diff --git a/src/plugins/unified_histogram/public/chart/use_refetch_id.test.ts b/src/plugins/unified_histogram/public/chart/use_refetch_id.test.ts new file mode 100644 index 0000000000000..8835173df2599 --- /dev/null +++ b/src/plugins/unified_histogram/public/chart/use_refetch_id.test.ts @@ -0,0 +1,68 @@ +/* + * Copyright 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 { DataView } from '@kbn/data-views-plugin/common'; +import { AggregateQuery, Filter, Query, TimeRange } from '@kbn/es-query'; +import { renderHook } from '@testing-library/react-hooks'; +import { + UnifiedHistogramBreakdownContext, + UnifiedHistogramChartContext, + UnifiedHistogramHitsContext, + UnifiedHistogramRequestContext, +} from '../types'; +import { dataViewWithTimefieldMock } from '../__mocks__/data_view_with_timefield'; +import { useRefetchId } from './use_refetch_id'; + +describe('useRefetchId', () => { + const getDeps: () => { + dataView: DataView; + lastReloadRequestTime: number | undefined; + request: UnifiedHistogramRequestContext | undefined; + hits: UnifiedHistogramHitsContext | undefined; + chart: UnifiedHistogramChartContext | undefined; + chartVisible: boolean; + breakdown: UnifiedHistogramBreakdownContext | undefined; + filters: Filter[]; + query: Query | AggregateQuery; + relativeTimeRange: TimeRange; + } = () => ({ + dataView: dataViewWithTimefieldMock, + lastReloadRequestTime: 0, + request: undefined, + hits: undefined, + chart: undefined, + chartVisible: true, + breakdown: undefined, + filters: [], + query: { language: 'kuery', query: '' }, + relativeTimeRange: { from: 'now-15m', to: 'now' }, + }); + + it('should increment the refetchId when any of the arguments change', () => { + const hook = renderHook((props) => useRefetchId(props), { initialProps: getDeps() }); + expect(hook.result.current).toBe(0); + hook.rerender(getDeps()); + expect(hook.result.current).toBe(0); + hook.rerender({ + ...getDeps(), + lastReloadRequestTime: 1, + }); + expect(hook.result.current).toBe(1); + hook.rerender({ + ...getDeps(), + lastReloadRequestTime: 1, + }); + expect(hook.result.current).toBe(1); + hook.rerender({ + ...getDeps(), + lastReloadRequestTime: 1, + query: { language: 'kuery', query: 'foo' }, + }); + expect(hook.result.current).toBe(2); + }); +}); diff --git a/src/plugins/unified_histogram/public/chart/use_refetch_id.ts b/src/plugins/unified_histogram/public/chart/use_refetch_id.ts new file mode 100644 index 0000000000000..4415be9ccd8b6 --- /dev/null +++ b/src/plugins/unified_histogram/public/chart/use_refetch_id.ts @@ -0,0 +1,121 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { DataView } from '@kbn/data-views-plugin/common'; +import type { AggregateQuery, Filter, Query, TimeRange } from '@kbn/es-query'; +import { cloneDeep, isEqual } from 'lodash'; +import { useEffect, useRef, useState } from 'react'; +import type { + UnifiedHistogramBreakdownContext, + UnifiedHistogramChartContext, + UnifiedHistogramHitsContext, + UnifiedHistogramRequestContext, +} from '../types'; + +export const useRefetchId = ({ + dataView, + lastReloadRequestTime, + request, + hits, + chart, + chartVisible, + breakdown, + filters, + query, + relativeTimeRange: relativeTimeRange, +}: { + dataView: DataView; + lastReloadRequestTime: number | undefined; + request: UnifiedHistogramRequestContext | undefined; + hits: UnifiedHistogramHitsContext | undefined; + chart: UnifiedHistogramChartContext | undefined; + chartVisible: boolean; + breakdown: UnifiedHistogramBreakdownContext | undefined; + filters: Filter[]; + query: Query | AggregateQuery; + relativeTimeRange: TimeRange; +}) => { + const refetchDeps = useRef>(); + const [refetchId, setRefetchId] = useState(0); + + // When the unified histogram props change, we must compare the current subset + // that should trigger a histogram refetch against the previous subset. If they + // are different, we must refetch the histogram to ensure it's up to date. + useEffect(() => { + const newRefetchDeps = getRefetchDeps({ + dataView, + lastReloadRequestTime, + request, + hits, + chart, + chartVisible, + breakdown, + filters, + query, + relativeTimeRange, + }); + + if (!isEqual(refetchDeps.current, newRefetchDeps)) { + if (refetchDeps.current) { + setRefetchId((id) => id + 1); + } + + refetchDeps.current = newRefetchDeps; + } + }, [ + breakdown, + chart, + chartVisible, + dataView, + filters, + hits, + lastReloadRequestTime, + query, + request, + relativeTimeRange, + ]); + + return refetchId; +}; + +const getRefetchDeps = ({ + dataView, + lastReloadRequestTime, + request, + hits, + chart, + chartVisible, + breakdown, + filters, + query, + relativeTimeRange, +}: { + dataView: DataView; + lastReloadRequestTime: number | undefined; + request: UnifiedHistogramRequestContext | undefined; + hits: UnifiedHistogramHitsContext | undefined; + chart: UnifiedHistogramChartContext | undefined; + chartVisible: boolean; + breakdown: UnifiedHistogramBreakdownContext | undefined; + filters: Filter[]; + query: Query | AggregateQuery; + relativeTimeRange: TimeRange; +}) => + cloneDeep([ + dataView.id, + lastReloadRequestTime, + request?.searchSessionId, + Boolean(hits), + chartVisible, + chart?.timeInterval, + Boolean(breakdown), + breakdown?.field, + filters, + query, + relativeTimeRange, + ]); diff --git a/src/plugins/unified_histogram/public/chart/use_request_params.tsx b/src/plugins/unified_histogram/public/chart/use_request_params.tsx new file mode 100644 index 0000000000000..defa2bdd920d9 --- /dev/null +++ b/src/plugins/unified_histogram/public/chart/use_request_params.tsx @@ -0,0 +1,58 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { connectToQueryState, QueryState } from '@kbn/data-plugin/public'; +import { createStateContainer, useContainerState } from '@kbn/kibana-utils-plugin/public'; +import { useEffect, useMemo, useRef } from 'react'; +import type { UnifiedHistogramRequestContext, UnifiedHistogramServices } from '../types'; + +export const useRequestParams = ({ + services, + lastReloadRequestTime, + request, +}: { + services: UnifiedHistogramServices; + lastReloadRequestTime: number | undefined; + request?: UnifiedHistogramRequestContext; +}) => { + const { data } = services; + + const queryStateContainer = useRef( + createStateContainer({ + filters: data.query.filterManager.getFilters(), + query: data.query.queryString.getQuery(), + refreshInterval: data.query.timefilter.timefilter.getRefreshInterval(), + time: data.query.timefilter.timefilter.getTime(), + }) + ).current; + + const queryState = useContainerState(queryStateContainer); + + useEffect(() => { + return connectToQueryState(data.query, queryStateContainer, { + time: true, + query: true, + filters: true, + refreshInterval: true, + }); + }, [data.query, queryStateContainer]); + + const filters = useMemo(() => queryState.filters ?? [], [queryState.filters]); + + const query = useMemo( + () => queryState.query ?? data.query.queryString.getDefaultQuery(), + [data.query.queryString, queryState.query] + ); + + const relativeTimeRange = useMemo( + () => queryState.time ?? data.query.timefilter.timefilter.getTimeDefaults(), + [data.query.timefilter.timefilter, queryState.time] + ); + + return { filters, query, relativeTimeRange }; +}; diff --git a/src/plugins/unified_histogram/public/chart/use_time_range.test.tsx b/src/plugins/unified_histogram/public/chart/use_time_range.test.tsx new file mode 100644 index 0000000000000..26070db1c7e54 --- /dev/null +++ b/src/plugins/unified_histogram/public/chart/use_time_range.test.tsx @@ -0,0 +1,239 @@ +/* + * Copyright 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 { uiSettingsServiceMock } from '@kbn/core-ui-settings-browser-mocks'; +import { TimeRange } from '@kbn/data-plugin/common'; +import { renderHook } from '@testing-library/react-hooks'; +import { UnifiedHistogramBucketInterval } from '../types'; +import { useTimeRange } from './use_time_range'; + +jest.mock('@kbn/datemath', () => ({ + parse: jest.fn((datetime: string) => { + return { + format: jest.fn(() => { + return datetime; + }), + }; + }), +})); + +describe('useTimeRange', () => { + const uiSettings = uiSettingsServiceMock.createStartContract(); + uiSettings.get.mockReturnValue('dateFormat'); + const bucketInterval: UnifiedHistogramBucketInterval = { + description: '1 minute', + }; + const timeRange: TimeRange = { + from: '2022-11-17T00:00:00.000Z', + to: '2022-11-17T12:00:00.000Z', + }; + const timeInterval = 'auto'; + + it('should return time range text', () => { + const { result } = renderHook(() => + useTimeRange({ + uiSettings, + bucketInterval, + timeRange, + timeInterval, + }) + ); + expect(result.current.timeRangeText).toMatchInlineSnapshot( + `"2022-11-17T00:00:00.000Z - 2022-11-17T12:00:00.000Z (interval: Auto - 1 minute)"` + ); + }); + + it('should return time range text when timeInterval is not auto', () => { + const { result } = renderHook(() => + useTimeRange({ + uiSettings, + bucketInterval, + timeRange, + timeInterval: '1m', + }) + ); + expect(result.current.timeRangeText).toMatchInlineSnapshot( + `"2022-11-17T00:00:00.000Z - 2022-11-17T12:00:00.000Z (interval: 1 minute)"` + ); + }); + + it('should return time range text when bucketInterval is undefined', () => { + const { result } = renderHook(() => + useTimeRange({ + uiSettings, + timeRange, + timeInterval, + }) + ); + expect(result.current.timeRangeText).toMatchInlineSnapshot( + `"2022-11-17T00:00:00.000Z - 2022-11-17T12:00:00.000Z (interval: Auto - Loading)"` + ); + }); + + it('should render time range display', () => { + const { result } = renderHook(() => + useTimeRange({ + uiSettings, + bucketInterval, + timeRange, + timeInterval, + }) + ); + expect(result.current.timeRangeDisplay).toMatchInlineSnapshot(` + + 2022-11-17T00:00:00.000Z - 2022-11-17T12:00:00.000Z (interval: Auto - 1 minute) + + `); + }); + + it('should render time range display when buckets are too large', () => { + const { result } = renderHook(() => + useTimeRange({ + uiSettings, + bucketInterval: { + ...bucketInterval, + scaled: true, + scale: 2, + }, + timeRange, + timeInterval, + }) + ); + expect(result.current.timeRangeDisplay).toMatchInlineSnapshot(` + + + + 2022-11-17T00:00:00.000Z - 2022-11-17T12:00:00.000Z (interval: Auto - 1 minute) + + + + + + + `); + }); + + it('should render time range display when there are too many buckets', () => { + const { result } = renderHook(() => + useTimeRange({ + uiSettings, + bucketInterval: { + ...bucketInterval, + scaled: true, + scale: 0.5, + }, + timeRange, + timeInterval, + }) + ); + expect(result.current.timeRangeDisplay).toMatchInlineSnapshot(` + + + + 2022-11-17T00:00:00.000Z - 2022-11-17T12:00:00.000Z (interval: Auto - 1 minute) + + + + + + + `); + }); +}); diff --git a/src/plugins/unified_histogram/public/chart/use_time_range.tsx b/src/plugins/unified_histogram/public/chart/use_time_range.tsx new file mode 100644 index 0000000000000..539f32251b832 --- /dev/null +++ b/src/plugins/unified_histogram/public/chart/use_time_range.tsx @@ -0,0 +1,127 @@ +/* + * Copyright 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 { EuiFlexGroup, EuiFlexItem, EuiIconTip, EuiText, useEuiTheme } from '@elastic/eui'; +import { css } from '@emotion/react'; +import type { IUiSettingsClient } from '@kbn/core-ui-settings-browser'; +import { i18n } from '@kbn/i18n'; +import React, { useCallback, useMemo } from 'react'; +import dateMath from '@kbn/datemath'; +import type { TimeRange } from '@kbn/data-plugin/common'; +import type { UnifiedHistogramBucketInterval } from '../types'; + +export const useTimeRange = ({ + uiSettings, + bucketInterval, + timeRange: { from, to }, + timeInterval, +}: { + uiSettings: IUiSettingsClient; + bucketInterval?: UnifiedHistogramBucketInterval; + timeRange: TimeRange; + timeInterval?: string; +}) => { + const dateFormat = useMemo(() => uiSettings.get('dateFormat'), [uiSettings]); + + const toMoment = useCallback( + (datetime?: moment.Moment) => { + if (!datetime) { + return ''; + } + if (!dateFormat) { + return String(datetime); + } + return datetime.format(dateFormat); + }, + [dateFormat] + ); + + const timeRangeText = useMemo(() => { + const timeRange = { + from: dateMath.parse(from), + to: dateMath.parse(to, { roundUp: true }), + }; + + const intervalText = i18n.translate('unifiedHistogram.histogramTimeRangeIntervalDescription', { + defaultMessage: '(interval: {value})', + values: { + value: `${ + timeInterval === 'auto' + ? `${i18n.translate('unifiedHistogram.histogramTimeRangeIntervalAuto', { + defaultMessage: 'Auto', + })} - ` + : '' + }${ + bucketInterval?.description ?? + i18n.translate('unifiedHistogram.histogramTimeRangeIntervalLoading', { + defaultMessage: 'Loading', + }) + }`, + }, + }); + + return `${toMoment(timeRange.from)} - ${toMoment(timeRange.to)} ${intervalText}`; + }, [bucketInterval, from, timeInterval, to, toMoment]); + + const { euiTheme } = useEuiTheme(); + const timeRangeCss = css` + padding: 0 ${euiTheme.size.s} 0 ${euiTheme.size.s}; + `; + + let timeRangeDisplay = ( + + {timeRangeText} + + ); + + if (bucketInterval?.scaled) { + const toolTipTitle = i18n.translate('unifiedHistogram.timeIntervalWithValueWarning', { + defaultMessage: 'Warning', + }); + + const toolTipContent = i18n.translate('unifiedHistogram.bucketIntervalTooltip', { + defaultMessage: + 'This interval creates {bucketsDescription} to show in the selected time range, so it has been scaled to {bucketIntervalDescription}.', + values: { + bucketsDescription: + bucketInterval.scale && bucketInterval.scale > 1 + ? i18n.translate('unifiedHistogram.bucketIntervalTooltip.tooLargeBucketsText', { + defaultMessage: 'buckets that are too large', + }) + : i18n.translate('unifiedHistogram.bucketIntervalTooltip.tooManyBucketsText', { + defaultMessage: 'too many buckets', + }), + bucketIntervalDescription: bucketInterval.description, + }, + }); + + const timeRangeWrapperCss = css` + flex-grow: 0; + `; + + timeRangeDisplay = ( + + {timeRangeDisplay} + + + + + ); + } + + return { + timeRangeText, + timeRangeDisplay, + }; +}; diff --git a/src/plugins/unified_histogram/public/chart/use_total_hits.test.ts b/src/plugins/unified_histogram/public/chart/use_total_hits.test.ts new file mode 100644 index 0000000000000..4782df3683fcb --- /dev/null +++ b/src/plugins/unified_histogram/public/chart/use_total_hits.test.ts @@ -0,0 +1,212 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 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 { Filter } from '@kbn/es-query'; +import { UnifiedHistogramFetchStatus } from '../types'; +import { dataViewWithTimefieldMock } from '../__mocks__/data_view_with_timefield'; +import { useTotalHits } from './use_total_hits'; +import { useEffect as mockUseEffect } from 'react'; +import { renderHook } from '@testing-library/react-hooks'; +import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; +import { searchSourceInstanceMock } from '@kbn/data-plugin/common/search/search_source/mocks'; +import { of, throwError } from 'rxjs'; +import { waitFor } from '@testing-library/dom'; +import { RequestAdapter } from '@kbn/inspector-plugin/common'; +import { DataViewType, SearchSourceSearchOptions } from '@kbn/data-plugin/common'; + +jest.mock('react-use/lib/useDebounce', () => { + return jest.fn((...args) => { + mockUseEffect(args[0], args[2]); + }); +}); + +describe('useTotalHits', () => { + const getDeps = () => ({ + services: { data: dataPluginMock.createStartContract() } as any, + dataView: dataViewWithTimefieldMock, + lastReloadRequestTime: undefined, + request: undefined, + hits: { + status: UnifiedHistogramFetchStatus.uninitialized, + total: undefined, + }, + chart: { + hidden: true, + timeInterval: 'auto', + }, + chartVisible: false, + breakdown: undefined, + filters: [], + query: { query: '', language: 'kuery' }, + timeRange: { from: 'now-15m', to: 'now' }, + refetchId: 0, + onTotalHitsChange: jest.fn(), + }); + + it('should fetch total hits on first execution', async () => { + const onTotalHitsChange = jest.fn(); + let fetchOptions: SearchSourceSearchOptions | undefined; + const fetchSpy = jest + .spyOn(searchSourceInstanceMock, 'fetch$') + .mockClear() + .mockImplementation((options) => { + fetchOptions = options; + return of({ + isRunning: false, + isPartial: false, + rawResponse: { + hits: { + total: 42, + }, + }, + }) as any; + }); + const setFieldSpy = jest.spyOn(searchSourceInstanceMock, 'setField').mockClear(); + const data = dataPluginMock.createStartContract(); + const timeRange = { from: 'now-15m', to: 'now' }; + jest + .spyOn(data.query.timefilter.timefilter, 'createFilter') + .mockClear() + .mockReturnValue(timeRange as any); + const query = { query: 'test query', language: 'kuery' }; + const filters: Filter[] = [{ meta: { index: 'test' }, query: { match_all: {} } }]; + const adapter = new RequestAdapter(); + renderHook(() => + useTotalHits({ + ...getDeps(), + services: { data } as any, + request: { + searchSessionId: '123', + adapter, + }, + query, + filters, + timeRange, + onTotalHitsChange, + }) + ); + expect(onTotalHitsChange).toBeCalledTimes(1); + expect(onTotalHitsChange).toBeCalledWith(UnifiedHistogramFetchStatus.loading, undefined); + expect(setFieldSpy).toHaveBeenCalledWith('index', dataViewWithTimefieldMock); + expect(setFieldSpy).toHaveBeenCalledWith('query', query); + expect(setFieldSpy).toHaveBeenCalledWith('size', 0); + expect(setFieldSpy).toHaveBeenCalledWith('trackTotalHits', true); + expect(setFieldSpy).toHaveBeenCalledWith('filter', [...filters, timeRange]); + expect(fetchSpy).toHaveBeenCalled(); + expect(fetchOptions?.inspector?.adapter).toBe(adapter); + expect(fetchOptions?.sessionId).toBe('123'); + expect(fetchOptions?.abortSignal).toBeInstanceOf(AbortSignal); + expect(fetchOptions?.executionContext?.description).toBe('fetch total hits'); + await waitFor(() => { + expect(onTotalHitsChange).toBeCalledTimes(2); + expect(onTotalHitsChange).toBeCalledWith(UnifiedHistogramFetchStatus.complete, 42); + }); + }); + + it('should not fetch total hits if chartVisible is true', async () => { + const onTotalHitsChange = jest.fn(); + const fetchSpy = jest.spyOn(searchSourceInstanceMock, 'fetch$').mockClear(); + const setFieldSpy = jest.spyOn(searchSourceInstanceMock, 'setField').mockClear(); + renderHook(() => useTotalHits({ ...getDeps(), chartVisible: true, onTotalHitsChange })); + expect(onTotalHitsChange).toBeCalledTimes(0); + expect(setFieldSpy).not.toHaveBeenCalled(); + expect(fetchSpy).not.toHaveBeenCalled(); + }); + + it('should not fetch total hits if hits is undefined', async () => { + const onTotalHitsChange = jest.fn(); + const fetchSpy = jest.spyOn(searchSourceInstanceMock, 'fetch$').mockClear(); + const setFieldSpy = jest.spyOn(searchSourceInstanceMock, 'setField').mockClear(); + renderHook(() => useTotalHits({ ...getDeps(), hits: undefined, onTotalHitsChange })); + expect(onTotalHitsChange).toBeCalledTimes(0); + expect(setFieldSpy).not.toHaveBeenCalled(); + expect(fetchSpy).not.toHaveBeenCalled(); + }); + + it('should not fetch a second time if fetchId is the same', async () => { + const onTotalHitsChange = jest.fn(); + const fetchSpy = jest.spyOn(searchSourceInstanceMock, 'fetch$').mockClear(); + const setFieldSpy = jest.spyOn(searchSourceInstanceMock, 'setField').mockClear(); + const options = { ...getDeps(), refetchId: 0, onTotalHitsChange }; + const { rerender } = renderHook(() => useTotalHits(options)); + expect(onTotalHitsChange).toBeCalledTimes(1); + expect(setFieldSpy).toHaveBeenCalled(); + expect(fetchSpy).toHaveBeenCalled(); + await waitFor(() => { + expect(onTotalHitsChange).toBeCalledTimes(2); + }); + rerender(); + expect(onTotalHitsChange).toBeCalledTimes(2); + expect(setFieldSpy).toHaveBeenCalledTimes(5); + expect(fetchSpy).toHaveBeenCalledTimes(1); + }); + + it('should fetch a second time if fetchId is different', async () => { + const abortSpy = jest.spyOn(AbortController.prototype, 'abort').mockClear(); + const onTotalHitsChange = jest.fn(); + const fetchSpy = jest.spyOn(searchSourceInstanceMock, 'fetch$').mockClear(); + const setFieldSpy = jest.spyOn(searchSourceInstanceMock, 'setField').mockClear(); + const options = { ...getDeps(), refetchId: 0, onTotalHitsChange }; + const { rerender } = renderHook(() => useTotalHits(options)); + expect(onTotalHitsChange).toBeCalledTimes(1); + expect(setFieldSpy).toHaveBeenCalled(); + expect(fetchSpy).toHaveBeenCalled(); + await waitFor(() => { + expect(onTotalHitsChange).toBeCalledTimes(2); + }); + options.refetchId = 1; + rerender(); + expect(abortSpy).toHaveBeenCalled(); + expect(onTotalHitsChange).toBeCalledTimes(3); + expect(setFieldSpy).toHaveBeenCalledTimes(10); + expect(fetchSpy).toHaveBeenCalledTimes(2); + await waitFor(() => { + expect(onTotalHitsChange).toBeCalledTimes(4); + }); + }); + + it('should call onTotalHitsChange with an error status if fetch fails', async () => { + const onTotalHitsChange = jest.fn(); + const error = new Error('test error'); + jest + .spyOn(searchSourceInstanceMock, 'fetch$') + .mockClear() + .mockReturnValue(throwError(() => error)); + renderHook(() => useTotalHits({ ...getDeps(), onTotalHitsChange })); + await waitFor(() => { + expect(onTotalHitsChange).toBeCalledTimes(2); + expect(onTotalHitsChange).toBeCalledWith(UnifiedHistogramFetchStatus.error, error); + }); + }); + + it('should call searchSource.setOverwriteDataViewType if dataView is a rollup', async () => { + const setOverwriteDataViewTypeSpy = jest + .spyOn(searchSourceInstanceMock, 'setOverwriteDataViewType') + .mockClear(); + const setFieldSpy = jest.spyOn(searchSourceInstanceMock, 'setField').mockClear(); + const data = dataPluginMock.createStartContract(); + const timeRange = { from: 'now-15m', to: 'now' }; + jest + .spyOn(data.query.timefilter.timefilter, 'createFilter') + .mockClear() + .mockReturnValue(timeRange as any); + const filters: Filter[] = [{ meta: { index: 'test' }, query: { match_all: {} } }]; + renderHook(() => + useTotalHits({ + ...getDeps(), + dataView: { + ...dataViewWithTimefieldMock, + type: DataViewType.ROLLUP, + } as any, + filters, + }) + ); + expect(setOverwriteDataViewTypeSpy).toHaveBeenCalledWith(undefined); + expect(setFieldSpy).toHaveBeenCalledWith('filter', filters); + }); +}); diff --git a/src/plugins/unified_histogram/public/chart/use_total_hits.ts b/src/plugins/unified_histogram/public/chart/use_total_hits.ts new file mode 100644 index 0000000000000..3f24b642c81bf --- /dev/null +++ b/src/plugins/unified_histogram/public/chart/use_total_hits.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 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 { isCompleteResponse } from '@kbn/data-plugin/public'; +import { DataView, DataViewType } from '@kbn/data-views-plugin/public'; +import type { AggregateQuery, Filter, Query, TimeRange } from '@kbn/es-query'; +import { i18n } from '@kbn/i18n'; +import { MutableRefObject, useRef } from 'react'; +import useDebounce from 'react-use/lib/useDebounce'; +import { catchError, filter, lastValueFrom, map, of } from 'rxjs'; +import { + UnifiedHistogramBreakdownContext, + UnifiedHistogramChartContext, + UnifiedHistogramFetchStatus, + UnifiedHistogramHitsContext, + UnifiedHistogramRequestContext, + UnifiedHistogramServices, +} from '../types'; +import { REQUEST_DEBOUNCE_MS } from './consts'; + +export const useTotalHits = ({ + services, + dataView, + lastReloadRequestTime, + request, + hits, + chart, + chartVisible, + breakdown, + filters, + query, + timeRange, + refetchId, + onTotalHitsChange, +}: { + services: UnifiedHistogramServices; + dataView: DataView; + lastReloadRequestTime: number | undefined; + request: UnifiedHistogramRequestContext | undefined; + hits: UnifiedHistogramHitsContext | undefined; + chart: UnifiedHistogramChartContext | undefined; + chartVisible: boolean; + breakdown: UnifiedHistogramBreakdownContext | undefined; + filters: Filter[]; + query: Query | AggregateQuery; + timeRange: TimeRange; + refetchId: number; + onTotalHitsChange?: (status: UnifiedHistogramFetchStatus, result?: number | Error) => void; +}) => { + const abortController = useRef(); + + useDebounce( + () => { + fetchTotalHits({ + services, + abortController, + dataView, + request, + hits, + chartVisible, + filters, + query, + timeRange, + onTotalHitsChange, + }); + }, + REQUEST_DEBOUNCE_MS, + [onTotalHitsChange, refetchId, services] + ); +}; + +const fetchTotalHits = async ({ + services: { data }, + abortController, + dataView, + request, + hits, + chartVisible, + filters: originalFilters, + query, + timeRange, + onTotalHitsChange, +}: { + services: UnifiedHistogramServices; + abortController: MutableRefObject; + dataView: DataView; + request: UnifiedHistogramRequestContext | undefined; + hits: UnifiedHistogramHitsContext | undefined; + chartVisible: boolean; + filters: Filter[]; + query: Query | AggregateQuery; + timeRange: TimeRange; + onTotalHitsChange?: (status: UnifiedHistogramFetchStatus, result?: number | Error) => void; +}) => { + abortController.current?.abort(); + abortController.current = undefined; + + // Either the chart is visible, in which case Lens will make the request, + // or there is no hits context, which means the total hits should be hidden + if (chartVisible || !hits) { + return; + } + + onTotalHitsChange?.(UnifiedHistogramFetchStatus.loading, hits.total); + + const searchSource = data.search.searchSource.createEmpty(); + + searchSource + .setField('index', dataView) + .setField('query', query) + .setField('size', 0) + .setField('trackTotalHits', true); + + let filters = originalFilters; + + if (dataView.type === DataViewType.ROLLUP) { + // We treat that data view as "normal" even if it was a rollup data view, + // since the rollup endpoint does not support querying individual documents, but we + // can get them from the regular _search API that will be used if the data view + // not a rollup data view. + searchSource.setOverwriteDataViewType(undefined); + } else { + // Set the date range filter fields from timeFilter using the absolute format. + // Search sessions requires that it be converted from a relative range + const timeFilter = data.query.timefilter.timefilter.createFilter(dataView, timeRange); + + if (timeFilter) { + filters = [...filters, timeFilter]; + } + } + + searchSource.setField('filter', filters); + + abortController.current = new AbortController(); + + // Let the consumer inspect the request if they want to track it + const inspector = request?.adapter + ? { + adapter: request.adapter, + title: i18n.translate('unifiedHistogram.inspectorRequestDataTitleTotalHits', { + defaultMessage: 'Total hits', + }), + description: i18n.translate('unifiedHistogram.inspectorRequestDescriptionTotalHits', { + defaultMessage: 'This request queries Elasticsearch to fetch the total hits.', + }), + } + : undefined; + + const fetch$ = searchSource + .fetch$({ + inspector, + sessionId: request?.searchSessionId, + abortSignal: abortController.current.signal, + executionContext: { + description: 'fetch total hits', + }, + }) + .pipe( + filter((res) => isCompleteResponse(res)), + map((res) => res.rawResponse.hits.total as number), + catchError((error: Error) => of(error)) + ); + + const result = await lastValueFrom(fetch$); + + const resultStatus = + result instanceof Error + ? UnifiedHistogramFetchStatus.error + : UnifiedHistogramFetchStatus.complete; + + onTotalHitsChange?.(resultStatus, result); +}; diff --git a/src/plugins/unified_histogram/public/hits_counter/hits_counter.test.tsx b/src/plugins/unified_histogram/public/hits_counter/hits_counter.test.tsx index d094fef953af8..03b350448e9c2 100644 --- a/src/plugins/unified_histogram/public/hits_counter/hits_counter.test.tsx +++ b/src/plugins/unified_histogram/public/hits_counter/hits_counter.test.tsx @@ -13,6 +13,7 @@ import type { HitsCounterProps } from './hits_counter'; import { HitsCounter } from './hits_counter'; import { findTestSubject } from '@elastic/eui/lib/test'; import { EuiLoadingSpinner } from '@elastic/eui'; +import { UnifiedHistogramFetchStatus } from '../types'; describe('hits counter', function () { let props: HitsCounterProps; @@ -21,7 +22,7 @@ describe('hits counter', function () { beforeAll(() => { props = { hits: { - status: 'complete', + status: UnifiedHistogramFetchStatus.complete, total: 2, }, }; @@ -35,7 +36,10 @@ describe('hits counter', function () { it('expect to render 1,899 hits if 1899 hits given', function () { component = mountWithIntl( - + ); const hits = findTestSubject(component, 'unifiedHistogramQueryHits'); expect(hits.text()).toBe('1,899'); @@ -48,12 +52,16 @@ describe('hits counter', function () { }); it('should render a EuiLoadingSpinner when status is partial', () => { - component = mountWithIntl(); + component = mountWithIntl( + + ); expect(component.find(EuiLoadingSpinner).length).toBe(1); }); it('should render unifiedHistogramQueryHitsPartial when status is partial', () => { - component = mountWithIntl(); + component = mountWithIntl( + + ); expect(component.find('[data-test-subj="unifiedHistogramQueryHitsPartial"]').length).toBe(1); }); diff --git a/src/plugins/unified_histogram/public/hits_counter/hits_counter.tsx b/src/plugins/unified_histogram/public/hits_counter/hits_counter.tsx index 39df40650557c..b6f1212bfeaed 100644 --- a/src/plugins/unified_histogram/public/hits_counter/hits_counter.tsx +++ b/src/plugins/unified_histogram/public/hits_counter/hits_counter.tsx @@ -37,6 +37,9 @@ export function HitsCounter({ hits, append }: HitsCounterProps) { const hitsCounterCss = css` flex-grow: 0; `; + const hitsCounterTextCss = css` + overflow: hidden; + `; return ( - - + + {hits.status === 'partial' && ( new UnifiedHistogramPublicPlugin(); diff --git a/src/plugins/unified_histogram/public/layout/layout.test.tsx b/src/plugins/unified_histogram/public/layout/layout.test.tsx index 3cb3fb254ecf7..d77bbfa05be30 100644 --- a/src/plugins/unified_histogram/public/layout/layout.test.tsx +++ b/src/plugins/unified_histogram/public/layout/layout.test.tsx @@ -6,13 +6,20 @@ * Side Public License, v 1. */ +import { searchSourceInstanceMock } from '@kbn/data-plugin/common/search/search_source/mocks'; import { mountWithIntl } from '@kbn/test-jest-helpers'; import type { ReactWrapper } from 'enzyme'; import React from 'react'; import { act } from 'react-dom/test-utils'; +import { of } from 'rxjs'; import { Chart } from '../chart'; import { Panels, PANELS_MODE } from '../panels'; -import type { UnifiedHistogramChartContext, UnifiedHistogramHitsContext } from '../types'; +import { + UnifiedHistogramChartContext, + UnifiedHistogramFetchStatus, + UnifiedHistogramHitsContext, +} from '../types'; +import { dataViewWithTimefieldMock } from '../__mocks__/data_view_with_timefield'; import { unifiedHistogramServicesMock } from '../__mocks__/services'; import { UnifiedHistogramLayout, UnifiedHistogramLayoutProps } from './layout'; @@ -30,19 +37,13 @@ jest.mock('@elastic/eui', () => { describe('Layout', () => { const createHits = (): UnifiedHistogramHitsContext => ({ - status: 'complete', + status: UnifiedHistogramFetchStatus.complete, total: 10, }); const createChart = (): UnifiedHistogramChartContext => ({ - status: 'complete', hidden: false, timeInterval: 'auto', - bucketInterval: { - scaled: true, - description: 'test', - scale: 2, - }, }); const mountComponent = async ({ @@ -59,12 +60,21 @@ describe('Layout', () => { return { from: '2020-05-14T11:05:13.590', to: '2020-05-14T11:20:13.590' }; }; + (services.data.query.queryString.getDefaultQuery as jest.Mock).mockReturnValue({ + language: 'kuery', + query: '', + }); + (searchSourceInstanceMock.fetch$ as jest.Mock).mockImplementation( + jest.fn().mockReturnValue(of({ rawResponse: { hits: { total: 2 } } })) + ); + const component = mountWithIntl( ); diff --git a/src/plugins/unified_histogram/public/layout/layout.tsx b/src/plugins/unified_histogram/public/layout/layout.tsx index 229d8a922e465..87d4170a1035f 100644 --- a/src/plugins/unified_histogram/public/layout/layout.tsx +++ b/src/plugins/unified_histogram/public/layout/layout.tsx @@ -11,17 +11,41 @@ import type { PropsWithChildren, ReactElement, RefObject } from 'react'; import React, { useMemo } from 'react'; import { createHtmlPortalNode, InPortal, OutPortal } from 'react-reverse-portal'; import { css } from '@emotion/css'; +import type { DataView, DataViewField } from '@kbn/data-views-plugin/public'; +import type { TypedLensByValueInput } from '@kbn/lens-plugin/public'; import { Chart } from '../chart'; import { Panels, PANELS_MODE } from '../panels'; import type { UnifiedHistogramChartContext, UnifiedHistogramServices, UnifiedHistogramHitsContext, + UnifiedHistogramBreakdownContext, + UnifiedHistogramFetchStatus, + UnifiedHistogramRequestContext, + UnifiedHistogramChartLoadEvent, } from '../types'; export interface UnifiedHistogramLayoutProps extends PropsWithChildren { + /** + * Optional class name to add to the layout container + */ className?: string; + /** + * Required services + */ services: UnifiedHistogramServices; + /** + * The current data view + */ + dataView: DataView; + /** + * Can be updated to `Date.now()` to force a refresh + */ + lastReloadRequestTime?: number; + /** + * Context object for requests made by unified histogram components -- optional + */ + request?: UnifiedHistogramRequestContext; /** * Context object for the hits count -- leave undefined to hide the hits count */ @@ -30,6 +54,10 @@ export interface UnifiedHistogramLayoutProps extends PropsWithChildren * Context object for the chart -- leave undefined to hide the chart */ chart?: UnifiedHistogramChartContext; + /** + * Context object for the breakdown -- leave undefined to hide the breakdown + */ + breakdown?: UnifiedHistogramBreakdownContext; /** * Ref to the element wrapping the layout which will be used for resize calculations */ @@ -49,7 +77,7 @@ export interface UnifiedHistogramLayoutProps extends PropsWithChildren /** * Callback to invoke when the user clicks the edit visualization button -- leave undefined to hide the button */ - onEditVisualization?: () => void; + onEditVisualization?: (lensAttributes: TypedLensByValueInput['attributes']) => void; /** * Callback to hide or show the chart -- should set {@link UnifiedHistogramChartContext.hidden} to chartHidden */ @@ -58,13 +86,30 @@ export interface UnifiedHistogramLayoutProps extends PropsWithChildren * Callback to update the time interval -- should set {@link UnifiedHistogramChartContext.timeInterval} to timeInterval */ onTimeIntervalChange?: (timeInterval: string) => void; + /** + * Callback to update the breakdown field -- should set {@link UnifiedHistogramBreakdownContext.field} to breakdownField + */ + onBreakdownFieldChange?: (breakdownField: DataViewField | undefined) => void; + /** + * Callback to update the total hits -- should set {@link UnifiedHistogramHitsContext.status} to status + * and {@link UnifiedHistogramHitsContext.total} to result + */ + onTotalHitsChange?: (status: UnifiedHistogramFetchStatus, result?: number | Error) => void; + /** + * Called when the histogram loading status changes + */ + onChartLoad?: (event: UnifiedHistogramChartLoadEvent) => void; } export const UnifiedHistogramLayout = ({ className, services, + dataView, + lastReloadRequestTime, + request, hits, chart, + breakdown, resizeRef, topPanelHeight, appendHitsCounter, @@ -72,6 +117,9 @@ export const UnifiedHistogramLayout = ({ onEditVisualization, onChartHiddenChange, onTimeIntervalChange, + onBreakdownFieldChange, + onTotalHitsChange, + onChartLoad, children, }: UnifiedHistogramLayoutProps) => { const topPanelNode = useMemo( @@ -88,7 +136,6 @@ export const UnifiedHistogramLayout = ({ const showFixedPanels = isMobile || !chart || chart.hidden; const { euiTheme } = useEuiTheme(); const defaultTopPanelHeight = euiTheme.base * 12; - const minTopPanelHeight = euiTheme.base * 8; const minMainPanelHeight = euiTheme.base * 10; const chartClassName = @@ -119,14 +166,21 @@ export const UnifiedHistogramLayout = ({ : } onEditVisualization={onEditVisualization} onResetChartHeight={onResetChartHeight} onChartHiddenChange={onChartHiddenChange} onTimeIntervalChange={onTimeIntervalChange} + onBreakdownFieldChange={onBreakdownFieldChange} + onTotalHitsChange={onTotalHitsChange} + onChartLoad={onChartLoad} /> {children} @@ -135,7 +189,7 @@ export const UnifiedHistogramLayout = ({ mode={panelsMode} resizeRef={resizeRef} topPanelHeight={currentTopPanelHeight} - minTopPanelHeight={minTopPanelHeight} + minTopPanelHeight={defaultTopPanelHeight} minMainPanelHeight={minMainPanelHeight} topPanel={} mainPanel={} diff --git a/src/plugins/unified_histogram/public/types.ts b/src/plugins/unified_histogram/public/types.ts index 53f81b0819900..a4b253274abde 100644 --- a/src/plugins/unified_histogram/public/types.ts +++ b/src/plugins/unified_histogram/public/types.ts @@ -10,19 +10,21 @@ import type { Theme } from '@kbn/charts-plugin/public/plugin'; import type { IUiSettingsClient } from '@kbn/core/public'; import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; import type { FieldFormatsStart } from '@kbn/field-formats-plugin/public'; -import type { Duration, Moment } from 'moment'; -import type { Unit } from '@kbn/datemath'; -import type { SerializedFieldFormat } from '@kbn/field-formats-plugin/common'; +import type { LensPublicStart } from '@kbn/lens-plugin/public'; +import type { DataViewField } from '@kbn/data-views-plugin/public'; +import type { RequestAdapter } from '@kbn/inspector-plugin/public'; +import type { DefaultInspectorAdapters } from '@kbn/expressions-plugin/common'; /** * The fetch status of a unified histogram request */ -export type UnifiedHistogramFetchStatus = - | 'uninitialized' - | 'loading' - | 'partial' - | 'complete' - | 'error'; +export enum UnifiedHistogramFetchStatus { + uninitialized = 'uninitialized', + loading = 'loading', + partial = 'partial', + complete = 'complete', + error = 'error', +} /** * The services required by the unified histogram components @@ -32,81 +34,46 @@ export interface UnifiedHistogramServices { theme: Theme; uiSettings: IUiSettingsClient; fieldFormats: FieldFormatsStart; + lens: LensPublicStart; } -interface Column { - id: string; - name: string; -} - -interface Row { - [key: string]: number | 'NaN'; -} - -interface Dimension { - accessor: 0 | 1; - format: SerializedFieldFormat<{ pattern: string }>; - label: string; -} - -interface Ordered { - date: true; - interval: Duration; - intervalESUnit: string; - intervalESValue: number; - min: Moment; - max: Moment; -} - -interface HistogramParams { - date: true; - interval: Duration; - intervalESValue: number; - intervalESUnit: Unit; - format: string; - bounds: HistogramParamsBounds; -} - -export interface HistogramParamsBounds { - min: Moment; - max: Moment; -} - -export interface Table { - columns: Column[]; - rows: Row[]; +/** + * The bucketInterval object returned by {@link buildBucketInterval} + */ +export interface UnifiedHistogramBucketInterval { + scaled?: boolean; + description?: string; + scale?: number; } -export interface Dimensions { - x: Dimension & { params: HistogramParams }; - y: Dimension; -} +export type UnifiedHistogramAdapters = Partial; /** - * The chartData object returned by {@link buildChartData} that - * should be used to set {@link UnifiedHistogramChartContext.data} + * Emitted when the histogram loading status changes */ -export interface UnifiedHistogramChartData { - values: Array<{ - x: number; - y: number; - }>; - xAxisOrderedValues: number[]; - xAxisFormat: Dimension['format']; - yAxisFormat: Dimension['format']; - xAxisLabel: Column['name']; - yAxisLabel?: Column['name']; - ordered: Ordered; +export interface UnifiedHistogramChartLoadEvent { + /** + * True if loading is complete + */ + complete: boolean; + /** + * Inspector adapters for the request + */ + adapters: UnifiedHistogramAdapters; } /** - * The bucketInterval object returned by {@link buildChartData} that - * should be used to set {@link UnifiedHistogramChartContext.bucketInterval} + * Context object for requests made by unified histogram components */ -export interface UnifiedHistogramBucketInterval { - scaled?: boolean; - description?: string; - scale?: number; +export interface UnifiedHistogramRequestContext { + /** + * Current search session ID + */ + searchSessionId?: string; + /** + * The adapter to use for requests (does not apply to Lens requests) + */ + adapter?: RequestAdapter; } /** @@ -116,7 +83,7 @@ export interface UnifiedHistogramHitsContext { /** * The fetch status of the hits count request */ - status: UnifiedHistogramFetchStatus; + status?: UnifiedHistogramFetchStatus; /** * The total number of hits */ @@ -127,10 +94,6 @@ export interface UnifiedHistogramHitsContext { * Context object for the chart */ export interface UnifiedHistogramChartContext { - /** - * The fetch status of the chart request - */ - status: UnifiedHistogramFetchStatus; /** * Controls whether or not the chart is hidden */ @@ -140,15 +103,17 @@ export interface UnifiedHistogramChartContext { */ timeInterval?: string; /** - * The bucketInterval object returned by {@link buildChartData} - */ - bucketInterval?: UnifiedHistogramBucketInterval; - /** - * The chartData object returned by {@link buildChartData} + * The chart title -- sets the title property on the Lens chart input */ - data?: UnifiedHistogramChartData; + title?: string; +} + +/** + * Context object for the histogram breakdown + */ +export interface UnifiedHistogramBreakdownContext { /** - * Error from failed chart request + * The field used for the breakdown */ - error?: Error; + field?: DataViewField; } diff --git a/src/plugins/unified_histogram/tsconfig.json b/src/plugins/unified_histogram/tsconfig.json index a275fdc784dbc..9c6213783980c 100644 --- a/src/plugins/unified_histogram/tsconfig.json +++ b/src/plugins/unified_histogram/tsconfig.json @@ -5,12 +5,13 @@ "emitDeclarationOnly": true, "declaration": true, }, - "include": ["common/**/*", "public/**/*", "server/**/*"], + "include": [ "../../../typings/**/*", "common/**/*", "public/**/*", "server/**/*"], "kbn_references": [ { "path": "../../core/tsconfig.json" }, { "path": "../charts/tsconfig.json" }, { "path": "../data/tsconfig.json" }, { "path": "../data_views/tsconfig.json" }, - { "path": "../saved_search/tsconfig.json" } + { "path": "../saved_search/tsconfig.json" }, + { "path": "../../../x-pack/plugins/lens/tsconfig.json" } ] } diff --git a/src/plugins/unified_search/public/query_string_input/no_data_popover.test.tsx b/src/plugins/unified_search/public/query_string_input/no_data_popover.test.tsx index f80fc68494091..8d41fac7ad29e 100644 --- a/src/plugins/unified_search/public/query_string_input/no_data_popover.test.tsx +++ b/src/plugins/unified_search/public/query_string_input/no_data_popover.test.tsx @@ -75,7 +75,7 @@ describe('NoDataPopover', () => { }; const instance = mount(); act(() => { - instance.find(EuiTourStep).prop('footerAction')!.props.onClick(); + instance.find('button[data-test-subj="noDataPopoverDismissButton"]').simulate('click'); }); instance.setProps({ ...props }); expect(props.storage.set).toHaveBeenCalledWith(expect.any(String), true); diff --git a/src/plugins/unified_search/server/autocomplete/autocomplete_service.ts b/src/plugins/unified_search/server/autocomplete/autocomplete_service.ts index 8ab86f8a05d90..d1969c381a7ce 100644 --- a/src/plugins/unified_search/server/autocomplete/autocomplete_service.ts +++ b/src/plugins/unified_search/server/autocomplete/autocomplete_service.ts @@ -7,6 +7,7 @@ */ import moment from 'moment'; +import { clone } from 'lodash'; import { CoreSetup, Plugin, PluginInitializerContext } from '@kbn/core/server'; import { registerRoutes } from './routes'; import { ConfigSchema } from '../../config'; @@ -32,6 +33,7 @@ export class AutocompleteService implements Plugin { terminateAfter: moment.duration(terminateAfter).asMilliseconds(), timeout: moment.duration(timeout).asMilliseconds(), }), + getInitializerContextConfig: () => clone(this.initializerContext.config), }; } diff --git a/src/plugins/unified_search/server/mocks.ts b/src/plugins/unified_search/server/mocks.ts index 7f63abcdaae0c..48708e5f2955e 100644 --- a/src/plugins/unified_search/server/mocks.ts +++ b/src/plugins/unified_search/server/mocks.ts @@ -6,10 +6,32 @@ * Side Public License, v 1. */ +import moment from 'moment'; +import { Observable } from 'rxjs'; +import { ConfigSchema } from '../config'; import { AutocompleteSetup } from './autocomplete'; const autocompleteSetupMock: jest.Mocked = { getAutocompleteSettings: jest.fn(), + // @ts-ignore as it is partially defined because not all fields are needed + getInitializerContextConfig: jest.fn(() => ({ + create: jest.fn( + () => + new Observable((subscribe) => + subscribe.next({ + autocomplete: { + querySuggestions: { enabled: true }, + valueSuggestions: { + enabled: true, + tiers: [], + terminateAfter: moment.duration(), + timeout: moment.duration(), + }, + }, + }) + ) + ), + })), }; function createSetupContract() { diff --git a/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/index.test.ts b/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/index.test.ts index 3f60b6fde0a94..523ed9ddba21c 100644 --- a/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/index.test.ts +++ b/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/index.test.ts @@ -90,7 +90,7 @@ describe('getConfiguration', () => { progression: 'fixed', rangeMax: 100, rangeMin: 0, - rangeType: 'number', + rangeType: 'percent', reverse: false, stops: [ { color: '#F7FBFF', stop: 12.5 }, diff --git a/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/palette.ts b/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/palette.ts index 32187e184d4ef..c92b3780796e9 100644 --- a/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/palette.ts +++ b/src/plugins/vis_types/heatmap/public/convert_to_lens/configurations/palette.ts @@ -37,13 +37,14 @@ export const getPaletteForHeatmap = async (params: HeatmapVisParams) => { true ); const colorsRange: Range[] = [{ from: stop[0], to: stop[stop.length - 1], type: 'range' }]; - const { colorSchema, invertColors, percentageMode } = params; + const { colorSchema, invertColors } = params; + // palette is type of percent, if user wants dynamic calulated ranges const percentageModeConfig = getPercentageModeConfig( { colorsRange, colorSchema, invertColors, - percentageMode, + percentageMode: true, }, false ); diff --git a/src/plugins/vis_types/timeseries/public/application/components/lib/replace_vars.ts b/src/plugins/vis_types/timeseries/public/application/components/lib/replace_vars.ts index d3a63f9f2421d..77ac817d53d28 100644 --- a/src/plugins/vis_types/timeseries/public/application/components/lib/replace_vars.ts +++ b/src/plugins/vis_types/timeseries/public/application/components/lib/replace_vars.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { encode, RisonValue } from 'rison-node'; +import { encode } from '@kbn/rison'; import Handlebars, { ExtendedCompileOptions, compileFnName } from '@kbn/handlebars'; import { i18n } from '@kbn/i18n'; import { emptyLabel } from '../../../../common/empty_label'; @@ -41,7 +41,7 @@ function createSerializationHelper( handlebars.registerHelper( 'rison', - createSerializationHelper('rison', (v) => encode(v as RisonValue)) + createSerializationHelper('rison', (v) => encode(v)) ); handlebars.registerHelper('encodeURIComponent', (component: unknown) => { diff --git a/src/plugins/visualizations/common/locator_location.ts b/src/plugins/visualizations/common/locator_location.ts index c4c86007fd124..e43fc9fcbd5e5 100644 --- a/src/plugins/visualizations/common/locator_location.ts +++ b/src/plugins/visualizations/common/locator_location.ts @@ -10,7 +10,7 @@ import type { Serializable } from '@kbn/utility-types'; import { omitBy } from 'lodash'; import type { ParsedQuery } from 'query-string'; import { stringify } from 'query-string'; -import rison from 'rison-node'; +import rison from '@kbn/rison'; import { isFilterPinned } from '@kbn/es-query'; import { url } from '@kbn/kibana-utils-plugin/common'; import { GLOBAL_STATE_STORAGE_KEY, STATE_STORAGE_KEY, VisualizeConstants } from './constants'; diff --git a/src/plugins/visualizations/public/wizard/agg_based_selection/agg_based_selection.tsx b/src/plugins/visualizations/public/wizard/agg_based_selection/agg_based_selection.tsx index d4d2c1505bf8a..8ee63361321ef 100644 --- a/src/plugins/visualizations/public/wizard/agg_based_selection/agg_based_selection.tsx +++ b/src/plugins/visualizations/public/wizard/agg_based_selection/agg_based_selection.tsx @@ -57,10 +57,12 @@ class AggBasedSelection extends React.Component - +

    + +

    diff --git a/src/plugins/visualizations/public/wizard/group_selection/group_selection.tsx b/src/plugins/visualizations/public/wizard/group_selection/group_selection.tsx index 6bc982a824de1..908c1a621ebc8 100644 --- a/src/plugins/visualizations/public/wizard/group_selection/group_selection.tsx +++ b/src/plugins/visualizations/public/wizard/group_selection/group_selection.tsx @@ -67,10 +67,12 @@ function GroupSelection(props: GroupSelectionProps) { <> - +

    + +

    diff --git a/src/plugins/visualizations/public/wizard/search_selection/search_selection.tsx b/src/plugins/visualizations/public/wizard/search_selection/search_selection.tsx index 5771747794273..89814c0a474a1 100644 --- a/src/plugins/visualizations/public/wizard/search_selection/search_selection.tsx +++ b/src/plugins/visualizations/public/wizard/search_selection/search_selection.tsx @@ -33,16 +33,18 @@ export class SearchSelection extends React.Component { - {' '} - /{' '} - +

    + {' '} + /{' '} + +

    diff --git a/test/api_integration/apis/guided_onboarding/get_config.ts b/test/api_integration/apis/guided_onboarding/get_config.ts new file mode 100644 index 0000000000000..fc96cb81c3816 --- /dev/null +++ b/test/api_integration/apis/guided_onboarding/get_config.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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import expect from '@kbn/expect'; +import type { FtrProviderContext } from '../../ftr_provider_context'; + +const getConfigsPath = '/api/guided_onboarding/configs'; +export default function testGetGuidesState({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + + describe('GET /api/guided_onboarding/configs', () => { + // check that all guides are present + ['testGuide', 'security', 'search', 'observability'].map((guideId) => { + it(`returns config for ${guideId}`, async () => { + const response = await supertest.get(`${getConfigsPath}/${guideId}`).expect(200); + expect(response.body).not.to.be.empty(); + const { config } = response.body; + expect(config).to.not.be.empty(); + }); + }); + }); +} diff --git a/test/api_integration/apis/guided_onboarding/index.ts b/test/api_integration/apis/guided_onboarding/index.ts index c924eafe6bdb1..b2b3c23705763 100644 --- a/test/api_integration/apis/guided_onboarding/index.ts +++ b/test/api_integration/apis/guided_onboarding/index.ts @@ -13,5 +13,6 @@ export default function apiIntegrationTests({ loadTestFile }: FtrProviderContext loadTestFile(require.resolve('./get_state')); loadTestFile(require.resolve('./put_state')); loadTestFile(require.resolve('./get_guides')); + loadTestFile(require.resolve('./get_config')); }); } diff --git a/test/functional/apps/discover/group1/_discover.ts b/test/functional/apps/discover/group1/_discover.ts index 60f2a54dd01fd..1cba5aa4812d8 100644 --- a/test/functional/apps/discover/group1/_discover.ts +++ b/test/functional/apps/discover/group1/_discover.ts @@ -18,7 +18,6 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const kibanaServer = getService('kibanaServer'); const queryBar = getService('queryBar'); const inspector = getService('inspector'); - const elasticChart = getService('elasticChart'); const testSubjects = getService('testSubjects'); const PageObjects = getPageObjects(['common', 'discover', 'header', 'timePicker']); @@ -106,48 +105,6 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { ); }); - it('should modify the time range when the histogram is brushed', async function () { - // this is the number of renderings of the histogram needed when new data is fetched - // this needs to be improved - const renderingCountInc = 2; - const prevRenderingCount = await elasticChart.getVisualizationRenderingCount(); - await PageObjects.timePicker.setDefaultAbsoluteRange(); - await PageObjects.discover.waitUntilSearchingHasFinished(); - await retry.waitFor('chart rendering complete', async () => { - const actualCount = await elasticChart.getVisualizationRenderingCount(); - const expectedCount = prevRenderingCount + renderingCountInc; - log.debug( - `renderings before brushing - actual: ${actualCount} expected: ${expectedCount}` - ); - return actualCount === expectedCount; - }); - let prevRowData = ''; - // to make sure the table is already rendered - await retry.try(async () => { - prevRowData = await PageObjects.discover.getDocTableField(1); - log.debug(`The first timestamp value in doc table before brushing: ${prevRowData}`); - }); - - await PageObjects.discover.brushHistogram(); - await PageObjects.discover.waitUntilSearchingHasFinished(); - await retry.waitFor('chart rendering complete after being brushed', async () => { - const actualCount = await elasticChart.getVisualizationRenderingCount(); - const expectedCount = prevRenderingCount + renderingCountInc * 2; - log.debug( - `renderings after brushing - actual: ${actualCount} expected: ${expectedCount}` - ); - return actualCount === expectedCount; - }); - const newDurationHours = await PageObjects.timePicker.getTimeDurationInHours(); - expect(Math.round(newDurationHours)).to.be(26); - - await retry.waitFor('doc table containing the documents of the brushed range', async () => { - const rowData = await PageObjects.discover.getDocTableField(1); - log.debug(`The first timestamp value in doc table after brushing: ${rowData}`); - return prevRowData !== rowData; - }); - }); - it('should show correct initial chart interval of Auto', async function () { await PageObjects.timePicker.setDefaultAbsoluteRange(); await PageObjects.discover.waitUntilSearchingHasFinished(); @@ -265,26 +222,6 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); }); - describe('empty query', function () { - it('should update the histogram timerange when the query is resubmitted', async function () { - await kibanaServer.uiSettings.update({ - 'timepicker:timeDefaults': '{ "from": "2015-09-18T19:37:13.000Z", "to": "now"}', - }); - await PageObjects.common.navigateToApp('discover'); - await PageObjects.header.awaitKibanaChrome(); - const initialTimeString = await PageObjects.discover.getChartTimespan(); - await queryBar.submitQuery(); - - await retry.waitFor('chart timespan to have changed', async () => { - const refreshedTimeString = await PageObjects.discover.getChartTimespan(); - log.debug( - `Timestamp before: ${initialTimeString}, Timestamp after: ${refreshedTimeString}` - ); - return refreshedTimeString !== initialTimeString; - }); - }); - }); - describe('managing fields', function () { it('should add a field, sort by it, remove it and also sorting by it', async function () { await PageObjects.timePicker.setDefaultAbsoluteRangeViaUiSettings(); diff --git a/test/functional/apps/discover/group1/_discover_histogram.ts b/test/functional/apps/discover/group1/_discover_histogram.ts index 12effb75cb7f3..70a1fba5afafc 100644 --- a/test/functional/apps/discover/group1/_discover_histogram.ts +++ b/test/functional/apps/discover/group1/_discover_histogram.ts @@ -23,6 +23,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const testSubjects = getService('testSubjects'); const browser = getService('browser'); const retry = getService('retry'); + const log = getService('log'); + const queryBar = getService('queryBar'); describe('discover histogram', function describeIndexTests() { before(async () => { @@ -52,6 +54,69 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { } } + it('should modify the time range when the histogram is brushed', async function () { + await PageObjects.common.navigateToApp('discover'); + await PageObjects.discover.waitUntilSearchingHasFinished(); + await PageObjects.timePicker.setDefaultAbsoluteRange(); + await PageObjects.discover.waitUntilSearchingHasFinished(); + // this is the number of renderings of the histogram needed when new data is fetched + let renderingCountInc = 1; + const prevRenderingCount = await elasticChart.getVisualizationRenderingCount(); + await PageObjects.timePicker.setDefaultAbsoluteRange(); + await PageObjects.discover.waitUntilSearchingHasFinished(); + await retry.waitFor('chart rendering complete', async () => { + const actualCount = await elasticChart.getVisualizationRenderingCount(); + const expectedCount = prevRenderingCount + renderingCountInc; + log.debug(`renderings before brushing - actual: ${actualCount} expected: ${expectedCount}`); + return actualCount === expectedCount; + }); + let prevRowData = ''; + // to make sure the table is already rendered + await retry.try(async () => { + prevRowData = await PageObjects.discover.getDocTableField(1); + log.debug(`The first timestamp value in doc table before brushing: ${prevRowData}`); + }); + + await PageObjects.discover.brushHistogram(); + await PageObjects.discover.waitUntilSearchingHasFinished(); + renderingCountInc = 2; + await retry.waitFor('chart rendering complete after being brushed', async () => { + const actualCount = await elasticChart.getVisualizationRenderingCount(); + const expectedCount = prevRenderingCount + renderingCountInc * 2; + log.debug(`renderings after brushing - actual: ${actualCount} expected: ${expectedCount}`); + return actualCount <= expectedCount; + }); + const newDurationHours = await PageObjects.timePicker.getTimeDurationInHours(); + expect(Math.round(newDurationHours)).to.be(26); + + await retry.waitFor('doc table containing the documents of the brushed range', async () => { + const rowData = await PageObjects.discover.getDocTableField(1); + log.debug(`The first timestamp value in doc table after brushing: ${rowData}`); + return prevRowData !== rowData; + }); + }); + + it('should update the histogram timerange when the query is resubmitted', async function () { + await kibanaServer.uiSettings.update({ + 'timepicker:timeDefaults': '{ "from": "2015-09-18T19:37:13.000Z", "to": "now"}', + }); + await PageObjects.common.navigateToApp('discover'); + await PageObjects.header.awaitKibanaChrome(); + const initialTimeString = await PageObjects.discover.getChartTimespan(); + await queryBar.clickQuerySubmitButton(); + await PageObjects.discover.waitUntilSearchingHasFinished(); + + await retry.waitFor('chart timespan to have changed', async () => { + const refreshedTimeString = await PageObjects.discover.getChartTimespan(); + await queryBar.clickQuerySubmitButton(); + await PageObjects.discover.waitUntilSearchingHasFinished(); + log.debug( + `Timestamp before: ${initialTimeString}, Timestamp after: ${refreshedTimeString}` + ); + return refreshedTimeString !== initialTimeString; + }); + }); + it('should visualize monthly data with different day intervals', async () => { const from = 'Nov 1, 2017 @ 00:00:00.000'; const to = 'Mar 21, 2018 @ 00:00:00.000'; @@ -83,8 +148,10 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { expect(canvasExists).to.be(true); await testSubjects.click('unifiedHistogramChartOptionsToggle'); await testSubjects.click('unifiedHistogramChartToggle'); - canvasExists = await elasticChart.canvasExists(); - expect(canvasExists).to.be(false); + await retry.try(async () => { + canvasExists = await elasticChart.canvasExists(); + expect(canvasExists).to.be(false); + }); // histogram is hidden, when reloading the page it should remain hidden await browser.refresh(); canvasExists = await elasticChart.canvasExists(); @@ -92,8 +159,10 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await testSubjects.click('unifiedHistogramChartOptionsToggle'); await testSubjects.click('unifiedHistogramChartToggle'); await PageObjects.header.waitUntilLoadingHasFinished(); - canvasExists = await elasticChart.canvasExists(); - expect(canvasExists).to.be(true); + await retry.try(async () => { + canvasExists = await elasticChart.canvasExists(); + expect(canvasExists).to.be(true); + }); }); it('should allow hiding the histogram, persisted in saved search', async () => { const from = 'Jan 1, 2010 @ 00:00:00.000'; @@ -104,8 +173,11 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { // close chart for saved search await testSubjects.click('unifiedHistogramChartOptionsToggle'); await testSubjects.click('unifiedHistogramChartToggle'); - let canvasExists = await elasticChart.canvasExists(); - expect(canvasExists).to.be(false); + let canvasExists: boolean; + await retry.try(async () => { + canvasExists = await elasticChart.canvasExists(); + expect(canvasExists).to.be(false); + }); // save search await PageObjects.discover.saveSearch(savedSearch); @@ -147,8 +219,11 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { // close chart await testSubjects.click('unifiedHistogramChartOptionsToggle'); await testSubjects.click('unifiedHistogramChartToggle'); - let canvasExists = await elasticChart.canvasExists(); - expect(canvasExists).to.be(false); + let canvasExists: boolean; + await retry.try(async () => { + canvasExists = await elasticChart.canvasExists(); + expect(canvasExists).to.be(false); + }); // save search await PageObjects.discover.saveSearch('persisted hidden histogram'); @@ -157,8 +232,10 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { // open chart await testSubjects.click('unifiedHistogramChartOptionsToggle'); await testSubjects.click('unifiedHistogramChartToggle'); - canvasExists = await elasticChart.canvasExists(); - expect(canvasExists).to.be(true); + await retry.try(async () => { + canvasExists = await elasticChart.canvasExists(); + expect(canvasExists).to.be(true); + }); // go to dashboard await PageObjects.common.navigateToApp('dashboard'); @@ -173,8 +250,10 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { // close chart await testSubjects.click('unifiedHistogramChartOptionsToggle'); await testSubjects.click('unifiedHistogramChartToggle'); - canvasExists = await elasticChart.canvasExists(); - expect(canvasExists).to.be(false); + await retry.try(async () => { + canvasExists = await elasticChart.canvasExists(); + expect(canvasExists).to.be(false); + }); }); }); } diff --git a/test/functional/apps/discover/group1/_discover_histogram_breakdown.ts b/test/functional/apps/discover/group1/_discover_histogram_breakdown.ts new file mode 100644 index 0000000000000..805d59aee937d --- /dev/null +++ b/test/functional/apps/discover/group1/_discover_histogram_breakdown.ts @@ -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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import expect from '@kbn/expect'; +import { FtrProviderContext } from '../ftr_provider_context'; + +export default function ({ getService, getPageObjects }: FtrProviderContext) { + const esArchiver = getService('esArchiver'); + const kibanaServer = getService('kibanaServer'); + const filterBar = getService('filterBar'); + const PageObjects = getPageObjects(['common', 'discover', 'header', 'timePicker']); + + describe('discover unified histogram breakdown', function describeIndexTests() { + before(async () => { + await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/logstash_functional'); + await kibanaServer.importExport.load('test/functional/fixtures/kbn_archiver/discover'); + await kibanaServer.uiSettings.replace({ defaultIndex: 'logstash-*' }); + await PageObjects.common.navigateToApp('discover'); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.timePicker.setDefaultAbsoluteRange(); + await PageObjects.discover.waitUntilSearchingHasFinished(); + }); + + after(async () => { + await kibanaServer.importExport.unload('test/functional/fixtures/kbn_archiver/discover'); + }); + + it('should choose breakdown field', async () => { + await PageObjects.discover.chooseBreakdownField('extension.raw'); + await PageObjects.header.waitUntilLoadingHasFinished(); + const list = await PageObjects.discover.getHistogramLegendList(); + expect(list).to.eql(['Other', 'png', 'css', 'jpg']); + }); + + it('should add filter using histogram legend values', async () => { + await PageObjects.discover.clickLegendFilter('png', '+'); + await PageObjects.header.waitUntilLoadingHasFinished(); + expect(await filterBar.hasFilter('extension.raw', 'png')).to.be(true); + }); + + it('should save breakdown field in saved search', async () => { + await filterBar.removeFilter('extension.raw'); + await PageObjects.discover.saveSearch('with breakdown'); + + await PageObjects.discover.clickNewSearchButton(); + await PageObjects.header.waitUntilLoadingHasFinished(); + const prevList = await PageObjects.discover.getHistogramLegendList(); + expect(prevList).to.eql([]); + + await PageObjects.discover.loadSavedSearch('with breakdown'); + await PageObjects.header.waitUntilLoadingHasFinished(); + const list = await PageObjects.discover.getHistogramLegendList(); + expect(list).to.eql(['Other', 'png', 'css', 'jpg']); + }); + }); +} diff --git a/test/functional/apps/discover/group1/_inspector.ts b/test/functional/apps/discover/group1/_inspector.ts index 10451adc98e4f..851f992f42b20 100644 --- a/test/functional/apps/discover/group1/_inspector.ts +++ b/test/functional/apps/discover/group1/_inspector.ts @@ -38,10 +38,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await kibanaServer.importExport.load('test/functional/fixtures/kbn_archiver/discover.json'); await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/logstash_functional'); // delete .kibana index and update configDoc - await kibanaServer.uiSettings.replace({ - defaultIndex: 'logstash-*', - }); - + await kibanaServer.uiSettings.replace({ defaultIndex: 'logstash-*' }); + await PageObjects.timePicker.setDefaultAbsoluteRangeViaUiSettings(); await PageObjects.common.navigateToApp('discover'); }); @@ -51,9 +49,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { it('should display request stats with no results', async () => { await inspector.open(); - await testSubjects.click('inspectorRequestChooser'); let foundZero = false; - for (const subj of ['Documents', 'Chart_data']) { + for (const subj of ['Documents', 'Data']) { + await testSubjects.click('inspectorRequestChooser'); await testSubjects.click(`inspectorRequestChooser${subj}`); if (await testSubjects.exists('inspectorRequestDetailStatistics', { timeout: 500 })) { await testSubjects.click(`inspectorRequestDetailStatistics`); diff --git a/test/functional/apps/discover/group1/_shared_links.ts b/test/functional/apps/discover/group1/_shared_links.ts index 9235cd1160db7..edad2010db7ed 100644 --- a/test/functional/apps/discover/group1/_shared_links.ts +++ b/test/functional/apps/discover/group1/_shared_links.ts @@ -76,7 +76,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const expectedUrl = baseUrl + '/app/discover?_t=1453775307251#' + - '/?_g=(filters:!(),refreshInterval:(pause:!t,value:0),time' + + '/?_g=(filters:!(),refreshInterval:(pause:!t,value:60000),time' + ":(from:'2015-09-19T06:31:44.000Z',to:'2015-09" + "-23T18:31:44.000Z'))&_a=(columns:!(),filters:!(),index:'logstash-" + "*',interval:auto,query:(language:kuery,query:'')" + @@ -102,7 +102,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { baseUrl + '/app/discover#' + '/view/ab12e3c0-f231-11e6-9486-733b1ac9221a' + - '?_g=(filters%3A!()%2CrefreshInterval%3A(pause%3A!t%2Cvalue%3A0)' + + '?_g=(filters%3A!()%2CrefreshInterval%3A(pause%3A!t%2Cvalue%3A60000)' + "%2Ctime%3A(from%3A'2015-09-19T06%3A31%3A44.000Z'%2C" + "to%3A'2015-09-23T18%3A31%3A44.000Z'))"; await PageObjects.discover.loadSavedSearch('A Saved Search'); diff --git a/test/functional/apps/discover/group1/_sidebar.ts b/test/functional/apps/discover/group1/_sidebar.ts index 585aae36196e6..109e8aa37cd38 100644 --- a/test/functional/apps/discover/group1/_sidebar.ts +++ b/test/functional/apps/discover/group1/_sidebar.ts @@ -20,22 +20,31 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { 'unifiedSearch', ]); const testSubjects = getService('testSubjects'); + const find = getService('find'); const browser = getService('browser'); + const monacoEditor = getService('monacoEditor'); const filterBar = getService('filterBar'); + const fieldEditor = getService('fieldEditor'); describe('discover sidebar', function describeIndexTests() { before(async function () { await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/logstash_functional'); + }); + + beforeEach(async () => { await kibanaServer.importExport.load('test/functional/fixtures/kbn_archiver/discover'); await kibanaServer.uiSettings.replace({ defaultIndex: 'logstash-*', }); await PageObjects.timePicker.setDefaultAbsoluteRangeViaUiSettings(); await PageObjects.common.navigateToApp('discover'); + await PageObjects.discover.waitUntilSearchingHasFinished(); }); - after(async () => { + afterEach(async () => { await kibanaServer.importExport.unload('test/functional/fixtures/kbn_archiver/discover'); + await kibanaServer.savedObjects.cleanStandardList(); + await kibanaServer.uiSettings.replace({}); }); describe('field filtering', function () { @@ -107,5 +116,449 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await testSubjects.existOrFail('discover-sidebar'); }); }); + + describe('renders field groups', function () { + it('should show field list groups excluding subfields', async function () { + await PageObjects.discover.waitUntilSidebarHasLoaded(); + expect(await PageObjects.discover.doesSidebarShowFields()).to.be(true); + + // Initial Available fields + const expectedInitialAvailableFields = + '@message, @tags, @timestamp, agent, bytes, clientip, extension, geo.coordinates, geo.dest, geo.src, geo.srcdest, headings, host, id, index, ip, links, machine.os, machine.ram, machine.ram_range, memory, meta.char, meta.related, meta.user.firstname, meta.user.lastname, nestedField.child, phpmemory, referer, relatedContent.article:modified_time, relatedContent.article:published_time, relatedContent.article:section, relatedContent.article:tag, relatedContent.og:description, relatedContent.og:image, relatedContent.og:image:height, relatedContent.og:image:width, relatedContent.og:site_name, relatedContent.og:title, relatedContent.og:type, relatedContent.og:url, relatedContent.twitter:card, relatedContent.twitter:description, relatedContent.twitter:image, relatedContent.twitter:site, relatedContent.twitter:title, relatedContent.url, request, response, spaces, type'; + let availableFields = await PageObjects.discover.getSidebarSectionFieldNames('available'); + expect(availableFields.length).to.be(50); + expect(availableFields.join(', ')).to.be(expectedInitialAvailableFields); + + // Available fields after scrolling down + const emptySectionButton = await find.byCssSelector( + PageObjects.discover.getSidebarSectionSelector('empty', true) + ); + await emptySectionButton.scrollIntoViewIfNecessary(); + availableFields = await PageObjects.discover.getSidebarSectionFieldNames('available'); + expect(availableFields.length).to.be(53); + expect(availableFields.join(', ')).to.be( + `${expectedInitialAvailableFields}, url, utc_time, xss` + ); + + // Expand Empty section + await PageObjects.discover.toggleSidebarSection('empty'); + expect((await PageObjects.discover.getSidebarSectionFieldNames('empty')).join(', ')).to.be( + '' + ); + + // Expand Meta section + await PageObjects.discover.toggleSidebarSection('meta'); + expect((await PageObjects.discover.getSidebarSectionFieldNames('meta')).join(', ')).to.be( + '_id, _index, _score' + ); + + expect(await PageObjects.discover.getSidebarAriaDescription()).to.be( + '53 available fields. 0 empty fields. 3 meta fields.' + ); + }); + + it('should show field list groups excluding subfields when searched from source', async function () { + await kibanaServer.uiSettings.update({ 'discover:searchFieldsFromSource': true }); + await browser.refresh(); + + await PageObjects.discover.waitUntilSidebarHasLoaded(); + expect(await PageObjects.discover.doesSidebarShowFields()).to.be(true); + + // Initial Available fields + let availableFields = await PageObjects.discover.getSidebarSectionFieldNames('available'); + expect(availableFields.length).to.be(50); + expect( + availableFields + .join(', ') + .startsWith( + '@message, @tags, @timestamp, agent, bytes, clientip, extension, geo.coordinates' + ) + ).to.be(true); + + // Available fields after scrolling down + const emptySectionButton = await find.byCssSelector( + PageObjects.discover.getSidebarSectionSelector('empty', true) + ); + await emptySectionButton.scrollIntoViewIfNecessary(); + availableFields = await PageObjects.discover.getSidebarSectionFieldNames('available'); + expect(availableFields.length).to.be(53); + + // Expand Empty section + await PageObjects.discover.toggleSidebarSection('empty'); + expect((await PageObjects.discover.getSidebarSectionFieldNames('empty')).join(', ')).to.be( + '' + ); + + // Expand Meta section + await PageObjects.discover.toggleSidebarSection('meta'); + expect((await PageObjects.discover.getSidebarSectionFieldNames('meta')).join(', ')).to.be( + '_id, _index, _score' + ); + + // Expand Unmapped section + await PageObjects.discover.toggleSidebarSection('unmapped'); + expect( + (await PageObjects.discover.getSidebarSectionFieldNames('unmapped')).join(', ') + ).to.be('relatedContent'); + + expect(await PageObjects.discover.getSidebarAriaDescription()).to.be( + '53 available fields. 1 unmapped field. 0 empty fields. 3 meta fields.' + ); + }); + + it('should show selected and popular fields', async function () { + await PageObjects.discover.clickFieldListItemAdd('extension'); + await PageObjects.discover.waitUntilSearchingHasFinished(); + await PageObjects.discover.clickFieldListItemAdd('@message'); + await PageObjects.discover.waitUntilSearchingHasFinished(); + + expect( + (await PageObjects.discover.getSidebarSectionFieldNames('selected')).join(', ') + ).to.be('extension, @message'); + + const availableFields = await PageObjects.discover.getSidebarSectionFieldNames('available'); + expect(availableFields.includes('extension')).to.be(true); + expect(availableFields.includes('@message')).to.be(true); + + expect(await PageObjects.discover.getSidebarAriaDescription()).to.be( + '2 selected fields. 2 popular fields. 53 available fields. 0 empty fields. 3 meta fields.' + ); + + await PageObjects.discover.clickFieldListItemRemove('@message'); + await PageObjects.discover.waitUntilSearchingHasFinished(); + + await PageObjects.discover.clickFieldListItemAdd('_id'); + await PageObjects.discover.waitUntilSearchingHasFinished(); + await PageObjects.discover.clickFieldListItemAdd('@message'); + await PageObjects.discover.waitUntilSearchingHasFinished(); + + expect( + (await PageObjects.discover.getSidebarSectionFieldNames('selected')).join(', ') + ).to.be('extension, _id, @message'); + + expect( + (await PageObjects.discover.getSidebarSectionFieldNames('popular')).join(', ') + ).to.be('@message, _id, extension'); + + expect(await PageObjects.discover.getSidebarAriaDescription()).to.be( + '3 selected fields. 3 popular fields. 53 available fields. 0 empty fields. 3 meta fields.' + ); + }); + + it('should show selected and available fields in text-based mode', async function () { + await kibanaServer.uiSettings.update({ 'discover:enableSql': true }); + await browser.refresh(); + + await PageObjects.discover.waitUntilSidebarHasLoaded(); + + expect(await PageObjects.discover.getSidebarAriaDescription()).to.be( + '53 available fields. 0 empty fields. 3 meta fields.' + ); + + await PageObjects.discover.selectTextBaseLang('SQL'); + + expect(await PageObjects.discover.getSidebarAriaDescription()).to.be( + '50 selected fields. 51 available fields.' + ); + + await PageObjects.discover.clickFieldListItemRemove('extension'); + await PageObjects.discover.waitUntilSidebarHasLoaded(); + + expect(await PageObjects.discover.getSidebarAriaDescription()).to.be( + '49 selected fields. 51 available fields.' + ); + + const testQuery = `SELECT "@tags", geo.dest, count(*) occurred FROM "logstash-*" + GROUP BY "@tags", geo.dest + HAVING occurred > 20 + ORDER BY occurred DESC`; + + await monacoEditor.setCodeEditorValue(testQuery); + await testSubjects.click('querySubmitButton'); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.discover.waitUntilSidebarHasLoaded(); + + expect(await PageObjects.discover.getSidebarAriaDescription()).to.be( + '3 selected fields. 3 available fields.' + ); + expect( + (await PageObjects.discover.getSidebarSectionFieldNames('selected')).join(', ') + ).to.be('@tags, geo.dest, occurred'); + + await PageObjects.unifiedSearch.switchDataView( + 'discover-dataView-switch-link', + 'logstash-*', + true + ); + + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.discover.waitUntilSidebarHasLoaded(); + + expect(await PageObjects.discover.getSidebarAriaDescription()).to.be( + '1 popular field. 53 available fields. 0 empty fields. 3 meta fields.' + ); + }); + + it('should work correctly for a data view for a missing index', async function () { + // but we are skipping importing the index itself + await kibanaServer.importExport.load( + 'test/functional/fixtures/kbn_archiver/index_pattern_without_timefield' + ); + await browser.refresh(); + await PageObjects.discover.waitUntilSidebarHasLoaded(); + + expect(await PageObjects.discover.getSidebarAriaDescription()).to.be( + '53 available fields. 0 empty fields. 3 meta fields.' + ); + + await PageObjects.discover.selectIndexPattern('with-timefield'); + + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.discover.waitUntilSidebarHasLoaded(); + + expect(await PageObjects.discover.getSidebarAriaDescription()).to.be( + '0 available fields. 0 meta fields.' + ); + await testSubjects.existOrFail( + `${PageObjects.discover.getSidebarSectionSelector('available')}-fetchWarning` + ); + await testSubjects.existOrFail( + `${PageObjects.discover.getSidebarSectionSelector( + 'available' + )}NoFieldsCallout-noFieldsExist` + ); + + await PageObjects.discover.selectIndexPattern('logstash-*'); + + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.discover.waitUntilSidebarHasLoaded(); + + expect(await PageObjects.discover.getSidebarAriaDescription()).to.be( + '53 available fields. 0 empty fields. 3 meta fields.' + ); + await kibanaServer.importExport.unload( + 'test/functional/fixtures/kbn_archiver/index_pattern_without_timefield' + ); + }); + + it('should work correctly when switching data views', async function () { + await esArchiver.loadIfNeeded( + 'test/functional/fixtures/es_archiver/index_pattern_without_timefield' + ); + await kibanaServer.importExport.load( + 'test/functional/fixtures/kbn_archiver/index_pattern_without_timefield' + ); + + await browser.refresh(); + await PageObjects.discover.waitUntilSidebarHasLoaded(); + + expect(await PageObjects.discover.getSidebarAriaDescription()).to.be( + '53 available fields. 0 empty fields. 3 meta fields.' + ); + + await PageObjects.discover.selectIndexPattern('without-timefield'); + + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.discover.waitUntilSidebarHasLoaded(); + + expect(await PageObjects.discover.getSidebarAriaDescription()).to.be( + '6 available fields. 0 empty fields. 3 meta fields.' + ); + + await PageObjects.discover.selectIndexPattern('with-timefield'); + + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.discover.waitUntilSidebarHasLoaded(); + + expect(await PageObjects.discover.getSidebarAriaDescription()).to.be( + '0 available fields. 7 empty fields. 3 meta fields.' + ); + await testSubjects.existOrFail( + `${PageObjects.discover.getSidebarSectionSelector( + 'available' + )}NoFieldsCallout-noFieldsMatch` + ); + + await PageObjects.discover.selectIndexPattern('logstash-*'); + + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.discover.waitUntilSidebarHasLoaded(); + + expect(await PageObjects.discover.getSidebarAriaDescription()).to.be( + '53 available fields. 0 empty fields. 3 meta fields.' + ); + + await kibanaServer.importExport.unload( + 'test/functional/fixtures/kbn_archiver/index_pattern_without_timefield' + ); + + await esArchiver.unload( + 'test/functional/fixtures/es_archiver/index_pattern_without_timefield' + ); + }); + + it('should work when filters change', async () => { + await PageObjects.header.waitUntilLoadingHasFinished(); + + expect(await PageObjects.discover.getSidebarAriaDescription()).to.be( + '53 available fields. 0 empty fields. 3 meta fields.' + ); + + await PageObjects.discover.clickFieldListItem('extension'); + expect(await testSubjects.getVisibleText('dscFieldStats-topValues')).to.be( + 'jpg\n65.0%\ncss\n15.4%\npng\n9.8%\ngif\n6.6%\nphp\n3.2%' + ); + + await filterBar.addFilter('extension', 'is', 'jpg'); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.discover.waitUntilSidebarHasLoaded(); + + expect(await PageObjects.discover.getSidebarAriaDescription()).to.be( + '53 available fields. 0 empty fields. 3 meta fields.' + ); + + // check that the filter was passed down to the sidebar + await PageObjects.discover.clickFieldListItem('extension'); + expect(await testSubjects.getVisibleText('dscFieldStats-topValues')).to.be('jpg\n100%'); + }); + + it('should work for many fields', async () => { + await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/many_fields'); + await kibanaServer.importExport.load( + 'test/functional/fixtures/kbn_archiver/many_fields_data_view' + ); + + await browser.refresh(); + await PageObjects.discover.waitUntilSidebarHasLoaded(); + + expect(await PageObjects.discover.getSidebarAriaDescription()).to.be( + '53 available fields. 0 empty fields. 3 meta fields.' + ); + + await PageObjects.discover.selectIndexPattern('indices-stats*'); + + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.discover.waitUntilSidebarHasLoaded(); + + expect(await PageObjects.discover.getSidebarAriaDescription()).to.be( + '6873 available fields. 0 empty fields. 3 meta fields.' + ); + + await PageObjects.discover.selectIndexPattern('logstash-*'); + + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.discover.waitUntilSidebarHasLoaded(); + + expect(await PageObjects.discover.getSidebarAriaDescription()).to.be( + '53 available fields. 0 empty fields. 3 meta fields.' + ); + + await kibanaServer.importExport.unload( + 'test/functional/fixtures/kbn_archiver/many_fields_data_view' + ); + await esArchiver.unload('test/functional/fixtures/es_archiver/many_fields'); + }); + + it('should work with ad-hoc data views and runtime fields', async () => { + await PageObjects.discover.createAdHocDataView('logstash', true); + await PageObjects.header.waitUntilLoadingHasFinished(); + + expect(await PageObjects.discover.getSidebarAriaDescription()).to.be( + '53 available fields. 0 empty fields. 3 meta fields.' + ); + + await PageObjects.discover.addRuntimeField( + '_bytes-runtimefield', + `emit((doc["bytes"].value * 2).toString())` + ); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.discover.waitUntilSidebarHasLoaded(); + + expect(await PageObjects.discover.getSidebarAriaDescription()).to.be( + '54 available fields. 0 empty fields. 3 meta fields.' + ); + + let allFields = await PageObjects.discover.getAllFieldNames(); + expect(allFields.includes('_bytes-runtimefield')).to.be(true); + + await PageObjects.discover.editField('_bytes-runtimefield'); + await fieldEditor.enableCustomLabel(); + await fieldEditor.setCustomLabel('_bytes-runtimefield2'); + await fieldEditor.save(); + + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.discover.waitUntilSidebarHasLoaded(); + + expect(await PageObjects.discover.getSidebarAriaDescription()).to.be( + '54 available fields. 0 empty fields. 3 meta fields.' + ); + + allFields = await PageObjects.discover.getAllFieldNames(); + expect(allFields.includes('_bytes-runtimefield2')).to.be(true); + expect(allFields.includes('_bytes-runtimefield')).to.be(false); + + await PageObjects.discover.removeField('_bytes-runtimefield'); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.discover.waitUntilSidebarHasLoaded(); + + expect(await PageObjects.discover.getSidebarAriaDescription()).to.be( + '53 available fields. 0 empty fields. 3 meta fields.' + ); + + allFields = await PageObjects.discover.getAllFieldNames(); + expect(allFields.includes('_bytes-runtimefield2')).to.be(false); + expect(allFields.includes('_bytes-runtimefield')).to.be(false); + }); + + it('should work correctly when time range is updated', async function () { + await esArchiver.loadIfNeeded( + 'test/functional/fixtures/es_archiver/index_pattern_without_timefield' + ); + await kibanaServer.importExport.load( + 'test/functional/fixtures/kbn_archiver/index_pattern_without_timefield' + ); + + await browser.refresh(); + await PageObjects.discover.waitUntilSidebarHasLoaded(); + + expect(await PageObjects.discover.getSidebarAriaDescription()).to.be( + '53 available fields. 0 empty fields. 3 meta fields.' + ); + + await PageObjects.discover.selectIndexPattern('with-timefield'); + + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.discover.waitUntilSidebarHasLoaded(); + + expect(await PageObjects.discover.getSidebarAriaDescription()).to.be( + '0 available fields. 7 empty fields. 3 meta fields.' + ); + await testSubjects.existOrFail( + `${PageObjects.discover.getSidebarSectionSelector( + 'available' + )}NoFieldsCallout-noFieldsMatch` + ); + + await PageObjects.timePicker.setAbsoluteRange( + 'Sep 21, 2019 @ 00:00:00.000', + 'Sep 23, 2019 @ 00:00:00.000' + ); + + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.discover.waitUntilSidebarHasLoaded(); + + expect(await PageObjects.discover.getSidebarAriaDescription()).to.be( + '7 available fields. 0 empty fields. 3 meta fields.' + ); + + await kibanaServer.importExport.unload( + 'test/functional/fixtures/kbn_archiver/index_pattern_without_timefield' + ); + + await esArchiver.unload( + 'test/functional/fixtures/es_archiver/index_pattern_without_timefield' + ); + }); + }); }); } diff --git a/test/functional/apps/discover/group1/index.ts b/test/functional/apps/discover/group1/index.ts index ab6798400b7a2..82fd341ccce04 100644 --- a/test/functional/apps/discover/group1/index.ts +++ b/test/functional/apps/discover/group1/index.ts @@ -23,6 +23,7 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./_no_data')); loadTestFile(require.resolve('./_discover')); loadTestFile(require.resolve('./_discover_accessibility')); + loadTestFile(require.resolve('./_discover_histogram_breakdown')); loadTestFile(require.resolve('./_discover_histogram')); loadTestFile(require.resolve('./_doc_accessibility')); loadTestFile(require.resolve('./_filter_editor')); diff --git a/test/functional/apps/discover/group2/_adhoc_data_views.ts b/test/functional/apps/discover/group2/_adhoc_data_views.ts index 773471994237f..50eb3be5f07d1 100644 --- a/test/functional/apps/discover/group2/_adhoc_data_views.ts +++ b/test/functional/apps/discover/group2/_adhoc_data_views.ts @@ -51,6 +51,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); after(async () => { + await kibanaServer.savedObjects.cleanStandardList(); await esArchiver.unload('x-pack/test/functional/es_archives/logstash_functional'); }); diff --git a/test/functional/apps/discover/group2/_huge_fields.ts b/test/functional/apps/discover/group2/_huge_fields.ts index 085788f1139d0..7ffcc891506e3 100644 --- a/test/functional/apps/discover/group2/_huge_fields.ts +++ b/test/functional/apps/discover/group2/_huge_fields.ts @@ -42,6 +42,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await security.testUser.restoreDefaults(); await esArchiver.unload('test/functional/fixtures/es_archiver/huge_fields'); await kibanaServer.uiSettings.unset('timepicker:timeDefaults'); + await kibanaServer.savedObjects.cleanStandardList(); }); }); } diff --git a/test/functional/apps/discover/group2/_indexpattern_with_unmapped_fields.ts b/test/functional/apps/discover/group2/_indexpattern_with_unmapped_fields.ts index d5d45d227d685..a17e6c0798a78 100644 --- a/test/functional/apps/discover/group2/_indexpattern_with_unmapped_fields.ts +++ b/test/functional/apps/discover/group2/_indexpattern_with_unmapped_fields.ts @@ -22,8 +22,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await kibanaServer.savedObjects.clean({ types: ['search', 'index-pattern'] }); await kibanaServer.importExport.load('test/functional/fixtures/kbn_archiver/unmapped_fields'); await security.testUser.setRoles(['kibana_admin', 'test-index-unmapped-fields']); - const fromTime = 'Jan 20, 2021 @ 00:00:00.000'; - const toTime = 'Jan 25, 2021 @ 00:00:00.000'; + const fromTime = '2021-01-20T00:00:00.000Z'; + const toTime = '2021-01-25T00:00:00.000Z'; await kibanaServer.uiSettings.replace({ defaultIndex: 'test-index-unmapped-fields', @@ -48,11 +48,18 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await retry.try(async function () { expect(await PageObjects.discover.getHitCount()).to.be(expectedHitCount); }); - const allFields = await PageObjects.discover.getAllFieldNames(); + let allFields = await PageObjects.discover.getAllFieldNames(); // message is a mapped field expect(allFields.includes('message')).to.be(true); // sender is not a mapped field - expect(allFields.includes('sender')).to.be(true); + expect(allFields.includes('sender')).to.be(false); + + await PageObjects.discover.toggleSidebarSection('unmapped'); + + allFields = await PageObjects.discover.getAllFieldNames(); + expect(allFields.includes('sender')).to.be(true); // now visible under Unmapped section + + await PageObjects.discover.toggleSidebarSection('unmapped'); }); it('unmapped fields exist on an existing saved search', async () => { @@ -61,10 +68,20 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await retry.try(async function () { expect(await PageObjects.discover.getHitCount()).to.be(expectedHitCount); }); - const allFields = await PageObjects.discover.getAllFieldNames(); + let allFields = await PageObjects.discover.getAllFieldNames(); expect(allFields.includes('message')).to.be(true); + expect(allFields.includes('sender')).to.be(false); + expect(allFields.includes('receiver')).to.be(false); + + await PageObjects.discover.toggleSidebarSection('unmapped'); + + allFields = await PageObjects.discover.getAllFieldNames(); + + // now visible under Unmapped section expect(allFields.includes('sender')).to.be(true); expect(allFields.includes('receiver')).to.be(true); + + await PageObjects.discover.toggleSidebarSection('unmapped'); }); }); } diff --git a/test/functional/apps/discover/group2/_search_on_page_load.ts b/test/functional/apps/discover/group2/_search_on_page_load.ts index be738c3708854..cb2b21e3849db 100644 --- a/test/functional/apps/discover/group2/_search_on_page_load.ts +++ b/test/functional/apps/discover/group2/_search_on_page_load.ts @@ -25,6 +25,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { defaultIndex: 'logstash-*', }; + const savedSearchName = 'saved-search-with-on-page-load'; + const initSearchOnPageLoad = async (searchOnPageLoad: boolean) => { await kibanaServer.uiSettings.replace({ 'discover:searchOnPageLoad': searchOnPageLoad }); await PageObjects.common.navigateToApp('discover'); @@ -60,6 +62,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await esArchiver.unload('test/functional/fixtures/es_archiver/date_nested'); await esArchiver.unload('test/functional/fixtures/es_archiver/logstash_functional'); await kibanaServer.uiSettings.replace(defaultSettings); + await kibanaServer.savedObjects.cleanStandardList(); }); describe(`when it's false`, () => { @@ -68,6 +71,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { it('should not fetch data from ES initially', async function () { expect(await testSubjects.exists(refreshButtonSelector)).to.be(true); await retry.waitFor('number of fetches to be 0', waitForFetches(0)); + expect(await PageObjects.discover.doesSidebarShowFields()).to.be(false); }); it('should not fetch on indexPattern change', async function () { @@ -78,43 +82,77 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { expect(await testSubjects.exists(refreshButtonSelector)).to.be(true); await retry.waitFor('number of fetches to be 0', waitForFetches(0)); + expect(await PageObjects.discover.doesSidebarShowFields()).to.be(false); }); it('should fetch data from ES after refreshDataButton click', async function () { expect(await testSubjects.exists(refreshButtonSelector)).to.be(true); await retry.waitFor('number of fetches to be 0', waitForFetches(0)); + expect(await PageObjects.discover.doesSidebarShowFields()).to.be(false); await testSubjects.click(refreshButtonSelector); await testSubjects.missingOrFail(refreshButtonSelector); await retry.waitFor('number of fetches to be 1', waitForFetches(1)); + expect(await PageObjects.discover.doesSidebarShowFields()).to.be(true); }); it('should fetch data from ES after submit query', async function () { expect(await testSubjects.exists(refreshButtonSelector)).to.be(true); await retry.waitFor('number of fetches to be 0', waitForFetches(0)); + expect(await PageObjects.discover.doesSidebarShowFields()).to.be(false); await queryBar.submitQuery(); await testSubjects.missingOrFail(refreshButtonSelector); await retry.waitFor('number of fetches to be 1', waitForFetches(1)); + expect(await PageObjects.discover.doesSidebarShowFields()).to.be(true); }); it('should fetch data from ES after choosing commonly used time range', async function () { await PageObjects.discover.selectIndexPattern('logstash-*'); expect(await testSubjects.exists(refreshButtonSelector)).to.be(true); await retry.waitFor('number of fetches to be 0', waitForFetches(0)); + expect(await PageObjects.discover.doesSidebarShowFields()).to.be(false); await PageObjects.timePicker.setCommonlyUsedTime('This_week'); await testSubjects.missingOrFail(refreshButtonSelector); await retry.waitFor('number of fetches to be 1', waitForFetches(1)); + expect(await PageObjects.discover.doesSidebarShowFields()).to.be(true); + }); + + it('should fetch data when a search is saved', async function () { + await PageObjects.discover.selectIndexPattern('logstash-*'); + + await retry.waitFor('number of fetches to be 0', waitForFetches(0)); + expect(await PageObjects.discover.doesSidebarShowFields()).to.be(false); + + await PageObjects.discover.saveSearch(savedSearchName); + + await retry.waitFor('number of fetches to be 1', waitForFetches(1)); + expect(await PageObjects.discover.doesSidebarShowFields()).to.be(true); + }); + + it('should reset state after opening a saved search and pressing New', async function () { + await PageObjects.discover.loadSavedSearch(savedSearchName); + await PageObjects.header.waitUntilLoadingHasFinished(); + + await retry.waitFor('number of fetches to be 1', waitForFetches(1)); + expect(await PageObjects.discover.doesSidebarShowFields()).to.be(true); + + await testSubjects.click('discoverNewButton'); + await PageObjects.header.waitUntilLoadingHasFinished(); + + await retry.waitFor('number of fetches to be 1', waitForFetches(1)); + expect(await PageObjects.discover.doesSidebarShowFields()).to.be(false); }); }); it(`when it's true should fetch data from ES initially`, async function () { await initSearchOnPageLoad(true); await retry.waitFor('number of fetches to be 1', waitForFetches(1)); + expect(await PageObjects.discover.doesSidebarShowFields()).to.be(true); }); }); } diff --git a/test/functional/page_objects/context_page.ts b/test/functional/page_objects/context_page.ts index 05ea89cb65b3d..2bb3d7fb84a2a 100644 --- a/test/functional/page_objects/context_page.ts +++ b/test/functional/page_objects/context_page.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import rison from 'rison-node'; +import rison from '@kbn/rison'; import { getUrl } from '@kbn/test'; import { FtrService } from '../ftr_provider_context'; diff --git a/test/functional/page_objects/discover_page.ts b/test/functional/page_objects/discover_page.ts index 79a30dba288d3..d6c12c9bb9e43 100644 --- a/test/functional/page_objects/discover_page.ts +++ b/test/functional/page_objects/discover_page.ts @@ -8,6 +8,9 @@ import expect from '@kbn/expect'; import { FtrService } from '../ftr_provider_context'; +import { WebElementWrapper } from '../services/lib/web_element_wrapper'; + +type SidebarSectionName = 'meta' | 'empty' | 'available' | 'unmapped' | 'popular' | 'selected'; export class DiscoverPageObject extends FtrService { private readonly retry = this.ctx.getService('retry'); @@ -25,6 +28,7 @@ export class DiscoverPageObject extends FtrService { private readonly kibanaServer = this.ctx.getService('kibanaServer'); private readonly fieldEditor = this.ctx.getService('fieldEditor'); private readonly queryBar = this.ctx.getService('queryBar'); + private readonly comboBox = this.ctx.getService('comboBox'); private readonly defaultFindTimeout = this.config.get('timeouts.find'); @@ -202,6 +206,22 @@ export class DiscoverPageObject extends FtrService { ); } + public async chooseBreakdownField(field: string) { + await this.comboBox.set('unifiedHistogramBreakdownFieldSelector', field); + } + + public async getHistogramLegendList() { + const unifiedHistogram = await this.testSubjects.find('unifiedHistogramChart'); + const list = await unifiedHistogram.findAllByClassName('echLegendItem__label'); + return Promise.all(list.map((elem: WebElementWrapper) => elem.getVisibleText())); + } + + public async clickLegendFilter(field: string, type: '+' | '-') { + const filterType = type === '+' ? 'filterIn' : 'filterOut'; + await this.testSubjects.click(`legend-${field}`); + await this.testSubjects.click(`legend-${field}-${filterType}`); + } + public async getCurrentQueryName() { return await this.globalNav.getLastBreadcrumb(); } @@ -377,14 +397,14 @@ export class DiscoverPageObject extends FtrService { public async editField(field: string) { await this.retry.try(async () => { - await this.testSubjects.click(`field-${field}`); + await this.clickFieldListItem(field); await this.testSubjects.click(`discoverFieldListPanelEdit-${field}`); await this.find.byClassName('indexPatternFieldEditor__form'); }); } public async removeField(field: string) { - await this.testSubjects.click(`field-${field}`); + await this.clickFieldListItem(field); await this.testSubjects.click(`discoverFieldListPanelDelete-${field}`); await this.testSubjects.existOrFail('runtimeFieldDeleteConfirmModal'); await this.fieldEditor.confirmDelete(); @@ -437,8 +457,65 @@ export class DiscoverPageObject extends FtrService { return await this.testSubjects.exists('discoverNoResultsTimefilter'); } + public async getSidebarAriaDescription(): Promise { + return await ( + await this.testSubjects.find('fieldListGrouped__ariaDescription') + ).getAttribute('innerText'); + } + + public async waitUntilSidebarHasLoaded() { + await this.retry.waitFor('sidebar is loaded', async () => { + return (await this.getSidebarAriaDescription()).length > 0; + }); + } + + public async doesSidebarShowFields() { + return await this.testSubjects.exists('fieldListGroupedFieldGroups'); + } + + public getSidebarSectionSelector( + sectionName: SidebarSectionName, + asCSSSelector: boolean = false + ) { + const testSubj = `fieldListGrouped${sectionName[0].toUpperCase()}${sectionName.substring( + 1 + )}Fields`; + if (!asCSSSelector) { + return testSubj; + } + return `[data-test-subj="${testSubj}"]`; + } + + public async getSidebarSectionFieldNames(sectionName: SidebarSectionName): Promise { + const elements = await this.find.allByCssSelector( + `${this.getSidebarSectionSelector(sectionName, true)} li` + ); + + if (!elements?.length) { + return []; + } + + return Promise.all( + elements.map(async (element) => await element.getAttribute('data-attr-field')) + ); + } + + public async toggleSidebarSection(sectionName: SidebarSectionName) { + return await this.find.clickByCssSelector( + `${this.getSidebarSectionSelector(sectionName, true)} .euiAccordion__iconButton` + ); + } + + public async waitUntilFieldPopoverIsOpen() { + await this.retry.waitFor('popover is open', async () => { + return Boolean(await this.find.byCssSelector('[data-popover-open="true"]')); + }); + } + public async clickFieldListItem(field: string) { - return await this.testSubjects.click(`field-${field}`); + await this.testSubjects.click(`field-${field}`); + + await this.waitUntilFieldPopoverIsOpen(); } public async clickFieldSort(field: string, text = 'Sort New-Old') { @@ -455,11 +532,16 @@ export class DiscoverPageObject extends FtrService { } public async clickFieldListItemAdd(field: string) { + await this.waitUntilSidebarHasLoaded(); + // a filter check may make sense here, but it should be properly handled to make // it work with the _score and _source fields as well if (await this.isFieldSelected(field)) { return; } + if (['_score', '_id', '_index'].includes(field)) { + await this.toggleSidebarSection('meta'); // expand Meta section + } await this.clickFieldListItemToggle(field); const isLegacyDefault = await this.useLegacyTable(); if (isLegacyDefault) { @@ -474,16 +556,18 @@ export class DiscoverPageObject extends FtrService { } public async isFieldSelected(field: string) { - if (!(await this.testSubjects.exists('fieldList-selected'))) { + if (!(await this.testSubjects.exists('fieldListGroupedSelectedFields'))) { return false; } - const selectedList = await this.testSubjects.find('fieldList-selected'); + const selectedList = await this.testSubjects.find('fieldListGroupedSelectedFields'); return await this.testSubjects.descendantExists(`field-${field}`, selectedList); } public async clickFieldListItemRemove(field: string) { + await this.waitUntilSidebarHasLoaded(); + if ( - !(await this.testSubjects.exists('fieldList-selected')) || + !(await this.testSubjects.exists('fieldListGroupedSelectedFields')) || !(await this.isFieldSelected(field)) ) { return; @@ -493,6 +577,8 @@ export class DiscoverPageObject extends FtrService { } public async clickFieldListItemVisualize(fieldName: string) { + await this.waitUntilSidebarHasLoaded(); + const field = await this.testSubjects.find(`field-${fieldName}-showDetails`); const isActive = await field.elementHasClass('kbnFieldButton-isActive'); @@ -501,6 +587,7 @@ export class DiscoverPageObject extends FtrService { await field.click(); } + await this.waitUntilFieldPopoverIsOpen(); await this.testSubjects.click(`fieldVisualize-${fieldName}`); await this.header.waitUntilLoadingHasFinished(); } diff --git a/test/functional/page_objects/time_picker.ts b/test/functional/page_objects/time_picker.ts index 59513bf350040..44aec2e3fb187 100644 --- a/test/functional/page_objects/time_picker.ts +++ b/test/functional/page_objects/time_picker.ts @@ -123,8 +123,21 @@ export class TimePickerPageObject extends FtrService { /** * @param {String} fromTime MMM D, YYYY @ HH:mm:ss.SSS * @param {String} toTime MMM D, YYYY @ HH:mm:ss.SSS + * @param {Boolean} force time picker force update, default is false */ - public async setAbsoluteRange(fromTime: string, toTime: string) { + public async setAbsoluteRange(fromTime: string, toTime: string, force = false) { + if (!force) { + const currentUrl = decodeURI(await this.browser.getCurrentUrl()); + const DEFAULT_DATE_FORMAT = 'MMM D, YYYY @ HH:mm:ss.SSS'; + const startMoment = moment.utc(fromTime, DEFAULT_DATE_FORMAT).toISOString(); + const endMoment = moment.utc(toTime, DEFAULT_DATE_FORMAT).toISOString(); + if (currentUrl.includes(`time:(from:'${startMoment}',to:'${endMoment}'`)) { + this.log.debug( + `We already have the desired start (${fromTime}) and end (${toTime}) in the URL, returning from setAbsoluteRange` + ); + return; + } + } this.log.debug(`Setting absolute range to ${fromTime} to ${toTime}`); await this.showStartEndTimes(); let panel!: WebElementWrapper; @@ -285,7 +298,14 @@ export class TimePickerPageObject extends FtrService { await this.testSubjects.click('superDatePickerToggleRefreshButton'); } - await this.inputValue('superDatePickerRefreshIntervalInput', intervalS.toString()); + await this.retry.waitFor('auto refresh to be set correctly', async () => { + await this.inputValue('superDatePickerRefreshIntervalInput', intervalS.toString()); + return ( + (await this.testSubjects.getAttribute('superDatePickerRefreshIntervalInput', 'value')) === + intervalS.toString() + ); + }); + await this.quickSelectTimeMenuToggle.close(); } diff --git a/tsconfig.base.json b/tsconfig.base.json index b127fbfc808a1..bc2472877cc9d 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -540,6 +540,8 @@ "@kbn/repo-source-classifier/*": ["packages/kbn-repo-source-classifier/*"], "@kbn/repo-source-classifier-cli": ["packages/kbn-repo-source-classifier-cli"], "@kbn/repo-source-classifier-cli/*": ["packages/kbn-repo-source-classifier-cli/*"], + "@kbn/rison": ["packages/kbn-rison"], + "@kbn/rison/*": ["packages/kbn-rison/*"], "@kbn/rule-data-utils": ["packages/kbn-rule-data-utils"], "@kbn/rule-data-utils/*": ["packages/kbn-rule-data-utils/*"], "@kbn/safer-lodash-set": ["packages/kbn-safer-lodash-set"], @@ -720,6 +722,8 @@ "@kbn/shared-ux-prompt-no-data-views-mocks/*": ["packages/shared-ux/prompt/no_data_views/mocks/*"], "@kbn/shared-ux-prompt-no-data-views-types": ["packages/shared-ux/prompt/no_data_views/types"], "@kbn/shared-ux-prompt-no-data-views-types/*": ["packages/shared-ux/prompt/no_data_views/types/*"], + "@kbn/shared-ux-prompt-not-found": ["packages/shared-ux/prompt/not_found"], + "@kbn/shared-ux-prompt-not-found/*": ["packages/shared-ux/prompt/not_found/*"], "@kbn/shared-ux-router": ["packages/shared-ux/router/impl"], "@kbn/shared-ux-router/*": ["packages/shared-ux/router/impl/*"], "@kbn/shared-ux-router-mocks": ["packages/shared-ux/router/mocks"], diff --git a/typings/rison_node.d.ts b/typings/rison_node.d.ts deleted file mode 100644 index dacb2524907be..0000000000000 --- a/typings/rison_node.d.ts +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -declare module 'rison-node' { - export type RisonValue = undefined | null | boolean | number | string | RisonObject | RisonArray; - - // eslint-disable-next-line @typescript-eslint/no-empty-interface - export interface RisonArray extends Array {} - - export interface RisonObject { - [key: string]: RisonValue; - } - - export const decode: (input: string) => RisonValue; - - // eslint-disable-next-line @typescript-eslint/naming-convention - export const decode_object: (input: string) => RisonObject; - - export const encode: (input: Input) => string; - - // eslint-disable-next-line @typescript-eslint/naming-convention - export const encode_object: (input: Input) => string; -} diff --git a/x-pack/plugins/actions/server/create_execute_function.test.ts b/x-pack/plugins/actions/server/create_execute_function.test.ts index a38a9e4a0e780..6e1c9aded6a3d 100644 --- a/x-pack/plugins/actions/server/create_execute_function.test.ts +++ b/x-pack/plugins/actions/server/create_execute_function.test.ts @@ -605,24 +605,27 @@ describe('bulkExecute()', () => { ] `); expect(savedObjectsClient.bulkGet).toHaveBeenCalledWith([{ id: '123', type: 'action' }]); - expect(savedObjectsClient.bulkCreate).toHaveBeenCalledWith([ - { - type: 'action_task_params', - attributes: { - actionId: '123', - params: { baz: false }, - executionId: '123abc', - apiKey: Buffer.from('123:abc').toString('base64'), - }, - references: [ - { - id: '123', - name: 'actionRef', - type: 'action', + expect(savedObjectsClient.bulkCreate).toHaveBeenCalledWith( + [ + { + type: 'action_task_params', + attributes: { + actionId: '123', + params: { baz: false }, + executionId: '123abc', + apiKey: Buffer.from('123:abc').toString('base64'), }, - ], - }, - ]); + references: [ + { + id: '123', + name: 'actionRef', + type: 'action', + }, + ], + }, + ], + { refresh: false } + ); expect(actionTypeRegistry.isActionExecutable).toHaveBeenCalledWith('123', 'mock-action', { notifyUsage: true, }); @@ -691,25 +694,28 @@ describe('bulkExecute()', () => { ] `); expect(savedObjectsClient.bulkGet).toHaveBeenCalledWith([{ id: '123', type: 'action' }]); - expect(savedObjectsClient.bulkCreate).toHaveBeenCalledWith([ - { - type: 'action_task_params', - attributes: { - actionId: '123', - params: { baz: false }, - executionId: '123abc', - consumer: 'test-consumer', - apiKey: Buffer.from('123:abc').toString('base64'), - }, - references: [ - { - id: '123', - name: 'actionRef', - type: 'action', + expect(savedObjectsClient.bulkCreate).toHaveBeenCalledWith( + [ + { + type: 'action_task_params', + attributes: { + actionId: '123', + params: { baz: false }, + executionId: '123abc', + consumer: 'test-consumer', + apiKey: Buffer.from('123:abc').toString('base64'), }, - ], - }, - ]); + references: [ + { + id: '123', + name: 'actionRef', + type: 'action', + }, + ], + }, + ], + { refresh: false } + ); expect(actionTypeRegistry.isActionExecutable).toHaveBeenCalledWith('123', 'mock-action', { notifyUsage: true, }); @@ -763,37 +769,40 @@ describe('bulkExecute()', () => { ], }, ]); - expect(savedObjectsClient.bulkCreate).toHaveBeenCalledWith([ - { - type: 'action_task_params', - attributes: { - actionId: '123', - params: { baz: false }, - apiKey: Buffer.from('123:abc').toString('base64'), - executionId: '123abc', - relatedSavedObjects: [ + expect(savedObjectsClient.bulkCreate).toHaveBeenCalledWith( + [ + { + type: 'action_task_params', + attributes: { + actionId: '123', + params: { baz: false }, + apiKey: Buffer.from('123:abc').toString('base64'), + executionId: '123abc', + relatedSavedObjects: [ + { + id: 'related_some-type_0', + namespace: 'some-namespace', + type: 'some-type', + typeId: 'some-typeId', + }, + ], + }, + references: [ { - id: 'related_some-type_0', - namespace: 'some-namespace', + id: '123', + name: 'actionRef', + type: 'action', + }, + { + id: 'some-id', + name: 'related_some-type_0', type: 'some-type', - typeId: 'some-typeId', }, ], }, - references: [ - { - id: '123', - name: 'actionRef', - type: 'action', - }, - { - id: 'some-id', - name: 'related_some-type_0', - type: 'some-type', - }, - ], - }, - ]); + ], + { refresh: false } + ); }); test('schedules the action with all given parameters with a preconfigured action', async () => { @@ -868,24 +877,27 @@ describe('bulkExecute()', () => { ] `); expect(savedObjectsClient.get).not.toHaveBeenCalled(); - expect(savedObjectsClient.bulkCreate).toHaveBeenCalledWith([ - { - type: 'action_task_params', - attributes: { - actionId: '123', - params: { baz: false }, - executionId: '123abc', - apiKey: Buffer.from('123:abc').toString('base64'), - }, - references: [ - { - id: source.id, - name: 'source', - type: source.type, + expect(savedObjectsClient.bulkCreate).toHaveBeenCalledWith( + [ + { + type: 'action_task_params', + attributes: { + actionId: '123', + params: { baz: false }, + executionId: '123abc', + apiKey: Buffer.from('123:abc').toString('base64'), }, - ], - }, - ]); + references: [ + { + id: source.id, + name: 'source', + type: source.type, + }, + ], + }, + ], + { refresh: false } + ); }); test('schedules the action with all given parameters with a preconfigured action and relatedSavedObjects', async () => { @@ -968,37 +980,40 @@ describe('bulkExecute()', () => { ] `); expect(savedObjectsClient.get).not.toHaveBeenCalled(); - expect(savedObjectsClient.bulkCreate).toHaveBeenCalledWith([ - { - type: 'action_task_params', - attributes: { - actionId: '123', - params: { baz: false }, - apiKey: Buffer.from('123:abc').toString('base64'), - executionId: '123abc', - relatedSavedObjects: [ + expect(savedObjectsClient.bulkCreate).toHaveBeenCalledWith( + [ + { + type: 'action_task_params', + attributes: { + actionId: '123', + params: { baz: false }, + apiKey: Buffer.from('123:abc').toString('base64'), + executionId: '123abc', + relatedSavedObjects: [ + { + id: 'related_some-type_0', + namespace: 'some-namespace', + type: 'some-type', + typeId: 'some-typeId', + }, + ], + }, + references: [ { - id: 'related_some-type_0', - namespace: 'some-namespace', + id: source.id, + name: 'source', + type: source.type, + }, + { + id: 'some-id', + name: 'related_some-type_0', type: 'some-type', - typeId: 'some-typeId', }, ], }, - references: [ - { - id: source.id, - name: 'source', - type: source.type, - }, - { - id: 'some-id', - name: 'related_some-type_0', - type: 'some-type', - }, - ], - }, - ]); + ], + { refresh: false } + ); }); test('throws when passing isESOCanEncrypt with false as a value', async () => { diff --git a/x-pack/plugins/actions/server/create_execute_function.ts b/x-pack/plugins/actions/server/create_execute_function.ts index 19447bf8e79e5..c050cf34c9fca 100644 --- a/x-pack/plugins/actions/server/create_execute_function.ts +++ b/x-pack/plugins/actions/server/create_execute_function.ts @@ -207,7 +207,7 @@ export function createBulkExecutionEnqueuerFunction({ }; }); const actionTaskParamsRecords: SavedObjectsBulkResponse = - await unsecuredSavedObjectsClient.bulkCreate(actions); + await unsecuredSavedObjectsClient.bulkCreate(actions, { refresh: false }); const taskInstances = actionTaskParamsRecords.saved_objects.map((so) => { const actionId = so.attributes.actionId; return { diff --git a/x-pack/plugins/aiops/common/index.ts b/x-pack/plugins/aiops/common/index.ts index 0726447532aa2..b4ec6c287b22d 100755 --- a/x-pack/plugins/aiops/common/index.ts +++ b/x-pack/plugins/aiops/common/index.ts @@ -21,4 +21,4 @@ export const PLUGIN_NAME = 'AIOps'; */ export const AIOPS_ENABLED = true; -export const CHANGE_POINT_DETECTION_ENABLED = false; +export const CHANGE_POINT_DETECTION_ENABLED = true; diff --git a/x-pack/plugins/aiops/public/components/log_categorization/use_discover_links.ts b/x-pack/plugins/aiops/public/components/log_categorization/use_discover_links.ts index 8a1c438199878..a56d5c0cdfc6e 100644 --- a/x-pack/plugins/aiops/public/components/log_categorization/use_discover_links.ts +++ b/x-pack/plugins/aiops/public/components/log_categorization/use_discover_links.ts @@ -5,7 +5,7 @@ * 2.0. */ -import rison from 'rison-node'; +import rison from '@kbn/rison'; import moment from 'moment'; import type { TimeRangeBounds } from '@kbn/data-plugin/common'; diff --git a/x-pack/plugins/aiops/public/hooks/use_url_state.tsx b/x-pack/plugins/aiops/public/hooks/use_url_state.tsx index c4d84163f887e..94273a204f5cc 100644 --- a/x-pack/plugins/aiops/public/hooks/use_url_state.tsx +++ b/x-pack/plugins/aiops/public/hooks/use_url_state.tsx @@ -8,7 +8,7 @@ import React, { FC } from 'react'; import { parse, stringify } from 'query-string'; import { createContext, useCallback, useContext, useMemo } from 'react'; -import { decode, encode } from 'rison-node'; +import { decode, encode } from '@kbn/rison'; import { useHistory, useLocation } from 'react-router-dom'; import { isEqual } from 'lodash'; diff --git a/x-pack/plugins/alerting/server/rules_client/rules_client.ts b/x-pack/plugins/alerting/server/rules_client/rules_client.ts index fa0bee7d9a338..5feb6ab8c0445 100644 --- a/x-pack/plugins/alerting/server/rules_client/rules_client.ts +++ b/x-pack/plugins/alerting/server/rules_client/rules_client.ts @@ -633,6 +633,7 @@ export class RulesClient { mutedInstanceIds: [], executionStatus: getRuleExecutionStatusPending(lastRunTimestamp.toISOString()), monitoring: getDefaultMonitoring(lastRunTimestamp.toISOString()), + scheduledTaskId: null, }; this.auditLogger?.log( diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/e2e/power_user/service_groups/generate_data.ts b/x-pack/plugins/apm/ftr_e2e/cypress/e2e/power_user/service_groups/generate_data.ts new file mode 100644 index 0000000000000..970c605dcf278 --- /dev/null +++ b/x-pack/plugins/apm/ftr_e2e/cypress/e2e/power_user/service_groups/generate_data.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 { apm, timerange } from '@kbn/apm-synthtrace'; + +export function generateData({ from, to }: { from: number; to: number }) { + const range = timerange(from, to); + const synthGo1 = apm + .service({ + name: 'synth-go-1', + environment: 'production', + agentName: 'go', + }) + .instance('my-instance'); + const synthGo2 = apm + .service({ name: 'synth-go-2', environment: 'production', agentName: 'go' }) + .instance('my-instance'); + const synthNode = apm + .service({ + name: 'synth-node-1', + environment: 'production', + agentName: 'nodejs', + }) + .instance('my-instance'); + + return range.interval('1m').generator((timestamp) => { + return [ + synthGo1 + .transaction({ transactionName: 'GET /apple 🍎' }) + .timestamp(timestamp) + .duration(1000) + .success(), + synthGo2 + .transaction({ transactionName: 'GET /banana 🍌' }) + .timestamp(timestamp) + .duration(1000) + .success(), + synthNode + .transaction({ transactionName: 'GET /apple 🍎' }) + .timestamp(timestamp) + .duration(1000) + .success(), + ]; + }); +} diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/e2e/power_user/service_groups/service_groups.cy.ts b/x-pack/plugins/apm/ftr_e2e/cypress/e2e/power_user/service_groups/service_groups.cy.ts new file mode 100644 index 0000000000000..a83766389a1f2 --- /dev/null +++ b/x-pack/plugins/apm/ftr_e2e/cypress/e2e/power_user/service_groups/service_groups.cy.ts @@ -0,0 +1,115 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import url from 'url'; +import { synthtrace } from '../../../../synthtrace'; +import { generateData } from './generate_data'; + +const start = Date.now() - 1000; +const end = Date.now(); + +const serviceGroupsHref = url.format({ + pathname: 'app/apm/service-groups', + query: { + rangeFrom: new Date(start).toISOString(), + rangeTo: new Date(end).toISOString(), + }, +}); + +const deleteAllServiceGroups = () => { + const kibanaUrl = Cypress.env('KIBANA_URL'); + cy.request({ + log: false, + method: 'GET', + url: `${kibanaUrl}/internal/apm/service-groups`, + body: {}, + headers: { + 'kbn-xsrf': 'e2e_test', + }, + auth: { user: 'editor', pass: 'changeme' }, + }).then((response) => { + const promises = response.body.serviceGroups.map((item: any) => { + if (item.id) { + return cy.request({ + log: false, + method: 'DELETE', + url: `${kibanaUrl}/internal/apm/service-group?serviceGroupId=${item.id}`, + headers: { + 'kbn-xsrf': 'e2e_test', + }, + auth: { user: 'editor', pass: 'changeme' }, + }); + } + }); + return Promise.all(promises); + }); +}; + +describe('Service groups', () => { + before(() => { + synthtrace.index( + generateData({ + from: new Date(start).getTime(), + to: new Date(end).getTime(), + }) + ); + }); + + after(() => { + synthtrace.clean(); + }); + + describe('When navigating to service groups', () => { + beforeEach(() => { + cy.loginAsEditorUser(); + cy.visitKibana(serviceGroupsHref); + }); + + after(() => { + deleteAllServiceGroups(); + }); + + describe('when there are not service groups', () => { + before(() => { + deleteAllServiceGroups(); + }); + it('shows no service groups', () => { + cy.contains('h2', 'No service groups'); + }); + + it('creates a service group', () => { + cy.getByTestSubj('apmCreateServiceGroupButton').click(); + cy.getByTestSubj('apmGroupNameInput').type('go services'); + cy.contains('Select services').click(); + cy.getByTestSubj('headerFilterKuerybar').type('agent.name:"go"{enter}'); + cy.contains('synth-go-1'); + cy.contains('synth-go-2'); + cy.contains('Save group').click(); + }); + }); + + describe('when there are service groups', () => { + it('shows service groups', () => { + cy.contains('1 group'); + cy.getByTestSubj('serviceGroupCard') + .should('contain', 'go services') + .should('contain', '2 services'); + }); + it('opens service list when click in service group card', () => { + cy.getByTestSubj('serviceGroupCard').click(); + cy.contains('go services'); + cy.contains('synth-go-1'); + cy.contains('synth-go-2'); + }); + it('deletes service group', () => { + cy.getByTestSubj('serviceGroupCard').click(); + cy.get('button:contains(Edit group)').click(); + cy.getByTestSubj('apmDeleteGroupButton').click(); + cy.contains('h2', 'No service groups'); + }); + }); + }); +}); diff --git a/x-pack/plugins/apm/public/components/alerting/rule_types/register_apm_rule_types.ts b/x-pack/plugins/apm/public/components/alerting/rule_types/register_apm_rule_types.ts index 4b4cc42e08089..ed9971307bf64 100644 --- a/x-pack/plugins/apm/public/components/alerting/rule_types/register_apm_rule_types.ts +++ b/x-pack/plugins/apm/public/components/alerting/rule_types/register_apm_rule_types.ts @@ -33,7 +33,8 @@ export function registerApmRuleTypes( return { reason: fields[ALERT_REASON]!, link: getAlertUrlErrorCount( - String(fields[SERVICE_NAME][0]!), + // TODO:fix SERVICE_NAME when we move it to initializeIndex + String(fields[SERVICE_NAME]![0]), fields[SERVICE_ENVIRONMENT] && String(fields[SERVICE_ENVIRONMENT][0]) ), }; @@ -46,6 +47,12 @@ export function registerApmRuleTypes( validate: () => ({ errors: [], }), + alertDetailsAppSection: lazy( + () => + import( + '../ui_components/alert_details_app_section/alert_details_app_section' + ) + ), requiresAppContext: false, defaultActionMessage: i18n.translate( 'xpack.apm.alertTypes.errorCount.defaultActionMessage', @@ -73,9 +80,10 @@ export function registerApmRuleTypes( return { reason: fields[ALERT_REASON]!, link: getAlertUrlTransaction( - String(fields[SERVICE_NAME][0]!), + // TODO:fix SERVICE_NAME when we move it to initializeIndex + String(fields[SERVICE_NAME]![0]), fields[SERVICE_ENVIRONMENT] && String(fields[SERVICE_ENVIRONMENT][0]), - String(fields[TRANSACTION_TYPE][0]!) + String(fields[TRANSACTION_TYPE]![0]) ), }; }, @@ -89,6 +97,12 @@ export function registerApmRuleTypes( validate: () => ({ errors: [], }), + alertDetailsAppSection: lazy( + () => + import( + '../ui_components/alert_details_app_section/alert_details_app_section' + ) + ), requiresAppContext: false, defaultActionMessage: i18n.translate( 'xpack.apm.alertTypes.transactionDuration.defaultActionMessage', @@ -116,9 +130,10 @@ export function registerApmRuleTypes( format: ({ fields, formatters: { asPercent } }) => ({ reason: fields[ALERT_REASON]!, link: getAlertUrlTransaction( - String(fields[SERVICE_NAME][0]!), + // TODO:fix SERVICE_NAME when we move it to initializeIndex + String(fields[SERVICE_NAME]![0]), fields[SERVICE_ENVIRONMENT] && String(fields[SERVICE_ENVIRONMENT][0]), - String(fields[TRANSACTION_TYPE][0]!) + String(fields[TRANSACTION_TYPE]![0]) ), }), iconClass: 'bell', @@ -131,6 +146,12 @@ export function registerApmRuleTypes( validate: () => ({ errors: [], }), + alertDetailsAppSection: lazy( + () => + import( + '../ui_components/alert_details_app_section/alert_details_app_section' + ) + ), requiresAppContext: false, defaultActionMessage: i18n.translate( 'xpack.apm.alertTypes.transactionErrorRate.defaultActionMessage', @@ -155,9 +176,10 @@ export function registerApmRuleTypes( format: ({ fields }) => ({ reason: fields[ALERT_REASON]!, link: getAlertUrlTransaction( - String(fields[SERVICE_NAME][0]!), + // TODO:fix SERVICE_NAME when we move it to initializeIndex + String(fields[SERVICE_NAME]![0]), fields[SERVICE_ENVIRONMENT] && String(fields[SERVICE_ENVIRONMENT][0]), - String(fields[TRANSACTION_TYPE][0]!) + String(fields[TRANSACTION_TYPE]![0]) ), }), iconClass: 'bell', @@ -170,6 +192,12 @@ export function registerApmRuleTypes( validate: () => ({ errors: [], }), + alertDetailsAppSection: lazy( + () => + import( + '../ui_components/alert_details_app_section/alert_details_app_section' + ) + ), requiresAppContext: false, defaultActionMessage: i18n.translate( 'xpack.apm.alertTypes.transactionDurationAnomaly.defaultActionMessage', diff --git a/x-pack/plugins/apm/public/components/alerting/ui_components/alert_details_app_section/alert_details_app_section.tsx b/x-pack/plugins/apm/public/components/alerting/ui_components/alert_details_app_section/alert_details_app_section.tsx new file mode 100644 index 0000000000000..92cd229333062 --- /dev/null +++ b/x-pack/plugins/apm/public/components/alerting/ui_components/alert_details_app_section/alert_details_app_section.tsx @@ -0,0 +1,419 @@ +/* + * Copyright 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 { EuiFlexGroup } from '@elastic/eui'; +import { EuiFlexItem } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { EuiPanel } from '@elastic/eui'; +import { EuiTitle } from '@elastic/eui'; +import { EuiIconTip } from '@elastic/eui'; +import { ALERT_DURATION, ALERT_END } from '@kbn/rule-data-utils'; +import moment from 'moment'; +import { ENVIRONMENT_ALL } from '../../../../../common/environment_filter_values'; +import { getTransactionType } from '../../../../context/apm_service/apm_service_context'; +import { useServiceAgentFetcher } from '../../../../context/apm_service/use_service_agent_fetcher'; +import { useServiceTransactionTypesFetcher } from '../../../../context/apm_service/use_service_transaction_types_fetcher'; +import { asPercent } from '../../../../../common/utils/formatters'; +import { APIReturnType } from '../../../../services/rest/create_call_apm_api'; +import { getDurationFormatter } from '../../../../../common/utils/formatters/duration'; +import { useFetcher } from '../../../../hooks/use_fetcher'; +import { useTimeRange } from '../../../../hooks/use_time_range'; +import { isTimeComparison } from '../../../shared/time_comparison/get_comparison_options'; +import { getComparisonChartTheme } from '../../../shared/time_comparison/get_comparison_chart_theme'; +import { getLatencyChartSelector } from '../../../../selectors/latency_chart_selectors'; +import { TimeseriesChart } from '../../../shared/charts/timeseries_chart'; +import { + getMaxY, + getResponseTimeTickFormatter, +} from '../../../shared/charts/transaction_charts/helper'; +import { ChartPointerEventContextProvider } from '../../../../context/chart_pointer_event/chart_pointer_event_context'; +import { + ChartType, + getTimeSeriesColor, +} from '../../../shared/charts/helper/get_timeseries_color'; +import { + AlertDetailsAppSectionProps, + SERVICE_NAME, + TRANSACTION_TYPE, +} from './types'; +import { getAggsTypeFromRule } from './helpers'; +import { filterNil } from '../../../shared/charts/latency_chart'; +import { errorRateI18n } from '../../../shared/charts/failed_transaction_rate_chart'; + +export function AlertDetailsAppSection({ + rule, + alert, + timeZone, +}: AlertDetailsAppSectionProps) { + const params = rule.params; + const environment = String(params.environment) || ENVIRONMENT_ALL.value; + const latencyAggregationType = getAggsTypeFromRule( + params.aggregationType as string + ); + + // duration is us, convert it to MS + const alertDurationMS = alert.fields[ALERT_DURATION]! / 1000; + + const serviceName = String(alert.fields[SERVICE_NAME]); + + // Currently, we don't use comparisonEnabled nor offset. + // But providing them as they are required for the chart. + const comparisonEnabled = false; + const offset = '1d'; + const ruleWindowSizeMS = moment + .duration(rule.params.windowSize, rule.params.windowUnit) + .asMilliseconds(); + + const TWENTY_TIMES_RULE_WINDOW_MS = 20 * ruleWindowSizeMS; + /** + * This is part or the requirements (RFC). + * If the alert is less than 20 units of `FOR THE LAST ` then we should draw a time range of 20 units. + * IE. The user set "FOR THE LAST 5 minutes" at a minimum we should show 100 minutes. + */ + const rangeFrom = + alertDurationMS < TWENTY_TIMES_RULE_WINDOW_MS + ? moment(alert.start) + .subtract(TWENTY_TIMES_RULE_WINDOW_MS, 'millisecond') + .toISOString() + : moment(alert.start) + .subtract(ruleWindowSizeMS, 'millisecond') + .toISOString(); + + const rangeTo = alert.active + ? 'now' + : moment(alert.fields[ALERT_END]) + .add(ruleWindowSizeMS, 'millisecond') + .toISOString(); + + const { start, end } = useTimeRange({ rangeFrom, rangeTo }); + const { agentName } = useServiceAgentFetcher({ + serviceName, + start, + end, + }); + const transactionTypes = useServiceTransactionTypesFetcher({ + serviceName, + start, + end, + }); + + const transactionType = getTransactionType({ + transactionType: String(alert.fields[TRANSACTION_TYPE]), + transactionTypes, + agentName, + }); + + const comparisonChartTheme = getComparisonChartTheme(); + const INITIAL_STATE = { + currentPeriod: [], + previousPeriod: [], + }; + + /* Latency Chart */ + const { data, status } = useFetcher( + (callApmApi) => { + if ( + serviceName && + start && + end && + transactionType && + latencyAggregationType + ) { + return callApmApi( + `GET /internal/apm/services/{serviceName}/transactions/charts/latency`, + { + params: { + path: { serviceName }, + query: { + environment, + kuery: '', + start, + end, + transactionType, + transactionName: undefined, + latencyAggregationType, + }, + }, + } + ); + } + }, + [ + end, + environment, + latencyAggregationType, + serviceName, + start, + transactionType, + ] + ); + + const memoizedData = useMemo( + () => + getLatencyChartSelector({ + latencyChart: data, + latencyAggregationType, + previousPeriodLabel: '', + }), + // It should only update when the data has changed + // eslint-disable-next-line react-hooks/exhaustive-deps + [data] + ); + const { currentPeriod, previousPeriod } = memoizedData; + + const timeseriesLatency = [ + currentPeriod, + comparisonEnabled && isTimeComparison(offset) ? previousPeriod : undefined, + ].filter(filterNil); + + const latencyMaxY = getMaxY(timeseriesLatency); + const latencyFormatter = getDurationFormatter(latencyMaxY); + + /* Latency Chart */ + + /* Throughput Chart */ + const { data: dataThroughput = INITIAL_STATE, status: statusThroughput } = + useFetcher( + (callApmApi) => { + if (serviceName && transactionType && start && end) { + return callApmApi( + 'GET /internal/apm/services/{serviceName}/throughput', + { + params: { + path: { + serviceName, + }, + query: { + environment, + kuery: '', + start, + end, + transactionType, + transactionName: undefined, + }, + }, + } + ); + } + }, + [environment, serviceName, start, end, transactionType] + ); + const { currentPeriodColor, previousPeriodColor } = getTimeSeriesColor( + ChartType.THROUGHPUT + ); + const timeseriesThroughput = [ + { + data: dataThroughput.currentPeriod, + type: 'linemark', + color: currentPeriodColor, + title: i18n.translate('xpack.apm.serviceOverview.throughtputChartTitle', { + defaultMessage: 'Throughput', + }), + }, + ...(comparisonEnabled + ? [ + { + data: dataThroughput.previousPeriod, + type: 'area', + color: previousPeriodColor, + title: '', + }, + ] + : []), + ]; + + /* Throughput Chart */ + + /* Error Rate */ + type ErrorRate = + APIReturnType<'GET /internal/apm/services/{serviceName}/transactions/charts/error_rate'>; + + const INITIAL_STATE_ERROR_RATE: ErrorRate = { + currentPeriod: { + timeseries: [], + average: null, + }, + previousPeriod: { + timeseries: [], + average: null, + }, + }; + function yLabelFormat(y?: number | null) { + return asPercent(y || 0, 1); + } + + const { + data: dataErrorRate = INITIAL_STATE_ERROR_RATE, + status: statusErrorRate, + } = useFetcher( + (callApmApi) => { + if (transactionType && serviceName && start && end) { + return callApmApi( + 'GET /internal/apm/services/{serviceName}/transactions/charts/error_rate', + { + params: { + path: { + serviceName, + }, + query: { + environment, + kuery: '', + start, + end, + transactionType, + transactionName: undefined, + }, + }, + } + ); + } + }, + [environment, serviceName, start, end, transactionType] + ); + + const { currentPeriodColor: currentPeriodColorErrorRate } = + getTimeSeriesColor(ChartType.FAILED_TRANSACTION_RATE); + + const timeseriesErrorRate = [ + { + data: dataErrorRate.currentPeriod.timeseries, + type: 'linemark', + color: currentPeriodColorErrorRate, + title: i18n.translate('xpack.apm.errorRate.chart.errorRate', { + defaultMessage: 'Failed transaction rate (avg.)', + }), + }, + ]; + + /* Error Rate */ + + return ( + + + + + + + +

    + {i18n.translate( + 'xpack.apm.dependencyLatencyChart.chartTitle', + { + defaultMessage: 'Latency', + } + )} +

    +
    +
    +
    + +
    +
    + + + + + + + + +

    + {i18n.translate( + 'xpack.apm.serviceOverview.throughtputChartTitle', + { defaultMessage: 'Throughput' } + )} +

    +
    +
    + + + + +
    + + +
    +
    + + + + + +

    + {i18n.translate('xpack.apm.errorRate', { + defaultMessage: 'Failed transaction rate', + })} +

    +
    +
    + + + + +
    + + +
    +
    +
    +
    +
    +
    + ); +} + +// eslint-disable-next-line import/no-default-export +export default AlertDetailsAppSection; diff --git a/x-pack/plugins/apm/public/components/alerting/ui_components/alert_details_app_section/helpers.ts b/x-pack/plugins/apm/public/components/alerting/ui_components/alert_details_app_section/helpers.ts new file mode 100644 index 0000000000000..a095f8caa4574 --- /dev/null +++ b/x-pack/plugins/apm/public/components/alerting/ui_components/alert_details_app_section/helpers.ts @@ -0,0 +1,16 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { LatencyAggregationType } from '../../../../../common/latency_aggregation_types'; + +export const getAggsTypeFromRule = ( + ruleAggType: string +): LatencyAggregationType => { + if (ruleAggType === '95th') return LatencyAggregationType.p95; + if (ruleAggType === '99th') return LatencyAggregationType.p99; + return LatencyAggregationType.avg; +}; diff --git a/x-pack/plugins/apm/public/components/alerting/ui_components/alert_details_app_section/types.ts b/x-pack/plugins/apm/public/components/alerting/ui_components/alert_details_app_section/types.ts new file mode 100644 index 0000000000000..0094d9332009a --- /dev/null +++ b/x-pack/plugins/apm/public/components/alerting/ui_components/alert_details_app_section/types.ts @@ -0,0 +1,24 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { Rule } from '@kbn/alerting-plugin/common'; +import { TopAlert } from '@kbn/observability-plugin/public/pages/alerts'; +import { TIME_UNITS } from '@kbn/triggers-actions-ui-plugin/public'; +import { LatencyAggregationType } from '../../../../../common/latency_aggregation_types'; + +export const SERVICE_NAME = 'service.name' as const; +export const TRANSACTION_TYPE = 'transaction.type' as const; +export interface AlertDetailsAppSectionProps { + rule: Rule<{ + environment: string; + aggregationType: LatencyAggregationType; + windowSize: number; + windowUnit: TIME_UNITS; + }>; + alert: TopAlert<{ [SERVICE_NAME]: string; [TRANSACTION_TYPE]: string }>; + timeZone: string; +} diff --git a/x-pack/plugins/apm/public/components/app/metrics/serverless_metrics/serverless_active_instances.tsx b/x-pack/plugins/apm/public/components/app/metrics/serverless_metrics/serverless_active_instances.tsx index 9c44d472c5b70..a0a72526e3632 100644 --- a/x-pack/plugins/apm/public/components/app/metrics/serverless_metrics/serverless_active_instances.tsx +++ b/x-pack/plugins/apm/public/components/app/metrics/serverless_metrics/serverless_active_instances.tsx @@ -27,7 +27,7 @@ import { useApmParams } from '../../../../hooks/use_apm_params'; import { FETCH_STATUS, useFetcher } from '../../../../hooks/use_fetcher'; import { useTimeRange } from '../../../../hooks/use_time_range'; import { APIReturnType } from '../../../../services/rest/create_call_apm_api'; -import { TimeseriesChart } from '../../../shared/charts/timeseries_chart'; +import { TimeseriesChartWithContext } from '../../../shared/charts/timeseries_chart_with_context'; import { ListMetric } from '../../../shared/list_metric'; import { ServerlessFunctionNameLink } from './serverless_function_name_link'; @@ -201,7 +201,7 @@ export function ServerlessActiveInstances({ serverlessId }: Props) {
    - { setName(e.target.value); @@ -172,6 +173,7 @@ export function GroupDetails({ }} color="danger" isDisabled={isLoading} + data-test-subj="apmDeleteGroupButton" > {i18n.translate( 'xpack.apm.serviceGroups.groupDetailsForm.deleteGroup', diff --git a/x-pack/plugins/apm/public/components/app/service_groups/service_groups_list/service_group_card.tsx b/x-pack/plugins/apm/public/components/app/service_groups/service_groups_list/service_group_card.tsx index bc8a424c922b9..080b3772b6250 100644 --- a/x-pack/plugins/apm/public/components/app/service_groups/service_groups_list/service_group_card.tsx +++ b/x-pack/plugins/apm/public/components/app/service_groups/service_groups_list/service_group_card.tsx @@ -81,7 +81,11 @@ export function ServiceGroupsCard({ return ( - + ); } diff --git a/x-pack/plugins/apm/public/components/app/service_overview/service_overview_throughput_chart.tsx b/x-pack/plugins/apm/public/components/app/service_overview/service_overview_throughput_chart.tsx index 3c1ab8cde0b17..5e7c02610d7c8 100644 --- a/x-pack/plugins/apm/public/components/app/service_overview/service_overview_throughput_chart.tsx +++ b/x-pack/plugins/apm/public/components/app/service_overview/service_overview_throughput_chart.tsx @@ -24,7 +24,7 @@ import { useApmParams } from '../../../hooks/use_apm_params'; import { useFetcher } from '../../../hooks/use_fetcher'; import { usePreferredServiceAnomalyTimeseries } from '../../../hooks/use_preferred_service_anomaly_timeseries'; import { useTimeRange } from '../../../hooks/use_time_range'; -import { TimeseriesChart } from '../../shared/charts/timeseries_chart'; +import { TimeseriesChartWithContext } from '../../shared/charts/timeseries_chart_with_context'; import { getComparisonChartTheme } from '../../shared/time_comparison/get_comparison_chart_theme'; import { ChartType, @@ -152,7 +152,7 @@ export function ServiceOverviewThroughputChart({
    - , + append: , label: i18n.translate('xpack.apm.home.infraTabLabel', { defaultMessage: 'Infrastructure', }), diff --git a/x-pack/plugins/apm/public/components/routing/templates/dependency_detail_template.tsx b/x-pack/plugins/apm/public/components/routing/templates/dependency_detail_template.tsx index f7cf9734dcdce..833b489004bf3 100644 --- a/x-pack/plugins/apm/public/components/routing/templates/dependency_detail_template.tsx +++ b/x-pack/plugins/apm/public/components/routing/templates/dependency_detail_template.tsx @@ -91,7 +91,7 @@ export function DependencyDetailTemplate({ children }: Props) { isSelected: path === '/dependencies/operations' || path === '/dependencies/operation', - append: , + append: , }, ] : []; diff --git a/x-pack/plugins/apm/public/components/shared/agent_icon/icons/functions.svg b/x-pack/plugins/apm/public/components/shared/agent_icon/icons/functions.svg new file mode 100644 index 0000000000000..172fe00a49d85 --- /dev/null +++ b/x-pack/plugins/apm/public/components/shared/agent_icon/icons/functions.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/x-pack/plugins/apm/public/components/shared/charts/failed_transaction_rate_chart/index.tsx b/x-pack/plugins/apm/public/components/shared/charts/failed_transaction_rate_chart/index.tsx index dacb295a011dd..508d3d0f0ed68 100644 --- a/x-pack/plugins/apm/public/components/shared/charts/failed_transaction_rate_chart/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/charts/failed_transaction_rate_chart/index.tsx @@ -15,7 +15,7 @@ import { APIReturnType } from '../../../../services/rest/create_call_apm_api'; import { asPercent } from '../../../../../common/utils/formatters'; import { useFetcher } from '../../../../hooks/use_fetcher'; import { useLegacyUrlParams } from '../../../../context/url_params_context/use_url_params'; -import { TimeseriesChart } from '../timeseries_chart'; +import { TimeseriesChartWithContext } from '../timeseries_chart_with_context'; import { useApmServiceContext } from '../../../../context/apm_service/use_apm_service_context'; import { getComparisonChartTheme } from '../../time_comparison/get_comparison_chart_theme'; import { useApmParams } from '../../../../hooks/use_apm_params'; @@ -49,6 +49,10 @@ const INITIAL_STATE: ErrorRate = { }, }; +export const errorRateI18n = i18n.translate('xpack.apm.errorRate.tip', { + defaultMessage: + "The percentage of failed transactions for the selected service. HTTP server transactions with a 4xx status code (client error) aren't considered failures because the caller, not the server, caused the failure.", +}); export function FailedTransactionRateChart({ height, showAnnotations = true, @@ -154,17 +158,11 @@ export function FailedTransactionRateChart({
    - +
    - = [ { value: LatencyAggregationType.p99, text: '99th percentile' }, ]; -function filterNil(value: T | null | undefined): value is T { +export function filterNil(value: T | null | undefined): value is T { return value != null; } @@ -126,7 +126,7 @@ export function LatencyChart({ height, kuery }: Props) {
    - )}
    - >; - /** - * Formatter for y-axis tick values - */ - yLabelFormat: (y: number) => string; - /** - * Formatter for legend and tooltip values - */ - yTickFormat?: (y: number) => string; - showAnnotations?: boolean; - yDomain?: YDomainRange; - anomalyTimeseries?: AnomalyTimeseries; - customTheme?: Record; - anomalyTimeseriesColor?: string; -} +import { TimeseriesChartWithContextProps } from './timeseries_chart_with_context'; const END_ZONE_LABEL = i18n.translate('xpack.apm.timeseries.endzone', { defaultMessage: 'The selected time range does not include this entire bucket. It might contain partial data.', }); - +interface TimeseriesChartProps extends TimeseriesChartWithContextProps { + comparisonEnabled: boolean; + offset?: string; + timeZone: string; +} export function TimeseriesChart({ id, height = unit * 16, @@ -91,30 +64,22 @@ export function TimeseriesChart({ yDomain, anomalyTimeseries, customTheme = {}, -}: Props) { + comparisonEnabled, + offset, + timeZone, +}: TimeseriesChartProps) { const history = useHistory(); - const { core } = useApmPluginContext(); const { annotations } = useAnnotationsContext(); const { chartRef, updatePointerEvent } = useChartPointerEventContext(); const theme = useTheme(); const chartTheme = useChartTheme(); - const { - query: { comparisonEnabled, offset }, - } = useAnyOfApmParams( - '/services', - '/dependencies/*', - '/services/{serviceName}' - ); - const anomalyChartTimeseries = getChartAnomalyTimeseries({ anomalyTimeseries, theme, anomalyTimeseriesColor: anomalyTimeseries?.color, }); - const isEmpty = isTimeseriesEmpty(timeseries); const annotationColor = theme.eui.euiColorSuccess; - const isComparingExpectedBounds = comparisonEnabled && isExpectedBoundsComparison(offset); const allSeries = [ @@ -134,20 +99,14 @@ export function TimeseriesChart({ ); const xValues = timeseries.flatMap(({ data }) => data.map(({ x }) => x)); - const xValuesExpectedBounds = anomalyChartTimeseries?.boundaries?.flatMap(({ data }) => data.map(({ x }) => x) ) ?? []; - - const timeZone = getTimeZone(core.uiSettings); - const min = Math.min(...xValues); const max = Math.max(...xValues, ...xValuesExpectedBounds); const xFormatter = niceTimeFormatter([min, max]); - const xDomain = isEmpty ? { min: 0, max: 1 } : { min, max }; - // Using custom legendSort here when comparing expected bounds // because by default elastic-charts will show legends for expected bounds first // but for consistency, we are making `Expected bounds` last diff --git a/x-pack/plugins/apm/public/components/shared/charts/timeseries_chart_with_context.tsx b/x-pack/plugins/apm/public/components/shared/charts/timeseries_chart_with_context.tsx new file mode 100644 index 0000000000000..5c9aac5d28bdf --- /dev/null +++ b/x-pack/plugins/apm/public/components/shared/charts/timeseries_chart_with_context.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 { LegendItemListener, YDomainRange } from '@elastic/charts'; +import React from 'react'; +import { useAnyOfApmParams } from '../../../hooks/use_apm_params'; +import { ServiceAnomalyTimeseries } from '../../../../common/anomaly_detection/service_anomaly_timeseries'; +import { Coordinate, TimeSeries } from '../../../../typings/timeseries'; +import { useApmPluginContext } from '../../../context/apm_plugin/use_apm_plugin_context'; +import { FETCH_STATUS } from '../../../hooks/use_fetcher'; +import { unit } from '../../../utils/style'; +import { getTimeZone } from './helper/timezone'; +import { TimeseriesChart } from './timeseries_chart'; + +interface AnomalyTimeseries extends ServiceAnomalyTimeseries { + color?: string; +} +export interface TimeseriesChartWithContextProps { + id: string; + fetchStatus: FETCH_STATUS; + height?: number; + onToggleLegend?: LegendItemListener; + timeseries: Array>; + /** + * Formatter for y-axis tick values + */ + yLabelFormat: (y: number) => string; + /** + * Formatter for legend and tooltip values + */ + yTickFormat?: (y: number) => string; + showAnnotations?: boolean; + yDomain?: YDomainRange; + anomalyTimeseries?: AnomalyTimeseries; + customTheme?: Record; + anomalyTimeseriesColor?: string; +} + +export function TimeseriesChartWithContext({ + id, + height = unit * 16, + fetchStatus, + onToggleLegend, + timeseries, + yLabelFormat, + yTickFormat, + showAnnotations = true, + yDomain, + anomalyTimeseries, + customTheme = {}, +}: TimeseriesChartWithContextProps) { + const { + query: { comparisonEnabled, offset }, + } = useAnyOfApmParams( + '/services', + '/dependencies/*', + '/services/{serviceName}' + ); + const { core } = useApmPluginContext(); + const timeZone = getTimeZone(core.uiSettings); + + return ( + + ); +} diff --git a/x-pack/plugins/apm/public/components/shared/charts/transaction_coldstart_rate_chart/index.tsx b/x-pack/plugins/apm/public/components/shared/charts/transaction_coldstart_rate_chart/index.tsx index a3143bb7b6849..3dfc22a1c2809 100644 --- a/x-pack/plugins/apm/public/components/shared/charts/transaction_coldstart_rate_chart/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/charts/transaction_coldstart_rate_chart/index.tsx @@ -20,7 +20,7 @@ import { APIReturnType } from '../../../../services/rest/create_call_apm_api'; import { asPercent } from '../../../../../common/utils/formatters'; import { useFetcher } from '../../../../hooks/use_fetcher'; import { useTheme } from '../../../../hooks/use_theme'; -import { TimeseriesChart } from '../timeseries_chart'; +import { TimeseriesChartWithContext } from '../timeseries_chart_with_context'; import { useApmServiceContext } from '../../../../context/apm_service/use_apm_service_context'; import { getComparisonChartTheme } from '../../time_comparison/get_comparison_chart_theme'; import { useApmParams } from '../../../../hooks/use_apm_params'; @@ -161,7 +161,7 @@ export function TransactionColdstartRateChart({ />
    - { ); expect(href).toMatchInlineSnapshot( - `"/app/ml/explorer?_g=(ml:(jobIds:!(myservicename-mytransactiontype-high_mean_response_time)),refreshInterval:(pause:!t,value:10000),time:(from:now%2Fw,to:now-4h))&_a=(explorer:(mlExplorerFilter:(),mlExplorerSwimlane:()))"` + `"/app/ml/explorer?_g=(ml:(jobIds:!(myservicename-mytransactiontype-high_mean_response_time)),refreshInterval:(pause:!t,value:60000),time:(from:now%2Fw,to:now-4h))&_a=(explorer:(mlExplorerFilter:(),mlExplorerSwimlane:()))"` ); }); @@ -34,12 +34,12 @@ describe('MLExplorerLink', () => { ), { search: - '?rangeFrom=2020-07-29T17:27:29.000Z&rangeTo=2020-07-29T18:45:00.000Z&refreshInterval=10000&refreshPaused=true', + '?rangeFrom=2020-07-29T17:27:29.000Z&rangeTo=2020-07-29T18:45:00.000Z&refreshInterval=60000&refreshPaused=true', } as Location ); expect(href).toMatchInlineSnapshot( - `"/app/ml/explorer?_g=(ml:(jobIds:!(apm-production-485b-high_mean_transaction_duration)),refreshInterval:(pause:!t,value:10000),time:(from:'2020-07-29T17:27:29.000Z',to:'2020-07-29T18:45:00.000Z'))&_a=(explorer:(mlExplorerFilter:(),mlExplorerSwimlane:()))"` + `"/app/ml/explorer?_g=(ml:(jobIds:!(apm-production-485b-high_mean_transaction_duration)),refreshInterval:(pause:!t,value:60000),time:(from:'2020-07-29T17:27:29.000Z',to:'2020-07-29T18:45:00.000Z'))&_a=(explorer:(mlExplorerFilter:(),mlExplorerSwimlane:()))"` ); }); }); diff --git a/x-pack/plugins/apm/public/components/shared/links/machine_learning_links/mlexplorer_link.tsx b/x-pack/plugins/apm/public/components/shared/links/machine_learning_links/mlexplorer_link.tsx index 0990a961c0d4b..48bdfc69150ad 100644 --- a/x-pack/plugins/apm/public/components/shared/links/machine_learning_links/mlexplorer_link.tsx +++ b/x-pack/plugins/apm/public/components/shared/links/machine_learning_links/mlexplorer_link.tsx @@ -10,6 +10,7 @@ import { EuiLink } from '@elastic/eui'; import { useMlHref, ML_PAGES } from '@kbn/ml-plugin/public'; import { useApmPluginContext } from '../../../../context/apm_plugin/use_apm_plugin_context'; import { useLegacyUrlParams } from '../../../../context/url_params_context/use_url_params'; +import { DEFAULT_REFRESH_INTERVAL } from '../../date_picker/apm_date_picker'; interface Props { children?: ReactNode; @@ -48,7 +49,7 @@ export function useExplorerHref({ jobId }: { jobId: string }) { pageState: { jobIds: [jobId], timeRange: { from: rangeFrom, to: rangeTo }, - refreshInterval: { pause: true, value: 10000 }, + refreshInterval: { pause: true, value: DEFAULT_REFRESH_INTERVAL }, }, }); diff --git a/x-pack/plugins/apm/public/components/shared/links/machine_learning_links/mlsingle_metric_link.test.tsx b/x-pack/plugins/apm/public/components/shared/links/machine_learning_links/mlsingle_metric_link.test.tsx index eb6ae275563a3..bb6f5c524e7ac 100644 --- a/x-pack/plugins/apm/public/components/shared/links/machine_learning_links/mlsingle_metric_link.test.tsx +++ b/x-pack/plugins/apm/public/components/shared/links/machine_learning_links/mlsingle_metric_link.test.tsx @@ -23,7 +23,7 @@ describe('MLSingleMetricLink', () => { ); expect(href).toMatchInlineSnapshot( - `"/app/ml/timeseriesexplorer?_g=(ml:(jobIds:!(myservicename-mytransactiontype-high_mean_response_time)),refreshInterval:(pause:!t,value:10000),time:(from:now%2Fw,to:now-4h))&_a=(timeseriesexplorer:(mlTimeSeriesExplorer:()))"` + `"/app/ml/timeseriesexplorer?_g=(ml:(jobIds:!(myservicename-mytransactiontype-high_mean_response_time)),refreshInterval:(pause:!t,value:60000),time:(from:now%2Fw,to:now-4h))&_a=(timeseriesexplorer:(mlTimeSeriesExplorer:()))"` ); }); it('should produce the correct URL with jobId, serviceName, and transactionType', async () => { @@ -42,7 +42,7 @@ describe('MLSingleMetricLink', () => { ); expect(href).toMatchInlineSnapshot( - `"/app/ml/timeseriesexplorer?_g=(ml:(jobIds:!(myservicename-mytransactiontype-high_mean_response_time)),refreshInterval:(pause:!t,value:10000),time:(from:now%2Fw,to:now-4h))&_a=(timeseriesexplorer:(mlTimeSeriesExplorer:(entities:(service.name:opbeans-test,transaction.type:request))))"` + `"/app/ml/timeseriesexplorer?_g=(ml:(jobIds:!(myservicename-mytransactiontype-high_mean_response_time)),refreshInterval:(pause:!t,value:60000),time:(from:now%2Fw,to:now-4h))&_a=(timeseriesexplorer:(mlTimeSeriesExplorer:(entities:(service.name:opbeans-test,transaction.type:request))))"` ); }); @@ -57,12 +57,12 @@ describe('MLSingleMetricLink', () => { ), { search: - '?rangeFrom=2020-07-29T17:27:29.000Z&rangeTo=2020-07-29T18:45:00.000Z&refreshInterval=10000&refreshPaused=true', + '?rangeFrom=2020-07-29T17:27:29.000Z&rangeTo=2020-07-29T18:45:00.000Z&refreshInterval=60000&refreshPaused=true', } as Location ); expect(href).toMatchInlineSnapshot( - `"/app/ml/timeseriesexplorer?_g=(ml:(jobIds:!(apm-production-485b-high_mean_transaction_duration)),refreshInterval:(pause:!t,value:10000),time:(from:'2020-07-29T17:27:29.000Z',to:'2020-07-29T18:45:00.000Z'))&_a=(timeseriesexplorer:(mlTimeSeriesExplorer:(entities:(service.name:opbeans-java,transaction.type:request))))"` + `"/app/ml/timeseriesexplorer?_g=(ml:(jobIds:!(apm-production-485b-high_mean_transaction_duration)),refreshInterval:(pause:!t,value:60000),time:(from:'2020-07-29T17:27:29.000Z',to:'2020-07-29T18:45:00.000Z'))&_a=(timeseriesexplorer:(mlTimeSeriesExplorer:(entities:(service.name:opbeans-java,transaction.type:request))))"` ); }); }); diff --git a/x-pack/plugins/apm/public/components/shared/links/machine_learning_links/mlsingle_metric_link.tsx b/x-pack/plugins/apm/public/components/shared/links/machine_learning_links/mlsingle_metric_link.tsx index 7c4232866157b..ff8b350ac0454 100644 --- a/x-pack/plugins/apm/public/components/shared/links/machine_learning_links/mlsingle_metric_link.tsx +++ b/x-pack/plugins/apm/public/components/shared/links/machine_learning_links/mlsingle_metric_link.tsx @@ -10,6 +10,7 @@ import { EuiLink } from '@elastic/eui'; import { useMlHref, ML_PAGES } from '@kbn/ml-plugin/public'; import { useApmPluginContext } from '../../../../context/apm_plugin/use_apm_plugin_context'; import { useLegacyUrlParams } from '../../../../context/url_params_context/use_url_params'; +import { DEFAULT_REFRESH_INTERVAL } from '../../date_picker/apm_date_picker'; interface Props { children?: ReactNode; @@ -74,7 +75,7 @@ function useSingleMetricHref({ pageState: { jobIds: [jobId], timeRange: { from: rangeFrom, to: rangeTo }, - refreshInterval: { pause: true, value: 10000 }, + refreshInterval: { pause: true, value: DEFAULT_REFRESH_INTERVAL }, ...entities, }, }); diff --git a/x-pack/plugins/apm/public/components/shared/span_icon/get_span_icon.ts b/x-pack/plugins/apm/public/components/shared/span_icon/get_span_icon.ts index f9d74fe1bc956..96b1cd45fbdce 100644 --- a/x-pack/plugins/apm/public/components/shared/span_icon/get_span_icon.ts +++ b/x-pack/plugins/apm/public/components/shared/span_icon/get_span_icon.ts @@ -7,7 +7,6 @@ import { maybe } from '../../../../common/utils/maybe'; import awsIcon from './icons/aws.svg'; -import azureIcon from './icons/azure.svg'; import cassandraIcon from './icons/cassandra.svg'; import databaseIcon from './icons/database.svg'; import defaultIcon from './icons/default.svg'; @@ -24,6 +23,16 @@ import postgresqlIcon from './icons/postgresql.svg'; import redisIcon from './icons/redis.svg'; import websocketIcon from './icons/websocket.svg'; import javaIcon from '../agent_icon/icons/java.svg'; +import dynamodbIcon from './icons/dynamo_db.svg'; +import sThreeIcon from './icons/s3.svg'; +import snsIcon from './icons/sns.svg'; +import sqsIcon from './icons/sqs.svg'; +import cosmosDbIcon from './icons/cosmos_db.svg'; +import blobStorageIcon from './icons/blob_storage.svg'; +import fileShareStorageIcon from './icons/file_share_storage.svg'; +import serviceBusIcon from './icons/service_bus.svg'; +import storageQueueIcon from './icons/storage_queue.svg'; +import tableStorageIcon from './icons/table_storage.svg'; const defaultSpanTypeIcons: { [key: string]: string } = { cache: databaseIcon, @@ -43,8 +52,8 @@ export const spanTypeIcons: { cache: { redis: redisIcon }, db: { cassandra: cassandraIcon, - cosmosdb: azureIcon, - dynamodb: awsIcon, + cosmosdb: cosmosDbIcon, + dynamodb: dynamodbIcon, elasticsearch: elasticsearchIcon, mongodb: mongodbIcon, mysql: mysqlIcon, @@ -57,18 +66,18 @@ export const spanTypeIcons: { websocket: websocketIcon, }, messaging: { - azurequeue: azureIcon, - azureservicebus: azureIcon, + azurequeue: storageQueueIcon, + azureservicebus: serviceBusIcon, jms: javaIcon, kafka: kafkaIcon, - sns: awsIcon, - sqs: awsIcon, + sns: snsIcon, + sqs: sqsIcon, }, storage: { - azureblob: azureIcon, - azurefile: azureIcon, - azuretable: azureIcon, - s3: awsIcon, + azureblob: blobStorageIcon, + azurefile: fileShareStorageIcon, + azuretable: tableStorageIcon, + s3: sThreeIcon, }, template: { handlebars: handlebarsIcon, diff --git a/x-pack/plugins/apm/public/components/shared/span_icon/icons/blob_storage.svg b/x-pack/plugins/apm/public/components/shared/span_icon/icons/blob_storage.svg new file mode 100644 index 0000000000000..10806e4b75d81 --- /dev/null +++ b/x-pack/plugins/apm/public/components/shared/span_icon/icons/blob_storage.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/x-pack/plugins/apm/public/components/shared/span_icon/icons/cosmos_db.svg b/x-pack/plugins/apm/public/components/shared/span_icon/icons/cosmos_db.svg new file mode 100644 index 0000000000000..26205c2292a1f --- /dev/null +++ b/x-pack/plugins/apm/public/components/shared/span_icon/icons/cosmos_db.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/x-pack/plugins/apm/public/components/shared/span_icon/icons/dynamo_db.svg b/x-pack/plugins/apm/public/components/shared/span_icon/icons/dynamo_db.svg new file mode 100644 index 0000000000000..a8f80e39c6ca3 --- /dev/null +++ b/x-pack/plugins/apm/public/components/shared/span_icon/icons/dynamo_db.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/x-pack/plugins/apm/public/components/shared/span_icon/icons/file_share_storage.svg b/x-pack/plugins/apm/public/components/shared/span_icon/icons/file_share_storage.svg new file mode 100644 index 0000000000000..9c8b135e945f3 --- /dev/null +++ b/x-pack/plugins/apm/public/components/shared/span_icon/icons/file_share_storage.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/x-pack/plugins/apm/public/components/shared/span_icon/icons/s3.svg b/x-pack/plugins/apm/public/components/shared/span_icon/icons/s3.svg new file mode 100644 index 0000000000000..1dfa8fccf7765 --- /dev/null +++ b/x-pack/plugins/apm/public/components/shared/span_icon/icons/s3.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/x-pack/plugins/apm/public/components/shared/span_icon/icons/service_bus.svg b/x-pack/plugins/apm/public/components/shared/span_icon/icons/service_bus.svg new file mode 100644 index 0000000000000..76fc82312752f --- /dev/null +++ b/x-pack/plugins/apm/public/components/shared/span_icon/icons/service_bus.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/x-pack/plugins/apm/public/components/shared/span_icon/icons/sns.svg b/x-pack/plugins/apm/public/components/shared/span_icon/icons/sns.svg new file mode 100644 index 0000000000000..f668c7019baa0 --- /dev/null +++ b/x-pack/plugins/apm/public/components/shared/span_icon/icons/sns.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/x-pack/plugins/apm/public/components/shared/span_icon/icons/sqs.svg b/x-pack/plugins/apm/public/components/shared/span_icon/icons/sqs.svg new file mode 100644 index 0000000000000..21fe40a46c9c2 --- /dev/null +++ b/x-pack/plugins/apm/public/components/shared/span_icon/icons/sqs.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/x-pack/plugins/apm/public/components/shared/span_icon/icons/storage_queue.svg b/x-pack/plugins/apm/public/components/shared/span_icon/icons/storage_queue.svg new file mode 100644 index 0000000000000..3b540975b17d1 --- /dev/null +++ b/x-pack/plugins/apm/public/components/shared/span_icon/icons/storage_queue.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/x-pack/plugins/apm/public/components/shared/span_icon/icons/table_storage.svg b/x-pack/plugins/apm/public/components/shared/span_icon/icons/table_storage.svg new file mode 100644 index 0000000000000..9c3ba79e0371e --- /dev/null +++ b/x-pack/plugins/apm/public/components/shared/span_icon/icons/table_storage.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/x-pack/plugins/apm/public/context/apm_service/apm_service_context.tsx b/x-pack/plugins/apm/public/context/apm_service/apm_service_context.tsx index afbad8543059a..ce74feab48102 100644 --- a/x-pack/plugins/apm/public/context/apm_service/apm_service_context.tsx +++ b/x-pack/plugins/apm/public/context/apm_service/apm_service_context.tsx @@ -69,7 +69,7 @@ export function ApmServiceContextProvider({ end, }); - const transactionType = getOrRedirectToTransactionType({ + const currentTransactionType = getOrRedirectToTransactionType({ transactionType: query.transactionType, transactionTypes, agentName, @@ -85,7 +85,7 @@ export function ApmServiceContextProvider({ value={{ serviceName, agentName, - transactionType, + transactionType: currentTransactionType, transactionTypes, runtimeName, fallbackToTransactions, @@ -96,24 +96,44 @@ export function ApmServiceContextProvider({ ); } -export function getOrRedirectToTransactionType({ +const isTypeExistsInTransactionTypesList = ({ + transactionType, + transactionTypes, +}: { + transactionType?: string; + transactionTypes: string[]; +}): boolean => !!transactionType && transactionTypes.includes(transactionType); + +const isNoAgentAndNoTransactionTypes = ({ + transactionTypes, + agentName, +}: { + transactionTypes: string[]; + agentName?: string; +}): boolean => !agentName || transactionTypes.length === 0; + +export function getTransactionType({ transactionType, transactionTypes, agentName, - history, }: { transactionType?: string; transactionTypes: string[]; agentName?: string; - history: History; -}) { - if (transactionType && transactionTypes.includes(transactionType)) { - return transactionType; - } +}): string | undefined { + const isTransactionTypeExists = isTypeExistsInTransactionTypesList({ + transactionType, + transactionTypes, + }); - if (!agentName || transactionTypes.length === 0) { - return; - } + if (isTransactionTypeExists) return transactionType; + + const isNoAgentAndNoTransactionTypesExists = isNoAgentAndNoTransactionTypes({ + transactionTypes, + agentName, + }); + + if (isNoAgentAndNoTransactionTypesExists) return undefined; // The default transaction type is "page-load" for RUM agents and "request" for all others const defaultTransactionType = isRumAgentName(agentName) @@ -127,7 +147,42 @@ export function getOrRedirectToTransactionType({ ? defaultTransactionType : transactionTypes[0]; + return currentTransactionType; +} + +export function getOrRedirectToTransactionType({ + transactionType, + transactionTypes, + agentName, + history, +}: { + transactionType?: string; + transactionTypes: string[]; + agentName?: string; + history: History; +}) { + const isTransactionTypeExists = isTypeExistsInTransactionTypesList({ + transactionType, + transactionTypes, + }); + + if (isTransactionTypeExists) return transactionType; + + const isNoAgentAndNoTransactionTypesExists = isNoAgentAndNoTransactionTypes({ + transactionTypes, + agentName, + }); + + if (isNoAgentAndNoTransactionTypesExists) return undefined; + + const currentTransactionType = getTransactionType({ + transactionTypes, + transactionType, + agentName, + }); + // Replace transactionType in the URL in case it is not one of the types returned by the API - replace(history, { query: { transactionType: currentTransactionType } }); + replace(history, { query: { transactionType: currentTransactionType! } }); + return currentTransactionType; } diff --git a/x-pack/plugins/apm/server/index.ts b/x-pack/plugins/apm/server/index.ts index 17682706571cc..19b34766a1bf2 100644 --- a/x-pack/plugins/apm/server/index.ts +++ b/x-pack/plugins/apm/server/index.ts @@ -20,10 +20,10 @@ const configSchema = schema.object({ autoCreateApmDataView: schema.boolean({ defaultValue: true }), serviceMapEnabled: schema.boolean({ defaultValue: true }), serviceMapFingerprintBucketSize: schema.number({ defaultValue: 100 }), - serviceMapTraceIdBucketSize: schema.number({ defaultValue: 65 }), serviceMapFingerprintGlobalBucketSize: schema.number({ defaultValue: 1000, }), + serviceMapTraceIdBucketSize: schema.number({ defaultValue: 65 }), serviceMapTraceIdGlobalBucketSize: schema.number({ defaultValue: 6 }), serviceMapMaxTracesPerRequest: schema.number({ defaultValue: 50 }), ui: schema.object({ diff --git a/x-pack/plugins/apm/server/routes/fleet/merge_package_policy_with_apm.ts b/x-pack/plugins/apm/server/routes/fleet/merge_package_policy_with_apm.ts index 37f0705904770..1a3fcc6cd1967 100644 --- a/x-pack/plugins/apm/server/routes/fleet/merge_package_policy_with_apm.ts +++ b/x-pack/plugins/apm/server/routes/fleet/merge_package_policy_with_apm.ts @@ -12,7 +12,10 @@ import { getPackagePolicyWithAgentConfigurations, PackagePolicy, } from './register_fleet_policy_callbacks'; -import { getPackagePolicyWithSourceMap, listArtifacts } from './source_maps'; +import { + getPackagePolicyWithSourceMap, + listSourceMapArtifacts, +} from './source_maps'; export async function mergePackagePolicyWithApm({ packagePolicy, @@ -24,7 +27,7 @@ export async function mergePackagePolicyWithApm({ fleetPluginStart: NonNullable; }) { const agentConfigurations = await listConfigurations(internalESClient); - const artifacts = await listArtifacts({ fleetPluginStart }); + const { artifacts } = await listSourceMapArtifacts({ fleetPluginStart }); return getPackagePolicyWithAgentConfigurations( getPackagePolicyWithSourceMap({ packagePolicy, artifacts }), agentConfigurations diff --git a/x-pack/plugins/apm/server/routes/fleet/source_maps.ts b/x-pack/plugins/apm/server/routes/fleet/source_maps.ts index 6000b79956665..9cba744cdb689 100644 --- a/x-pack/plugins/apm/server/routes/fleet/source_maps.ts +++ b/x-pack/plugins/apm/server/routes/fleet/source_maps.ts @@ -32,37 +32,44 @@ export type FleetPluginStart = NonNullable; const doUnzip = promisify(unzip); -function decodeArtifacts(artifacts: Artifact[]): Promise { - return Promise.all( - artifacts.map(async (artifact) => { - const body = await doUnzip(Buffer.from(artifact.body, 'base64')); - return { - ...artifact, - body: JSON.parse(body.toString()) as ApmArtifactBody, - }; - }) - ); +async function unzipArtifactBody( + artifact: Artifact +): Promise { + const body = await doUnzip(Buffer.from(artifact.body, 'base64')); + + return { + ...artifact, + body: JSON.parse(body.toString()) as ApmArtifactBody, + }; } function getApmArtifactClient(fleetPluginStart: FleetPluginStart) { return fleetPluginStart.createArtifactsClient('apm'); } -export async function listArtifacts({ +export async function listSourceMapArtifacts({ fleetPluginStart, + perPage = 20, + page = 1, }: { fleetPluginStart: FleetPluginStart; + perPage?: number; + page?: number; }) { const apmArtifactClient = getApmArtifactClient(fleetPluginStart); - const fleetArtifactsResponse = await apmArtifactClient.listArtifacts({ + const artifactsResponse = await apmArtifactClient.listArtifacts({ kuery: 'type: sourcemap', - perPage: 20, - page: 1, + perPage, + page, sortOrder: 'desc', sortField: 'created', }); - return decodeArtifacts(fleetArtifactsResponse.items); + const artifacts = await Promise.all( + artifactsResponse.items.map(unzipArtifactBody) + ); + + return { artifacts, total: artifactsResponse.total }; } export async function createApmArtifact({ @@ -141,8 +148,7 @@ export async function updateSourceMapsOnFleetPolicies({ savedObjectsClient: SavedObjectsClientContract; elasticsearchClient: ElasticsearchClient; }) { - const artifacts = await listArtifacts({ fleetPluginStart }); - + const { artifacts } = await listSourceMapArtifacts({ fleetPluginStart }); const apmFleetPolicies = await getApmPackagePolicies({ core, fleetPluginStart, diff --git a/x-pack/plugins/apm/server/routes/service_map/get_service_map.ts b/x-pack/plugins/apm/server/routes/service_map/get_service_map.ts index 35c422c53156e..fb1d0eed0a151 100644 --- a/x-pack/plugins/apm/server/routes/service_map/get_service_map.ts +++ b/x-pack/plugins/apm/server/routes/service_map/get_service_map.ts @@ -7,14 +7,7 @@ import { Logger } from '@kbn/core/server'; import { chunk } from 'lodash'; -import { rangeQuery, termsQuery } from '@kbn/observability-plugin/server'; -import { ProcessorEvent } from '@kbn/observability-plugin/common'; -import { - AGENT_NAME, - SERVICE_ENVIRONMENT, - SERVICE_NAME, -} from '../../../common/es_fields/apm'; -import { environmentQuery } from '../../../common/utils/environment_query'; + import { withApmSpan } from '../../utils/with_apm_span'; import { MlClient } from '../../lib/helpers/get_ml_client'; import { @@ -24,44 +17,41 @@ import { import { getServiceMapFromTraceIds } from './get_service_map_from_trace_ids'; import { getTraceSampleIds } from './get_trace_sample_ids'; import { transformServiceMapResponses } from './transform_service_map_responses'; -import { ENVIRONMENT_ALL } from '../../../common/environment_filter_values'; -import { getProcessorEventForTransactions } from '../../lib/helpers/transactions'; -import { ServiceGroup } from '../../../common/service_groups'; -import { serviceGroupQuery } from '../../lib/service_group_query'; import { APMEventClient } from '../../lib/helpers/create_es_client/create_apm_event_client'; import { APMConfig } from '../..'; +import { getServiceStats } from './get_service_stats'; export interface IEnvOptions { mlClient?: MlClient; config: APMConfig; apmEventClient: APMEventClient; - serviceNames?: string[]; + serviceName?: string; environment: string; searchAggregatedTransactions: boolean; logger: Logger; start: number; end: number; - serviceGroup: ServiceGroup | null; + serviceGroupKuery?: string; } async function getConnectionData({ config, apmEventClient, - serviceNames, + serviceName, environment, start, end, - serviceGroup, + serviceGroupKuery, }: IEnvOptions) { return withApmSpan('get_service_map_connections', async () => { const { traceIds } = await getTraceSampleIds({ config, apmEventClient, - serviceNames, + serviceName, environment, start, end, - serviceGroup, + serviceGroupKuery, }); const chunks = chunk(traceIds, config.serviceMapMaxTracesPerRequest); @@ -101,79 +91,8 @@ async function getConnectionData({ }); } -async function getServicesData( - options: IEnvOptions & { maxNumberOfServices: number } -) { - const { - environment, - apmEventClient, - searchAggregatedTransactions, - start, - end, - maxNumberOfServices, - serviceGroup, - } = options; - const params = { - apm: { - events: [ - getProcessorEventForTransactions(searchAggregatedTransactions), - ProcessorEvent.metric as const, - ProcessorEvent.error as const, - ], - }, - body: { - track_total_hits: false, - size: 0, - query: { - bool: { - filter: [ - ...rangeQuery(start, end), - ...environmentQuery(environment), - ...termsQuery(SERVICE_NAME, ...(options.serviceNames ?? [])), - ...serviceGroupQuery(serviceGroup), - ], - }, - }, - aggs: { - services: { - terms: { - field: SERVICE_NAME, - size: maxNumberOfServices, - }, - aggs: { - agent_name: { - terms: { - field: AGENT_NAME, - }, - }, - }, - }, - }, - }, - }; - - const response = await apmEventClient.search( - 'get_service_stats_for_service_map', - params - ); - - return ( - response.aggregations?.services.buckets.map((bucket) => { - return { - [SERVICE_NAME]: bucket.key as string, - [AGENT_NAME]: - (bucket.agent_name.buckets[0]?.key as string | undefined) || '', - [SERVICE_ENVIRONMENT]: - options.environment === ENVIRONMENT_ALL.value - ? null - : options.environment, - }; - }) || [] - ); -} - export type ConnectionsResponse = Awaited>; -export type ServicesResponse = Awaited>; +export type ServicesResponse = Awaited>; export function getServiceMap( options: IEnvOptions & { maxNumberOfServices: number } @@ -192,7 +111,7 @@ export function getServiceMap( const [connectionData, servicesData, anomalies] = await Promise.all([ getConnectionData(options), - getServicesData(options), + getServiceStats(options), anomaliesPromise, ]); diff --git a/x-pack/plugins/apm/server/routes/service_map/get_service_stats.ts b/x-pack/plugins/apm/server/routes/service_map/get_service_stats.ts new file mode 100644 index 0000000000000..1f43a35d3b1ef --- /dev/null +++ b/x-pack/plugins/apm/server/routes/service_map/get_service_stats.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 { + kqlQuery, + rangeQuery, + termsQuery, +} from '@kbn/observability-plugin/server'; +import { ProcessorEvent } from '@kbn/observability-plugin/common'; +import { + AGENT_NAME, + SERVICE_ENVIRONMENT, + SERVICE_NAME, +} from '../../../common/es_fields/apm'; +import { environmentQuery } from '../../../common/utils/environment_query'; +import { ENVIRONMENT_ALL } from '../../../common/environment_filter_values'; +import { getProcessorEventForTransactions } from '../../lib/helpers/transactions'; +import { IEnvOptions } from './get_service_map'; + +export async function getServiceStats({ + environment, + apmEventClient, + searchAggregatedTransactions, + start, + end, + maxNumberOfServices, + serviceGroupKuery, + serviceName, +}: IEnvOptions & { maxNumberOfServices: number }) { + const params = { + apm: { + events: [ + getProcessorEventForTransactions(searchAggregatedTransactions), + ProcessorEvent.metric as const, + ProcessorEvent.error as const, + ], + }, + body: { + track_total_hits: false, + size: 0, + query: { + bool: { + filter: [ + ...rangeQuery(start, end), + ...environmentQuery(environment), + ...termsQuery(SERVICE_NAME, serviceName), + ...kqlQuery(serviceGroupKuery), + ], + }, + }, + aggs: { + services: { + terms: { + field: SERVICE_NAME, + size: maxNumberOfServices, + }, + aggs: { + agent_name: { + terms: { + field: AGENT_NAME, + }, + }, + }, + }, + }, + }, + }; + + const response = await apmEventClient.search( + 'get_service_stats_for_service_map', + params + ); + + return ( + response.aggregations?.services.buckets.map((bucket) => { + return { + [SERVICE_NAME]: bucket.key as string, + [AGENT_NAME]: + (bucket.agent_name.buckets[0]?.key as string | undefined) || '', + [SERVICE_ENVIRONMENT]: + environment === ENVIRONMENT_ALL.value ? null : environment, + }; + }) || [] + ); +} diff --git a/x-pack/plugins/apm/server/routes/service_map/get_trace_sample_ids.ts b/x-pack/plugins/apm/server/routes/service_map/get_trace_sample_ids.ts index d65e97c6988e5..42935dbdcda88 100644 --- a/x-pack/plugins/apm/server/routes/service_map/get_trace_sample_ids.ts +++ b/x-pack/plugins/apm/server/routes/service_map/get_trace_sample_ids.ts @@ -7,7 +7,11 @@ import Boom from '@hapi/boom'; import { sortBy, take, uniq } from 'lodash'; -import { rangeQuery } from '@kbn/observability-plugin/server'; +import { + kqlQuery, + rangeQuery, + termQuery, +} from '@kbn/observability-plugin/server'; import { ProcessorEvent } from '@kbn/observability-plugin/common'; import { asMutableArray } from '../../../common/utils/as_mutable_array'; import { @@ -18,62 +22,59 @@ import { } from '../../../common/es_fields/apm'; import { SERVICE_MAP_TIMEOUT_ERROR } from '../../../common/service_map'; import { environmentQuery } from '../../../common/utils/environment_query'; -import { serviceGroupQuery } from '../../lib/service_group_query'; -import { ServiceGroup } from '../../../common/service_groups'; + import { APMEventClient } from '../../lib/helpers/create_es_client/create_apm_event_client'; import { APMConfig } from '../..'; const MAX_TRACES_TO_INSPECT = 1000; export async function getTraceSampleIds({ - serviceNames, + serviceName, environment, config, apmEventClient, start, end, - serviceGroup, + serviceGroupKuery, }: { - serviceNames?: string[]; + serviceName?: string; environment: string; config: APMConfig; apmEventClient: APMEventClient; start: number; end: number; - serviceGroup: ServiceGroup | null; + serviceGroupKuery?: string; }) { const query = { bool: { - filter: [...rangeQuery(start, end), ...serviceGroupQuery(serviceGroup)], + filter: [ + ...rangeQuery(start, end), + ...environmentQuery(environment), + ...kqlQuery(serviceGroupKuery), + ...termQuery(SERVICE_NAME, serviceName), + ], }, }; - let events: ProcessorEvent[]; + const isGlobalServiceMap = !serviceName && !serviceGroupKuery; + let events = [ProcessorEvent.span, ProcessorEvent.transaction]; - const hasServiceNamesFilter = (serviceNames?.length ?? 0) > 0; - - if (hasServiceNamesFilter) { - query.bool.filter.push({ - terms: { [SERVICE_NAME]: serviceNames as string[] }, - }); - events = [ProcessorEvent.span, ProcessorEvent.transaction]; - } else { + // perf optimization that is only possible on the global service map with no filters + if (isGlobalServiceMap) { events = [ProcessorEvent.span]; query.bool.filter.push({ - exists: { - field: SPAN_DESTINATION_SERVICE_RESOURCE, - }, + exists: { field: SPAN_DESTINATION_SERVICE_RESOURCE }, }); } - query.bool.filter.push(...environmentQuery(environment)); + const fingerprintBucketSize = isGlobalServiceMap + ? config.serviceMapFingerprintGlobalBucketSize + : config.serviceMapFingerprintBucketSize; + + const traceIdBucketSize = isGlobalServiceMap + ? config.serviceMapTraceIdGlobalBucketSize + : config.serviceMapTraceIdBucketSize; - const fingerprintBucketSize = hasServiceNamesFilter - ? config.serviceMapFingerprintBucketSize - : config.serviceMapFingerprintGlobalBucketSize; - const traceIdBucketSize = hasServiceNamesFilter - ? config.serviceMapTraceIdBucketSize - : config.serviceMapTraceIdGlobalBucketSize; const samplerShardSize = traceIdBucketSize * 10; const params = { diff --git a/x-pack/plugins/apm/server/routes/service_map/route.ts b/x-pack/plugins/apm/server/routes/service_map/route.ts index 1cf4dd40afbcf..69f4422ad337a 100644 --- a/x-pack/plugins/apm/server/routes/service_map/route.ts +++ b/x-pack/plugins/apm/server/routes/service_map/route.ts @@ -7,7 +7,6 @@ import Boom from '@hapi/boom'; import * as t from 'io-ts'; -import { compact } from 'lodash'; import { apmServiceGroupMaxNumberOfServices } from '@kbn/observability-plugin/common'; import { isActivePlatinumLicense } from '../../../common/license_check'; import { invalidLicenseMessage } from '../../../common/service_map'; @@ -129,8 +128,6 @@ const serviceMapRoute = createApmServerRoute({ uiSettingsClient.get(apmServiceGroupMaxNumberOfServices), ]); - const serviceNames = compact([serviceName]); - const searchAggregatedTransactions = await getSearchTransactionsEvents({ apmEventClient, config, @@ -142,14 +139,14 @@ const serviceMapRoute = createApmServerRoute({ mlClient, config, apmEventClient, - serviceNames, + serviceName, environment, searchAggregatedTransactions, logger, start, end, maxNumberOfServices, - serviceGroup, + serviceGroupKuery: serviceGroup?.kuery, }); }, }); diff --git a/x-pack/plugins/apm/server/routes/source_maps/route.ts b/x-pack/plugins/apm/server/routes/source_maps/route.ts index 738192377beb0..b4d005373c4be 100644 --- a/x-pack/plugins/apm/server/routes/source_maps/route.ts +++ b/x-pack/plugins/apm/server/routes/source_maps/route.ts @@ -7,12 +7,12 @@ import Boom from '@hapi/boom'; import * as t from 'io-ts'; import { SavedObjectsClientContract } from '@kbn/core/server'; -import { jsonRt } from '@kbn/io-ts-utils'; +import { jsonRt, toNumberRt } from '@kbn/io-ts-utils'; import { Artifact } from '@kbn/fleet-plugin/server'; import { createApmArtifact, deleteApmArtifact, - listArtifacts, + listSourceMapArtifacts, updateSourceMapsOnFleetPolicies, getCleanedBundleFilePath, ArtifactSourceMap, @@ -40,14 +40,28 @@ export type SourceMap = t.TypeOf; const listSourceMapRoute = createApmServerRoute({ endpoint: 'GET /api/apm/sourcemaps', options: { tags: ['access:apm'] }, + params: t.partial({ + query: t.partial({ + page: toNumberRt, + perPage: toNumberRt, + }), + }), async handler({ + params, plugins, - }): Promise<{ artifacts: ArtifactSourceMap[] } | undefined> { + }): Promise<{ artifacts: ArtifactSourceMap[]; total: number } | undefined> { + const { page, perPage } = params.query; + try { const fleetPluginStart = await plugins.fleet?.start(); if (fleetPluginStart) { - const artifacts = await listArtifacts({ fleetPluginStart }); - return { artifacts }; + const { artifacts, total } = await listSourceMapArtifacts({ + fleetPluginStart, + page, + perPage, + }); + + return { artifacts, total }; } } catch (e) { throw Boom.internal( diff --git a/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/editor.tsx b/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/editor.tsx index c96024658048c..1a09116ba1196 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/editor.tsx +++ b/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/editor.tsx @@ -52,7 +52,7 @@ const EditorArg: FC = ({ argValue, typeInstance, onValueChange, const { language } = typeInstance?.options ?? {}; return ( - + { return ( -
    +
    diff --git a/x-pack/plugins/cases/public/components/add_comment/schema.tsx b/x-pack/plugins/cases/public/components/add_comment/schema.tsx index 5df5769ef62ab..980a03e76b772 100644 --- a/x-pack/plugins/cases/public/components/add_comment/schema.tsx +++ b/x-pack/plugins/cases/public/components/add_comment/schema.tsx @@ -9,6 +9,7 @@ import type { FormSchema } from '@kbn/es-ui-shared-plugin/static/forms/hook_form import { FIELD_TYPES } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; import { fieldValidators } from '@kbn/es-ui-shared-plugin/static/forms/helpers'; import type { CommentRequestUserType } from '../../../common/api'; + import * as i18n from './translations'; const { emptyField } = fieldValidators; @@ -22,7 +23,7 @@ export const schema: FormSchema = { type: FIELD_TYPES.TEXTAREA, validations: [ { - validator: emptyField(i18n.COMMENT_REQUIRED), + validator: emptyField(i18n.EMPTY_COMMENTS_NOT_ALLOWED), }, ], }, diff --git a/x-pack/plugins/cases/public/components/all_cases/selector_modal/use_cases_add_to_existing_case_modal.test.tsx b/x-pack/plugins/cases/public/components/all_cases/selector_modal/use_cases_add_to_existing_case_modal.test.tsx index d14787fee4a53..cc164b2396f60 100644 --- a/x-pack/plugins/cases/public/components/all_cases/selector_modal/use_cases_add_to_existing_case_modal.test.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/selector_modal/use_cases_add_to_existing_case_modal.test.tsx @@ -83,6 +83,7 @@ describe('use cases add to existing case modal hook', () => { const defaultParams = () => { return { onRowClick: jest.fn() }; }; + beforeEach(() => { appMockRender = createAppMockRenderer(); dispatch.mockReset(); @@ -166,7 +167,7 @@ describe('use cases add to existing case modal hook', () => { expect(mockedToastSuccess).toHaveBeenCalled(); }); - it('should not call createAttachments nor show toast success when a case is not selected', async () => { + it('should not call createAttachments nor show toast success when a case is not selected', async () => { const mockBulkCreateAttachments = jest.fn(); useCreateAttachmentsMock.mockReturnValueOnce({ createAttachments: mockBulkCreateAttachments, @@ -178,11 +179,11 @@ describe('use cases add to existing case modal hook', () => { }); AllCasesSelectorModalMock.mockImplementation(({ onRowClick }) => { - onRowClick(); return null; }); const result = appMockRender.render(); + userEvent.click(result.getByTestId('open-modal')); // give a small delay for the reducer to run diff --git a/x-pack/plugins/cases/public/components/all_cases/selector_modal/use_cases_add_to_existing_case_modal.tsx b/x-pack/plugins/cases/public/components/all_cases/selector_modal/use_cases_add_to_existing_case_modal.tsx index 2936ebf56d1e3..057973f82e0d2 100644 --- a/x-pack/plugins/cases/public/components/all_cases/selector_modal/use_cases_add_to_existing_case_modal.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/selector_modal/use_cases_add_to_existing_case_modal.tsx @@ -123,6 +123,7 @@ export const useCasesAddToExistingCaseModal = (props: AddToExistingFlyoutProps = }, [closeModal, dispatch, handleOnRowClick, props] ); + return { open: openModal, close: closeModal, diff --git a/x-pack/plugins/cases/public/components/all_cases/use_all_cases_query_params.tsx b/x-pack/plugins/cases/public/components/all_cases/use_all_cases_query_params.tsx index 9a094d3f45d55..d2c03d5e6ddab 100644 --- a/x-pack/plugins/cases/public/components/all_cases/use_all_cases_query_params.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/use_all_cases_query_params.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import { useCallback, useRef, useState } from 'react'; +import { useCallback, useRef, useState, useEffect } from 'react'; import { useLocation, useHistory } from 'react-router-dom'; import { isEqual } from 'lodash'; @@ -121,10 +121,12 @@ export function useAllCasesQueryParams(isModalView: boolean = false) { ] ); - if (isFirstRenderRef.current) { - persistAndUpdateQueryParams(isModalView ? DEFAULT_QUERY_PARAMS : {}); - isFirstRenderRef.current = false; - } + useEffect(() => { + if (isFirstRenderRef.current) { + persistAndUpdateQueryParams(isModalView ? DEFAULT_QUERY_PARAMS : {}); + isFirstRenderRef.current = false; + } + }, [isModalView, persistAndUpdateQueryParams]); return { queryParams, diff --git a/x-pack/plugins/cases/public/components/all_cases/use_cases_columns.tsx b/x-pack/plugins/cases/public/components/all_cases/use_cases_columns.tsx index cb08bf4b6e526..df261b613b0b2 100644 --- a/x-pack/plugins/cases/public/components/all_cases/use_cases_columns.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/use_cases_columns.tsx @@ -65,8 +65,11 @@ const LineClampedEuiBadgeGroup = euiStyled(EuiBadgeGroup)` word-break: normal; `; +// margin-right is required here because -webkit-box-orient: vertical; +// in the EuiBadgeGroup prevents us from defining gutterSize. const StyledEuiBadge = euiStyled(EuiBadge)` - max-width: 100px + max-width: 100px; + margin-right: 5px; `; // to allow for ellipsis const renderStringField = (field: string, dataTestSubj: string) => diff --git a/x-pack/plugins/cases/public/components/case_view/case_view_page.test.tsx b/x-pack/plugins/cases/public/components/case_view/case_view_page.test.tsx index 7a299257b8017..aff92e15c3f29 100644 --- a/x-pack/plugins/cases/public/components/case_view/case_view_page.test.tsx +++ b/x-pack/plugins/cases/public/components/case_view/case_view_page.test.tsx @@ -171,9 +171,9 @@ describe('CaseViewPage', () => { userEvent.click(dropdown.querySelector('button')!); await waitForEuiPopoverOpen(); userEvent.click(result.getByTestId('case-view-status-dropdown-closed')); + const updateObject = updateCaseProperty.mock.calls[0][0]; await waitFor(() => { - const updateObject = updateCaseProperty.mock.calls[0][0]; expect(updateCaseProperty).toHaveBeenCalledTimes(1); expect(updateObject.updateKey).toEqual('status'); expect(updateObject.updateValue).toEqual('closed'); @@ -187,8 +187,11 @@ describe('CaseViewPage', () => { updateKey: 'title', })); const result = appMockRenderer.render(); - expect(result.getByTestId('editable-title-loading')).toBeInTheDocument(); - expect(result.queryByTestId('editable-title-edit-icon')).not.toBeInTheDocument(); + + await waitFor(() => { + expect(result.getByTestId('editable-title-loading')).toBeInTheDocument(); + expect(result.queryByTestId('editable-title-edit-icon')).not.toBeInTheDocument(); + }); }); it('should display description isLoading', async () => { @@ -197,13 +200,17 @@ describe('CaseViewPage', () => { isLoading: true, updateKey: 'description', })); + const result = appMockRenderer.render(); - expect( - within(result.getByTestId('description-action')).getByTestId('user-action-title-loading') - ).toBeInTheDocument(); - expect( - within(result.getByTestId('description-action')).queryByTestId('property-actions') - ).not.toBeInTheDocument(); + + await waitFor(() => { + expect( + within(result.getByTestId('description-action')).getByTestId('user-action-title-loading') + ).toBeInTheDocument(); + expect( + within(result.getByTestId('description-action')).queryByTestId('property-actions') + ).not.toBeInTheDocument(); + }); }); it('should display tags isLoading', async () => { @@ -212,11 +219,18 @@ describe('CaseViewPage', () => { isLoading: true, updateKey: 'tags', })); + const result = appMockRenderer.render(); - expect( - within(result.getByTestId('case-view-tag-list')).getByTestId('tag-list-loading') - ).toBeInTheDocument(); - expect(result.queryByTestId('tag-list-edit')).not.toBeInTheDocument(); + + await waitFor(() => { + expect( + within(result.getByTestId('case-view-tag-list')).getByTestId('tag-list-loading') + ).toBeInTheDocument(); + }); + + await waitFor(() => { + expect(result.queryByTestId('tag-list-edit')).not.toBeInTheDocument(); + }); }); it('should update title', async () => { @@ -228,8 +242,10 @@ describe('CaseViewPage', () => { userEvent.click(result.getByTestId('editable-title-submit-btn')); const updateObject = updateCaseProperty.mock.calls[0][0]; - expect(updateObject.updateKey).toEqual('title'); - expect(updateObject.updateValue).toEqual(newTitle); + await waitFor(() => { + expect(updateObject.updateKey).toEqual('title'); + expect(updateObject.updateValue).toEqual(newTitle); + }); }); it('should push updates on button click', async () => { @@ -244,6 +260,7 @@ describe('CaseViewPage', () => { const result = appMockRenderer.render(); expect(result.getByTestId('has-data-to-push-button')).toBeInTheDocument(); + userEvent.click(result.getByTestId('push-to-external-service')); await waitFor(() => { @@ -260,7 +277,9 @@ describe('CaseViewPage', () => { }} /> ); - expect(result.getByTestId('push-to-external-service')).toBeDisabled(); + await waitFor(() => { + expect(result.getByTestId('push-to-external-service')).toBeDisabled(); + }); }); it('should update connector', async () => { @@ -328,8 +347,10 @@ describe('CaseViewPage', () => { const result = appMockRenderer.render( ); - expect(result.getByTestId('case-view-loading-content')).toBeInTheDocument(); - expect(result.queryByTestId('user-actions')).not.toBeInTheDocument(); + await waitFor(() => { + expect(result.getByTestId('case-view-loading-content')).toBeInTheDocument(); + expect(result.queryByTestId('user-actions')).not.toBeInTheDocument(); + }); }); it('should call show alert details with expected arguments', async () => { @@ -348,19 +369,21 @@ describe('CaseViewPage', () => { it('should show the rule name', async () => { const result = appMockRenderer.render(); - expect( - result - .getByTestId('user-action-alert-comment-create-action-alert-action-id') - .querySelector('.euiCommentEvent__headerEvent') - ).toHaveTextContent('added an alert from Awesome rule'); + await waitFor(() => { + expect( + result + .getByTestId('user-action-alert-comment-create-action-alert-action-id') + .querySelector('.euiCommentEvent__headerEvent') + ).toHaveTextContent('added an alert from Awesome rule'); + }); }); it('should update settings', async () => { const result = appMockRenderer.render(); userEvent.click(result.getByTestId('sync-alerts-switch')); + const updateObject = updateCaseProperty.mock.calls[0][0]; await waitFor(() => { - const updateObject = updateCaseProperty.mock.calls[0][0]; expect(updateObject.updateKey).toEqual('settings'); expect(updateObject.updateValue).toEqual({ syncAlerts: false }); }); @@ -379,6 +402,7 @@ describe('CaseViewPage', () => { const result = appMockRenderer.render( ); + await waitFor(() => { expect(result.getByTestId('has-data-to-push-button')).toHaveTextContent('My Connector 2'); }); diff --git a/x-pack/plugins/cases/public/components/case_view/components/case_view_activity.tsx b/x-pack/plugins/cases/public/components/case_view/components/case_view_activity.tsx index 1fa5e94e6df98..dc1db2651f5bf 100644 --- a/x-pack/plugins/cases/public/components/case_view/components/case_view_activity.tsx +++ b/x-pack/plugins/cases/public/components/case_view/components/case_view_activity.tsx @@ -189,7 +189,7 @@ export const CaseViewActivity = ({ )} - + {caseAssignmentAuthorized ? ( <> { + let appMock: AppMockRenderer; + const props = { + title: 'My title', + confirmButtonText: 'My confirm button text', + cancelButtonText: 'My cancel button text', + onCancel: jest.fn(), + onConfirm: jest.fn(), + }; + + beforeEach(() => { + appMock = createAppMockRenderer(); + jest.clearAllMocks(); + }); + + it('renders correctly', async () => { + const result = appMock.render(); + + expect(result.getByTestId('cancel-creation-confirmation-modal')).toBeInTheDocument(); + expect(result.getByText(props.title)).toBeInTheDocument(); + expect(result.getByText(props.confirmButtonText)).toBeInTheDocument(); + expect(result.getByText(props.cancelButtonText)).toBeInTheDocument(); + }); + + it('calls onConfirm', async () => { + const result = appMock.render(); + + expect(result.getByText(props.confirmButtonText)).toBeInTheDocument(); + userEvent.click(result.getByText(props.confirmButtonText)); + + expect(props.onConfirm).toHaveBeenCalled(); + }); + + it('calls onCancel', async () => { + const result = appMock.render(); + + expect(result.getByText(props.cancelButtonText)).toBeInTheDocument(); + userEvent.click(result.getByText(props.cancelButtonText)); + + expect(props.onCancel).toHaveBeenCalled(); + }); +}); diff --git a/x-pack/plugins/cases/public/components/create/cancel_creation_confirmation_modal.tsx b/x-pack/plugins/cases/public/components/create/cancel_creation_confirmation_modal.tsx new file mode 100644 index 0000000000000..0f73d90a60986 --- /dev/null +++ b/x-pack/plugins/cases/public/components/create/cancel_creation_confirmation_modal.tsx @@ -0,0 +1,41 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import type { EuiConfirmModalProps } from '@elastic/eui'; +import { EuiConfirmModal } from '@elastic/eui'; +import * as i18n from './translations'; + +type Props = Pick< + EuiConfirmModalProps, + 'title' | 'confirmButtonText' | 'cancelButtonText' | 'onConfirm' | 'onCancel' +>; + +const CancelCreationConfirmationModalComponent: React.FC = ({ + title, + confirmButtonText = i18n.CONFIRM_MODAL_BUTTON, + cancelButtonText = i18n.CANCEL_MODAL_BUTTON, + onConfirm, + onCancel, +}) => { + return ( + + ); +}; + +CancelCreationConfirmationModalComponent.displayName = 'CancelCreationConfirmationModal'; + +export const CancelCreationConfirmationModal = React.memo(CancelCreationConfirmationModalComponent); diff --git a/x-pack/plugins/cases/public/components/create/form.tsx b/x-pack/plugins/cases/public/components/create/form.tsx index 4ec587667e18d..68ec55bbc956b 100644 --- a/x-pack/plugins/cases/public/components/create/form.tsx +++ b/x-pack/plugins/cases/public/components/create/form.tsx @@ -38,6 +38,8 @@ import { useAvailableCasesOwners } from '../app/use_available_owners'; import type { CaseAttachmentsWithoutOwner } from '../../types'; import { Severity } from './severity'; import { Assignees } from './assignees'; +import { useCancelCreationAction } from './use_cancel_creation_action'; +import { CancelCreationConfirmationModal } from './cancel_creation_confirmation_modal'; interface ContainerProps { big?: boolean; @@ -184,45 +186,59 @@ export const CreateCaseForm: React.FC = React.memo( timelineIntegration, attachments, initialValue, - }) => ( - - - - - - - - {i18n.CANCEL} - - - - - - - - - - - ) + }) => { + const { showConfirmationModal, onOpenModal, onConfirmModal, onCancelModal } = + useCancelCreationAction({ + onConfirmationCallback: onCancel, + }); + + return ( + + + + + + + + {i18n.CANCEL} + + {showConfirmationModal && ( + + )} + + + + + + + + + + ); + } ); CreateCaseForm.displayName = 'CreateCaseForm'; diff --git a/x-pack/plugins/cases/public/components/create/index.test.tsx b/x-pack/plugins/cases/public/components/create/index.test.tsx index bd2ef3ca1068f..24798c114fede 100644 --- a/x-pack/plugins/cases/public/components/create/index.test.tsx +++ b/x-pack/plugins/cases/public/components/create/index.test.tsx @@ -8,7 +8,8 @@ import React from 'react'; import type { ReactWrapper } from 'enzyme'; import { mount } from 'enzyme'; -import { act } from '@testing-library/react'; +import { act, waitFor } from '@testing-library/react'; + import type { EuiComboBoxOptionOption } from '@elastic/eui'; import { EuiComboBox } from '@elastic/eui'; @@ -105,16 +106,66 @@ describe('CreateCase case', () => { }); }); - it('should call cancel on cancel click', async () => { + it('should open modal on cancel click', async () => { const wrapper = mount( ); - await act(async () => { - wrapper.find(`[data-test-subj="create-case-cancel"]`).first().simulate('click'); + + wrapper.find(`[data-test-subj="create-case-cancel"]`).first().simulate('click'); + + await waitFor(() => { + expect( + wrapper.find(`[data-test-subj="cancel-creation-confirmation-modal"]`).exists() + ).toBeTruthy(); + }); + }); + + it('should confirm cancelation on modal confirm click', async () => { + const wrapper = mount( + + + + ); + + wrapper.find(`[data-test-subj="create-case-cancel"]`).first().simulate('click'); + + await waitFor(() => { + expect( + wrapper.find(`[data-test-subj="cancel-creation-confirmation-modal"]`).exists() + ).toBeTruthy(); + }); + + wrapper.find(`button[data-test-subj="confirmModalConfirmButton"]`).simulate('click'); + + await waitFor(() => { + expect(defaultProps.onCancel).toHaveBeenCalled(); + }); + }); + + it('should close modal on modal cancel click', async () => { + const wrapper = mount( + + + + ); + + wrapper.find(`[data-test-subj="create-case-cancel"]`).first().simulate('click'); + + await waitFor(() => { + expect( + wrapper.find(`[data-test-subj="cancel-creation-confirmation-modal"]`).exists() + ).toBeTruthy(); + }); + + wrapper.find(`button[data-test-subj="confirmModalCancelButton"]`).simulate('click'); + + await waitFor(() => { + expect( + wrapper.find(`[data-test-subj="cancel-creation-confirmation-modal"]`).exists() + ).toBeFalsy(); }); - expect(defaultProps.onCancel).toHaveBeenCalled(); }); it('should redirect to new case when posting the case', async () => { @@ -128,6 +179,7 @@ describe('CreateCase case', () => { fillForm(wrapper); wrapper.find(`button[data-test-subj="create-case-submit"]`).first().simulate('click'); }); + expect(defaultProps.onSuccess).toHaveBeenCalled(); }); }); diff --git a/x-pack/plugins/cases/public/components/create/index.tsx b/x-pack/plugins/cases/public/components/create/index.tsx index 386b64f04bd1c..a765bb0f7b801 100644 --- a/x-pack/plugins/cases/public/components/create/index.tsx +++ b/x-pack/plugins/cases/public/components/create/index.tsx @@ -9,6 +9,7 @@ import React from 'react'; import { Field } from '@kbn/es-ui-shared-plugin/static/forms/components'; import { getUseField } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; +import { EuiPageSection } from '@elastic/eui'; import * as i18n from './translations'; import type { CreateCaseFormProps } from './form'; import { CreateCaseForm } from './form'; @@ -23,7 +24,7 @@ export const CreateCase = React.memo( useCasesBreadcrumbs(CasesDeepLinkId.casesCreate); return ( - <> + ( timelineIntegration={timelineIntegration} withSteps={withSteps} /> - + ); } ); diff --git a/x-pack/plugins/cases/public/components/create/translations.ts b/x-pack/plugins/cases/public/components/create/translations.ts index 780a1bbd1d02f..4bb7471e1c648 100644 --- a/x-pack/plugins/cases/public/components/create/translations.ts +++ b/x-pack/plugins/cases/public/components/create/translations.ts @@ -29,3 +29,15 @@ export const SYNC_ALERTS_LABEL = i18n.translate('xpack.cases.create.syncAlertsLa export const ASSIGN_YOURSELF = i18n.translate('xpack.cases.create.assignYourself', { defaultMessage: 'Assign yourself', }); + +export const MODAL_TITLE = i18n.translate('xpack.cases.create.modalTitle', { + defaultMessage: 'Discard case?', +}); + +export const CANCEL_MODAL_BUTTON = i18n.translate('xpack.cases.create.cancelModalButton', { + defaultMessage: 'Cancel', +}); + +export const CONFIRM_MODAL_BUTTON = i18n.translate('xpack.cases.create.confirmModalButton', { + defaultMessage: 'Exit without saving', +}); diff --git a/x-pack/plugins/cases/public/components/create/use_cancel_creation_action.test.tsx b/x-pack/plugins/cases/public/components/create/use_cancel_creation_action.test.tsx new file mode 100644 index 0000000000000..4174d33c44d2f --- /dev/null +++ b/x-pack/plugins/cases/public/components/create/use_cancel_creation_action.test.tsx @@ -0,0 +1,78 @@ +/* + * Copyright 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, act } from '@testing-library/react-hooks'; +import type { AppMockRenderer } from '../../common/mock'; +import { createAppMockRenderer } from '../../common/mock'; +import { useCancelCreationAction } from './use_cancel_creation_action'; + +describe('UseConfirmationModal', () => { + let appMockRender: AppMockRenderer; + const onConfirmationCallback = jest.fn(); + + beforeEach(() => { + appMockRender = createAppMockRenderer(); + jest.clearAllMocks(); + }); + + it('init', async () => { + const { result } = renderHook(() => useCancelCreationAction({ onConfirmationCallback }), { + wrapper: appMockRender.AppWrapper, + }); + + expect(result.current.showConfirmationModal).toBe(false); + }); + + it('opens the modal', async () => { + const { result } = renderHook(() => useCancelCreationAction({ onConfirmationCallback }), { + wrapper: appMockRender.AppWrapper, + }); + + act(() => { + result.current.onOpenModal(); + }); + + expect(result.current.showConfirmationModal).toBe(true); + }); + + it('closes the modal', async () => { + const { result } = renderHook(() => useCancelCreationAction({ onConfirmationCallback }), { + wrapper: appMockRender.AppWrapper, + }); + + act(() => { + result.current.onOpenModal(); + }); + + expect(result.current.showConfirmationModal).toBe(true); + + act(() => { + result.current.onCancelModal(); + }); + + expect(result.current.showConfirmationModal).toBe(false); + }); + + it('calls onConfirmationCallback on confirm', async () => { + const { result } = renderHook(() => useCancelCreationAction({ onConfirmationCallback }), { + wrapper: appMockRender.AppWrapper, + }); + + act(() => { + result.current.onOpenModal(); + }); + + expect(result.current.showConfirmationModal).toBe(true); + + act(() => { + result.current.onConfirmModal(); + }); + + expect(result.current.showConfirmationModal).toBe(false); + expect(onConfirmationCallback).toHaveBeenCalled(); + }); +}); diff --git a/x-pack/plugins/cases/public/components/create/use_cancel_creation_action.tsx b/x-pack/plugins/cases/public/components/create/use_cancel_creation_action.tsx new file mode 100644 index 0000000000000..461125b739ee7 --- /dev/null +++ b/x-pack/plugins/cases/public/components/create/use_cancel_creation_action.tsx @@ -0,0 +1,31 @@ +/* + * Copyright 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 { useCallback, useState } from 'react'; + +interface Props { + onConfirmationCallback: () => void; +} + +export const useCancelCreationAction = ({ onConfirmationCallback }: Props) => { + const [showConfirmationModal, setShowConfirmationModal] = useState(false); + + const onOpenModal = useCallback(() => { + setShowConfirmationModal(true); + }, []); + + const onConfirmModal = useCallback(() => { + setShowConfirmationModal(false); + onConfirmationCallback(); + }, [onConfirmationCallback]); + + const onCancelModal = useCallback(() => { + setShowConfirmationModal(false); + }, []); + + return { showConfirmationModal, onOpenModal, onConfirmModal, onCancelModal }; +}; diff --git a/x-pack/plugins/cases/public/components/use_create_case_modal/create_case_modal.test.tsx b/x-pack/plugins/cases/public/components/use_create_case_modal/create_case_modal.test.tsx index 9ee4a78b7d817..e1ffe92e0c4c1 100644 --- a/x-pack/plugins/cases/public/components/use_create_case_modal/create_case_modal.test.tsx +++ b/x-pack/plugins/cases/public/components/use_create_case_modal/create_case_modal.test.tsx @@ -61,7 +61,7 @@ describe('CreateCaseModal', () => { ); - wrapper.find('.euiModal__closeIcon').first().simulate('click'); + wrapper.find('button.euiModal__closeIcon').first().simulate('click'); expect(onCloseCaseModal).toBeCalled(); }); diff --git a/x-pack/plugins/cases/public/components/user_actions/markdown_form.test.tsx b/x-pack/plugins/cases/public/components/user_actions/markdown_form.test.tsx index f9fb8594ea51e..c6b6c0e59f004 100644 --- a/x-pack/plugins/cases/public/components/user_actions/markdown_form.test.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/markdown_form.test.tsx @@ -16,6 +16,7 @@ const onChangeEditable = jest.fn(); const onSaveContent = jest.fn(); const newValue = 'Hello from Tehas'; +const emptyValue = ''; const hyperlink = `[hyperlink](http://elastic.co)`; const defaultProps = { content: `A link to a timeline ${hyperlink}`, @@ -61,6 +62,7 @@ describe('UserActionMarkdown ', () => { expect(onChangeEditable).toHaveBeenCalledWith(defaultProps.id); }); }); + it('Does not call onSaveContent if no change from current text', async () => { const wrapper = mount( @@ -75,6 +77,28 @@ describe('UserActionMarkdown ', () => { }); expect(onSaveContent).not.toHaveBeenCalled(); }); + + it('Save button disabled if current text is empty', async () => { + const wrapper = mount( + + + + ); + + wrapper + .find(`.euiMarkdownEditorTextArea`) + .first() + .simulate('change', { + target: { value: emptyValue }, + }); + + await waitFor(() => { + expect( + wrapper.find(`button[data-test-subj="user-action-save-markdown"]`).first().prop('disabled') + ).toBeTruthy(); + }); + }); + it('Cancel button click calls only onChangeEditable', async () => { const wrapper = mount( diff --git a/x-pack/plugins/cases/public/components/user_actions/markdown_form.tsx b/x-pack/plugins/cases/public/components/user_actions/markdown_form.tsx index b2b7443e001e8..42abc55f336c9 100644 --- a/x-pack/plugins/cases/public/components/user_actions/markdown_form.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/markdown_form.tsx @@ -5,15 +5,14 @@ * 2.0. */ -import { EuiFlexGroup, EuiFlexItem, EuiButtonEmpty, EuiButton } from '@elastic/eui'; -import React, { forwardRef, useCallback, useImperativeHandle, useMemo, useRef } from 'react'; +import React, { forwardRef, useCallback, useImperativeHandle, useRef } from 'react'; import styled from 'styled-components'; import { Form, useForm, UseField } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; -import * as i18n from '../case_view/translations'; import type { Content } from './schema'; import { schema } from './schema'; import { MarkdownRenderer, MarkdownEditorForm } from '../markdown_editor'; +import { UserActionMarkdownFooter } from './markdown_form_footer'; export const ContentWrapper = styled.div` padding: ${({ theme }) => `${theme.eui.euiSizeM} ${theme.eui.euiSizeL}`}; @@ -66,36 +65,6 @@ const UserActionMarkdownComponent = forwardRef< [setFieldValue] ); - const EditorButtons = useMemo( - () => ( - - - - {i18n.CANCEL} - - - - - {i18n.SAVE} - - - - ), - [handleCancelAction, handleSaveAction] - ); - useImperativeHandle(ref, () => ({ setComment, editor: editorRef.current, @@ -111,7 +80,12 @@ const UserActionMarkdownComponent = forwardRef< 'aria-label': 'Cases markdown editor', value: content, id, - bottomRightContent: EditorButtons, + bottomRightContent: ( + + ), }} /> diff --git a/x-pack/plugins/cases/public/components/user_actions/markdown_form_footer.tsx b/x-pack/plugins/cases/public/components/user_actions/markdown_form_footer.tsx new file mode 100644 index 0000000000000..ad047c68313f1 --- /dev/null +++ b/x-pack/plugins/cases/public/components/user_actions/markdown_form_footer.tsx @@ -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 { EuiFlexGroup, EuiFlexItem, EuiButtonEmpty, EuiButton } from '@elastic/eui'; +import React from 'react'; + +import { useFormData } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; + +import * as i18n from '../case_view/translations'; + +interface UserActionMarkdownFooterProps { + handleSaveAction: () => Promise; + handleCancelAction: () => void; +} + +const UserActionMarkdownFooterComponent: React.FC = ({ + handleSaveAction, + handleCancelAction, +}) => { + const [{ content }] = useFormData<{ content: string }>({ watch: ['content'] }); + + return ( + + + + {i18n.CANCEL} + + + + + {i18n.SAVE} + + + + ); +}; + +UserActionMarkdownFooterComponent.displayName = 'UserActionMarkdownFooterComponent'; + +export const UserActionMarkdownFooter = React.memo(UserActionMarkdownFooterComponent); diff --git a/x-pack/plugins/cases/public/components/user_actions/tags.tsx b/x-pack/plugins/cases/public/components/user_actions/tags.tsx index bbcad0e8486f5..ad944f1cf49b1 100644 --- a/x-pack/plugins/cases/public/components/user_actions/tags.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/tags.tsx @@ -25,7 +25,7 @@ const getLabelTitle = (userAction: UserActionResponse) => { {userAction.action === Actions.delete && i18n.REMOVED_FIELD} {i18n.TAGS.toLowerCase()} - + ); diff --git a/x-pack/plugins/cases/public/containers/use_get_feature_ids.test.tsx b/x-pack/plugins/cases/public/containers/use_get_feature_ids.test.tsx index b173ea4ad19e0..3d4382bc709ab 100644 --- a/x-pack/plugins/cases/public/containers/use_get_feature_ids.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_get_feature_ids.test.tsx @@ -10,7 +10,6 @@ import React from 'react'; import { TestProviders } from '../common/mock'; import { useGetFeatureIds } from './use_get_feature_ids'; import * as api from './api'; -import { waitFor } from '@testing-library/dom'; jest.mock('./api'); jest.mock('../common/lib/kibana'); @@ -27,29 +26,31 @@ describe('useGetFeaturesIds', () => { wrapper: ({ children }) => {children}, }); - act(() => { + await act(async () => { expect(result.current.alertFeatureIds).toEqual([]); expect(result.current.isLoading).toEqual(true); expect(result.current.isError).toEqual(false); }); }); - // + it('fetches data and returns it correctly', async () => { const spy = jest.spyOn(api, 'getFeatureIds'); const { result } = renderHook(() => useGetFeatureIds(['context1']), { wrapper: ({ children }) => {children}, }); - await waitFor(() => { + await act(async () => { expect(spy).toHaveBeenCalledWith( { registrationContext: ['context1'] }, expect.any(AbortSignal) ); }); - expect(result.current.alertFeatureIds).toEqual(['siem', 'observability']); - expect(result.current.isLoading).toEqual(false); - expect(result.current.isError).toEqual(false); + await act(async () => { + expect(result.current.alertFeatureIds).toEqual(['siem', 'observability']); + expect(result.current.isLoading).toEqual(false); + expect(result.current.isError).toEqual(false); + }); }); it('sets isError to true when an error occurs', async () => { diff --git a/x-pack/plugins/cases/server/authorization/audit_logger.test.ts b/x-pack/plugins/cases/server/authorization/audit_logger.test.ts index b2bbf1f4afac3..7e973f2685990 100644 --- a/x-pack/plugins/cases/server/authorization/audit_logger.test.ts +++ b/x-pack/plugins/cases/server/authorization/audit_logger.test.ts @@ -38,23 +38,6 @@ describe('audit_logger', () => { logger = new AuthorizationAuditLogger(mockLogger); }); - it('does not throw an error when the underlying audit logger is undefined', () => { - const authLogger = new AuthorizationAuditLogger(); - jest.spyOn(authLogger, 'log'); - - expect(() => { - authLogger.log({ - operation: Operations.createCase, - entity: { - owner: 'a', - id: '1', - }, - }); - }).not.toThrow(); - - expect(authLogger.log).toHaveBeenCalledTimes(1); - }); - it('logs a message with a saved object ID in the message field', () => { logger.log({ operation: Operations.createCase, diff --git a/x-pack/plugins/cases/server/authorization/audit_logger.ts b/x-pack/plugins/cases/server/authorization/audit_logger.ts index 8a415e1b69559..88293689446f8 100644 --- a/x-pack/plugins/cases/server/authorization/audit_logger.ts +++ b/x-pack/plugins/cases/server/authorization/audit_logger.ts @@ -21,9 +21,9 @@ interface CreateAuditMsgParams { * Audit logger for authorization operations */ export class AuthorizationAuditLogger { - private readonly auditLogger?: AuditLogger; + private readonly auditLogger: AuditLogger; - constructor(logger?: AuditLogger) { + constructor(logger: AuditLogger) { this.auditLogger = logger; } @@ -97,6 +97,6 @@ export class AuthorizationAuditLogger { * Logs an audit event based on the status of an operation. */ public log(auditMsgParams: CreateAuditMsgParams) { - this.auditLogger?.log(AuthorizationAuditLogger.createAuditMsg(auditMsgParams)); + this.auditLogger.log(AuthorizationAuditLogger.createAuditMsg(auditMsgParams)); } } diff --git a/x-pack/plugins/cases/server/authorization/authorization.test.ts b/x-pack/plugins/cases/server/authorization/authorization.test.ts index 0483489d6c8a2..e7bbcb0abbb9b 100644 --- a/x-pack/plugins/cases/server/authorization/authorization.test.ts +++ b/x-pack/plugins/cases/server/authorization/authorization.test.ts @@ -61,7 +61,7 @@ describe('authorization', () => { securityAuth: securityStart.authz, spaces: spacesStart, features: featuresStart, - auditLogger: new AuthorizationAuditLogger(), + auditLogger: new AuthorizationAuditLogger(mockLogger), logger: loggingSystemMock.createLogger(), }); @@ -81,7 +81,7 @@ describe('authorization', () => { securityAuth: securityStart.authz, spaces: spacesStart, features: featuresStart, - auditLogger: new AuthorizationAuditLogger(), + auditLogger: new AuthorizationAuditLogger(mockLogger), logger: loggingSystemMock.createLogger(), }); @@ -140,7 +140,7 @@ describe('authorization', () => { request, spaces: spacesStart, features: featuresStart, - auditLogger: new AuthorizationAuditLogger(), + auditLogger: new AuthorizationAuditLogger(mockLogger), logger: loggingSystemMock.createLogger(), }); @@ -266,7 +266,7 @@ describe('authorization', () => { securityAuth: securityStart.authz, spaces: spacesStart, features: featuresStart, - auditLogger: new AuthorizationAuditLogger(), + auditLogger: new AuthorizationAuditLogger(mockLogger), logger: loggingSystemMock.createLogger(), }); @@ -295,7 +295,7 @@ describe('authorization', () => { securityAuth: securityStart.authz, spaces: spacesStart, features: featuresStart, - auditLogger: new AuthorizationAuditLogger(), + auditLogger: new AuthorizationAuditLogger(mockLogger), logger: loggingSystemMock.createLogger(), }); @@ -322,7 +322,7 @@ describe('authorization', () => { securityAuth: securityStart.authz, spaces: spacesStart, features: featuresStart, - auditLogger: new AuthorizationAuditLogger(), + auditLogger: new AuthorizationAuditLogger(mockLogger), logger: loggingSystemMock.createLogger(), }); diff --git a/x-pack/plugins/cloud_integrations/cloud_full_story/.i18nrc.json b/x-pack/plugins/cloud_integrations/cloud_full_story/.i18nrc.json index aa690dec41fc1..e86db74eed77a 100755 --- a/x-pack/plugins/cloud_integrations/cloud_full_story/.i18nrc.json +++ b/x-pack/plugins/cloud_integrations/cloud_full_story/.i18nrc.json @@ -3,5 +3,5 @@ "paths": { "cloudFullStory": "." }, - "translations": ["translations/ja-JP.json"] + "translations": [] } diff --git a/x-pack/plugins/cloud_security_posture/common/constants.ts b/x-pack/plugins/cloud_security_posture/common/constants.ts index a78266a51f279..539048af7bee1 100644 --- a/x-pack/plugins/cloud_security_posture/common/constants.ts +++ b/x-pack/plugins/cloud_security_posture/common/constants.ts @@ -46,3 +46,19 @@ export const CSP_RULE_TEMPLATE_SAVED_OBJECT_TYPE = 'csp-rule-template'; export const CLOUDBEAT_VANILLA = 'cloudbeat/cis_k8s'; // Integration input export const CLOUDBEAT_EKS = 'cloudbeat/cis_eks'; // Integration input +export const CLOUDBEAT_AWS = 'cloudbeat/cis_aws'; // Integration input +export const CLOUDBEAT_GCP = 'cloudbeat/cis_gcp'; // Integration input +export const CLOUDBEAT_AZURE = 'cloudbeat/cis_azure'; // Integration input +export const KSPM_POLICY_TEMPLATE = 'kspm'; +export const CSPM_POLICY_TEMPLATE = 'cspm'; +export const SUPPORTED_POLICY_TEMPLATES = [KSPM_POLICY_TEMPLATE, CSPM_POLICY_TEMPLATE]; +export const SUPPORTED_CLOUDBEAT_INPUTS = [ + CLOUDBEAT_VANILLA, + CLOUDBEAT_EKS, + CLOUDBEAT_AWS, + CLOUDBEAT_GCP, + CLOUDBEAT_AZURE, +]; + +export type CLOUDBEAT_INTEGRATION = typeof SUPPORTED_CLOUDBEAT_INPUTS[number]; +export type POLICY_TEMPLATE = typeof SUPPORTED_POLICY_TEMPLATES[number]; diff --git a/x-pack/plugins/cloud_security_posture/public/common/constants.ts b/x-pack/plugins/cloud_security_posture/public/common/constants.ts index 9c02bfe1ba4f6..0590b60d73f68 100644 --- a/x-pack/plugins/cloud_security_posture/public/common/constants.ts +++ b/x-pack/plugins/cloud_security_posture/public/common/constants.ts @@ -7,7 +7,15 @@ import { i18n } from '@kbn/i18n'; import { euiThemeVars } from '@kbn/ui-theme'; -import { CLOUDBEAT_EKS, CLOUDBEAT_VANILLA } from '../../common/constants'; +import { + CLOUDBEAT_EKS, + CLOUDBEAT_VANILLA, + CLOUDBEAT_AWS, + CLOUDBEAT_GCP, + CLOUDBEAT_AZURE, + CLOUDBEAT_INTEGRATION, + POLICY_TEMPLATE, +} from '../../common/constants'; export const statusColors = { passed: euiThemeVars.euiColorVis0, @@ -22,9 +30,57 @@ export const LOCAL_STORAGE_PAGE_SIZE_FINDINGS_KEY = 'cloudPosture:findings:pageS export const LOCAL_STORAGE_PAGE_SIZE_BENCHMARK_KEY = 'cloudPosture:benchmark:pageSize'; export const LOCAL_STORAGE_PAGE_SIZE_RULES_KEY = 'cloudPosture:rules:pageSize'; -export type CloudPostureIntegrations = typeof cloudPostureIntegrations; +export type CloudPostureIntegrations = Record; +export interface CloudPostureIntegrationProps { + policyTemplate: POLICY_TEMPLATE; + name: string; + shortName: string; + options: Array<{ + type: CLOUDBEAT_INTEGRATION; + name: string; + benchmark: string; + }>; +} -export const cloudPostureIntegrations = { +export const cloudPostureIntegrations: CloudPostureIntegrations = { + cspm: { + policyTemplate: 'cspm', + name: i18n.translate('xpack.csp.cspmIntegration.integration.nameTitle', { + defaultMessage: 'Cloud Security Posture Management', + }), + shortName: i18n.translate('xpack.csp.cspmIntegration.integration.shortNameTitle', { + defaultMessage: 'CSPM', + }), + options: [ + { + type: CLOUDBEAT_AWS, + name: i18n.translate('xpack.csp.cspmIntegration.awsOption.nameTitle', { + defaultMessage: 'Amazon Web Services', + }), + benchmark: i18n.translate('xpack.csp.cspmIntegration.awsOption.benchmarkTitle', { + defaultMessage: 'CIS AWS', + }), + }, + { + type: CLOUDBEAT_GCP, + name: i18n.translate('xpack.csp.cspmIntegration.gcpOption.nameTitle', { + defaultMessage: 'GCP', + }), + benchmark: i18n.translate('xpack.csp.cspmIntegration.gcpOption.benchmarkTitle', { + defaultMessage: 'CIS GCP', + }), + }, + { + type: CLOUDBEAT_AZURE, + name: i18n.translate('xpack.csp.cspmIntegration.azureOption.nameTitle', { + defaultMessage: 'Azure', + }), + benchmark: i18n.translate('xpack.csp.cspmIntegration.azureOption.benchmarkTitle', { + defaultMessage: 'CIS Azure', + }), + }, + ], + }, kspm: { policyTemplate: 'kspm', name: i18n.translate('xpack.csp.kspmIntegration.integration.nameTitle', { @@ -54,4 +110,4 @@ export const cloudPostureIntegrations = { }, ], }, -} as const; +}; diff --git a/x-pack/plugins/cloud_security_posture/public/common/hooks/use_url_query.ts b/x-pack/plugins/cloud_security_posture/public/common/hooks/use_url_query.ts index 0573d77e6f9c8..8bc6ff96b4c4f 100644 --- a/x-pack/plugins/cloud_security_posture/public/common/hooks/use_url_query.ts +++ b/x-pack/plugins/cloud_security_posture/public/common/hooks/use_url_query.ts @@ -6,7 +6,6 @@ */ import { useEffect, useCallback, useMemo } from 'react'; import { useHistory, useLocation } from 'react-router-dom'; -import type { RisonObject } from 'rison-node'; import { decodeQuery, encodeQuery } from '../navigation/query_utils'; /** @@ -35,7 +34,7 @@ export const useUrlQuery = (getDefaultQuery: () => T) => { useEffect(() => { if (search) return; - replace({ search: encodeQuery(getDefaultQuery() as RisonObject) }); + replace({ search: encodeQuery(getDefaultQuery()) }); }, [getDefaultQuery, search, replace]); return { diff --git a/x-pack/plugins/cloud_security_posture/public/common/navigation/query_utils.ts b/x-pack/plugins/cloud_security_posture/public/common/navigation/query_utils.ts index 601ad3097b7a8..3a051456733a6 100644 --- a/x-pack/plugins/cloud_security_posture/public/common/navigation/query_utils.ts +++ b/x-pack/plugins/cloud_security_posture/public/common/navigation/query_utils.ts @@ -4,10 +4,10 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { encode, decode, type RisonObject } from 'rison-node'; +import { encode, decode } from '@kbn/rison'; import type { LocationDescriptorObject } from 'history'; -const encodeRison = (v: RisonObject): string | undefined => { +const encodeRison = (v: any): string | undefined => { try { return encode(v); } catch (e) { @@ -27,7 +27,7 @@ const decodeRison = (query: string): T | undefined => { const QUERY_PARAM_KEY = 'cspq'; -export const encodeQuery = (query: RisonObject): LocationDescriptorObject['search'] => { +export const encodeQuery = (query: any): LocationDescriptorObject['search'] => { const risonQuery = encodeRison(query); if (!risonQuery) return; return `${QUERY_PARAM_KEY}=${risonQuery}`; diff --git a/x-pack/plugins/cloud_security_posture/public/common/utils/get_enabled_csp_integration_details.ts b/x-pack/plugins/cloud_security_posture/public/common/utils/get_enabled_csp_integration_details.ts index 6cc02ac9aedc1..2fed31c2f8cc4 100644 --- a/x-pack/plugins/cloud_security_posture/public/common/utils/get_enabled_csp_integration_details.ts +++ b/x-pack/plugins/cloud_security_posture/public/common/utils/get_enabled_csp_integration_details.ts @@ -6,6 +6,7 @@ */ import { PackagePolicy } from '@kbn/fleet-plugin/common'; +import { SUPPORTED_CLOUDBEAT_INPUTS } from '../../../common/constants'; import { cloudPostureIntegrations, CloudPostureIntegrations } from '../constants'; const isPolicyTemplate = (name: unknown): name is keyof CloudPostureIntegrations => @@ -13,7 +14,14 @@ const isPolicyTemplate = (name: unknown): name is keyof CloudPostureIntegrations export const getEnabledCspIntegrationDetails = (packageInfo?: PackagePolicy) => { const enabledInput = packageInfo?.inputs.find((input) => input.enabled); - if (!enabledInput || !isPolicyTemplate(enabledInput.policy_template)) return null; + + // Check for valid and support input + if ( + !enabledInput || + !isPolicyTemplate(enabledInput.policy_template) || + !SUPPORTED_CLOUDBEAT_INPUTS.includes(enabledInput.type) + ) + return null; const integration = cloudPostureIntegrations[enabledInput.policy_template]; const enabledIntegrationOption = integration.options.find( diff --git a/x-pack/plugins/cloud_security_posture/public/components/csp_evaluation_badge.tsx b/x-pack/plugins/cloud_security_posture/public/components/csp_evaluation_badge.tsx index 0d838daa1e660..24ca4cd4fe4eb 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/csp_evaluation_badge.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/csp_evaluation_badge.tsx @@ -24,7 +24,11 @@ const getColor = (type: Props['type']): EuiBadgeProps['color'] => { }; export const CspEvaluationBadge = ({ type }: Props) => ( - + {type === 'failed' ? ( ) : ( diff --git a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/deployment_type_select.tsx b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/deployment_type_select.tsx index b01b5073a0e1b..bc5c61fa0370b 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/deployment_type_select.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/deployment_type_select.tsx @@ -17,18 +17,19 @@ import { } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import { cloudPostureIntegrations } from '../../common/constants'; -import { CLOUDBEAT_EKS, CLOUDBEAT_VANILLA } from '../../../common/constants'; - -export type InputType = typeof CLOUDBEAT_EKS | typeof CLOUDBEAT_VANILLA; +import { CLOUDBEAT_INTEGRATION, POLICY_TEMPLATE } from '../../../common/constants'; interface Props { - type: InputType; - onChange?: (type: InputType) => void; + policyTemplate: POLICY_TEMPLATE; + type: CLOUDBEAT_INTEGRATION; + onChange?: (type: CLOUDBEAT_INTEGRATION) => void; isDisabled?: boolean; } -const kubeDeployOptions: Array> = - cloudPostureIntegrations.kspm.options.map((o) => ({ value: o.type, label: o.name })); +const kubeDeployOptions = ( + policyTemplate: POLICY_TEMPLATE +): Array> => + cloudPostureIntegrations[policyTemplate].options.map((o) => ({ value: o.type, label: o.name })); const KubernetesDeploymentFieldLabel = () => ( ( ); -export const DeploymentTypeSelect = ({ type, isDisabled, onChange }: Props) => ( +export const DeploymentTypeSelect = ({ policyTemplate, type, isDisabled, onChange }: Props) => ( }> }> o.value === type)} + options={kubeDeployOptions(policyTemplate)} + selectedOptions={kubeDeployOptions(policyTemplate).filter((o) => o.value === type)} isDisabled={isDisabled} onChange={(options) => !isDisabled && onChange?.(options[0].value!)} /> diff --git a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_extension_create.tsx b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_extension_create.tsx index ae5d79984da7e..790cd8978725c 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_extension_create.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_extension_create.tsx @@ -7,16 +7,22 @@ import React, { memo } from 'react'; import { EuiForm } from '@elastic/eui'; import type { PackagePolicyCreateExtensionComponentProps } from '@kbn/fleet-plugin/public'; -import { CLOUDBEAT_EKS } from '../../../common/constants'; -import { DeploymentTypeSelect, InputType } from './deployment_type_select'; +import { CLOUDBEAT_AWS, CLOUDBEAT_EKS, CLOUDBEAT_INTEGRATION } from '../../../common/constants'; +import { DeploymentTypeSelect } from './deployment_type_select'; import { EksFormWrapper } from './eks_form'; -import { getEnabledInputType, getUpdatedDeploymentType, getUpdatedEksVar } from './utils'; +import { + getEnabledInput, + getEnabledInputType, + getUpdatedDeploymentType, + getUpdatedEksVar, +} from './utils'; export const CspCreatePolicyExtension = memo( ({ newPolicy, onChange }) => { const selectedDeploymentType = getEnabledInputType(newPolicy.inputs); - - const updateDeploymentType = (inputType: InputType) => + const selectedInput = getEnabledInput(newPolicy.inputs); + const policyTemplate = selectedInput?.policy_template; + const updateDeploymentType = (inputType: CLOUDBEAT_INTEGRATION) => onChange(getUpdatedDeploymentType(newPolicy, inputType)); const updateEksVar = (key: string, value: string) => @@ -24,9 +30,18 @@ export const CspCreatePolicyExtension = memo - - {selectedDeploymentType === CLOUDBEAT_EKS && ( - + {selectedInput && (policyTemplate === 'kspm' || policyTemplate === 'cspm') && ( + <> + + {(selectedDeploymentType === CLOUDBEAT_EKS || + selectedDeploymentType === CLOUDBEAT_AWS) && ( + + )} + )} ); diff --git a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_extension_edit.tsx b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_extension_edit.tsx index 33ed6dced08ad..e268dac8cd14e 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_extension_edit.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_extension_edit.tsx @@ -7,23 +7,34 @@ import React, { memo } from 'react'; import { EuiForm } from '@elastic/eui'; import type { PackagePolicyEditExtensionComponentProps } from '@kbn/fleet-plugin/public'; -import { CLOUDBEAT_EKS } from '../../../common/constants'; +import { CLOUDBEAT_EKS, CLOUDBEAT_AWS } from '../../../common/constants'; import { DeploymentTypeSelect } from './deployment_type_select'; import { EksFormWrapper } from './eks_form'; -import { getEnabledInputType, getUpdatedEksVar } from './utils'; +import { getEnabledInput, getEnabledInputType, getUpdatedEksVar } from './utils'; export const CspEditPolicyExtension = memo( ({ newPolicy, onChange }) => { const selectedDeploymentType = getEnabledInputType(newPolicy.inputs); + const selectedInput = getEnabledInput(newPolicy.inputs); + const policyTemplate = selectedInput?.policy_template; const updateEksVar = (key: string, value: string) => onChange(getUpdatedEksVar(newPolicy, key, value)); return ( - - {selectedDeploymentType === CLOUDBEAT_EKS && ( - + {(policyTemplate === 'kspm' || policyTemplate === 'cspm') && ( + <> + + {(selectedDeploymentType === CLOUDBEAT_EKS || + selectedDeploymentType === CLOUDBEAT_AWS) && ( + + )} + )} ); diff --git a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/utils.ts b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/utils.ts index 9641606abfcf7..2f2285ad5c4ce 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/utils.ts +++ b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/utils.ts @@ -5,15 +5,42 @@ * 2.0. */ import type { NewPackagePolicy, NewPackagePolicyInput } from '@kbn/fleet-plugin/common'; -import { CLOUDBEAT_EKS, CLOUDBEAT_VANILLA } from '../../../common/constants'; -import type { InputType } from './deployment_type_select'; +import { + CLOUDBEAT_AWS, + CLOUDBEAT_EKS, + CLOUDBEAT_VANILLA, + CLOUDBEAT_INTEGRATION, + SUPPORTED_POLICY_TEMPLATES, + POLICY_TEMPLATE, +} from '../../../common/constants'; export const isEksInput = (input: NewPackagePolicyInput) => input.type === CLOUDBEAT_EKS; +export const inputsWithVars = [CLOUDBEAT_EKS, CLOUDBEAT_AWS]; +const defaultInputType: Record = { + kspm: CLOUDBEAT_VANILLA, + cspm: CLOUDBEAT_AWS, +}; +export const getEnabledInputType = (inputs: NewPackagePolicy['inputs']): CLOUDBEAT_INTEGRATION => { + const enabledInput = getEnabledInput(inputs); + + if (enabledInput) return enabledInput.type as CLOUDBEAT_INTEGRATION; + + const policyTemplate = inputs[0].policy_template as POLICY_TEMPLATE | undefined; + + if (policyTemplate && SUPPORTED_POLICY_TEMPLATES.includes(policyTemplate)) + return defaultInputType[policyTemplate]; + + throw new Error('unsupported policy template'); +}; -export const getEnabledInputType = (inputs: NewPackagePolicy['inputs']): InputType => - (inputs.find((input) => input.enabled)?.type as InputType) || CLOUDBEAT_VANILLA; +export const getEnabledInput = ( + inputs: NewPackagePolicy['inputs'] +): NewPackagePolicyInput | undefined => inputs.find((input) => input.enabled); -export const getUpdatedDeploymentType = (newPolicy: NewPackagePolicy, inputType: InputType) => ({ +export const getUpdatedDeploymentType = ( + newPolicy: NewPackagePolicy, + inputType: CLOUDBEAT_INTEGRATION +) => ({ isValid: true, // TODO: add validations updatedPolicy: { ...newPolicy, @@ -33,7 +60,7 @@ export const getUpdatedEksVar = (newPolicy: NewPackagePolicy, key: string, value updatedPolicy: { ...newPolicy, inputs: newPolicy.inputs.map((item) => - isEksInput(item) ? getUpdatedStreamVars(item, key, value) : item + inputsWithVars.includes(item.type) ? getUpdatedStreamVars(item, key, value) : item ), }, }); diff --git a/x-pack/plugins/cloud_security_posture/public/pages/findings/__mocks__/findings.ts b/x-pack/plugins/cloud_security_posture/public/pages/findings/__mocks__/findings.ts new file mode 100644 index 0000000000000..48956856bf31c --- /dev/null +++ b/x-pack/plugins/cloud_security_posture/public/pages/findings/__mocks__/findings.ts @@ -0,0 +1,117 @@ +/* + * Copyright 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 { CspFinding } from '../../../../common/schemas/csp_finding'; + +export const mockFindingsHit: CspFinding = { + result: { + evaluation: 'passed', + evidence: { + serviceAccounts: [], + serviceAccount: [], + }, + // TODO: wrong type + // expected: null, + }, + orchestrator: { + cluster: { + name: 'kind-multi', + }, + }, + agent: { + name: 'kind-multi-worker', + id: '41b2ba39-fd4e-474d-8c61-d79c9204e793', + // TODO: missing + // ephemeral_id: '20964f94-a4fe-48c1-8bf3-4b7140baf03c', + type: 'cloudbeat', + version: '8.6.0', + }, + cluster_id: '087606d6-c71a-4892-9b27-67ab937770ce', + '@timestamp': '2022-11-24T22:27:19.515Z', + ecs: { + version: '8.0.0', + }, + resource: { + sub_type: 'ServiceAccount', + name: 'certificate-controller', + raw: { + metadata: { + uid: '597cd43e-90a5-4aea-95aa-35f177429794', + resourceVersion: '277', + creationTimestamp: '2022-11-15T16:08:49Z', + name: 'certificate-controller', + namespace: 'kube-system', + }, + apiVersion: 'v1', + kind: 'ServiceAccount', + secrets: [ + { + name: 'certificate-controller-token-ql8wn', + }, + ], + }, + id: '597cd43e-90a5-4aea-95aa-35f177429794', + type: 'k8s_object', + }, + host: { + id: '', // TODO: missing + hostname: 'kind-multi-worker', + os: { + kernel: '5.10.76-linuxkit', + codename: 'bullseye', + name: 'Debian GNU/Linux', + type: 'linux', + family: 'debian', + version: '11 (bullseye)', + platform: 'debian', + }, + containerized: false, + ip: ['172.19.0.3', 'fc00:f853:ccd:e793::3', 'fe80::42:acff:fe13:3'], + name: 'kind-multi-worker', + mac: ['02-42-AC-13-00-03'], + architecture: 'x86_64', + }, + rule: { + references: + '1. [https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/)\n', + impact: + 'All workloads which require access to the Kubernetes API will require an explicit service account to be created.\n', + description: + 'The `default` service account should not be used to ensure that rights granted to applications can be more easily audited and reviewed.\n', + default_value: + 'By default the `default` service account allows for its service account token\nto be mounted\nin pods in its namespace.\n', + section: 'RBAC and Service Accounts', + rationale: + 'Kubernetes provides a `default` service account which is used by cluster workloads where no specific service account is assigned to the pod. Where access to the Kubernetes API from a pod is required, a specific service account should be created for that pod, and rights granted to that service account. The default service account should be configured such that it does not provide a service account token and does not have any explicit rights assignments.\n', + version: '1.0', + benchmark: { + name: 'CIS Kubernetes V1.23', + id: 'cis_k8s', + version: 'v1.0.0', + }, + tags: ['CIS', 'Kubernetes', 'CIS 5.1.5', 'RBAC and Service Accounts'], + remediation: + 'Create explicit service accounts wherever a Kubernetes workload requires\nspecific access\nto the Kubernetes API server.\nModify the configuration of each default service account to include this value\n```\nautomountServiceAccountToken: false\n```\n', + audit: + 'For each namespace in the cluster, review the rights assigned to the default service account and ensure that it has no roles or cluster roles bound to it apart from the defaults. Additionally ensure that the `automountServiceAccountToken: false` setting is in place for each default service account.\n', + name: 'Ensure that default service accounts are not actively used. (Manual)', + id: '2b399496-f79d-5533-8a86-4ea00b95e3bd', + profile_applicability: '* Level 1 - Master Node\n', + rego_rule_id: '', + }, + event: { + agent_id_status: 'auth_metadata_missing', + sequence: 1669328831, + ingested: '2022-11-24T22:28:25Z', + created: '2022-11-24T22:27:19.514650003Z', + kind: 'state', + id: 'ce5c1501-90a3-4543-bf28-cd6c9e4d73e8', + type: ['info'], + category: ['configuration'], + outcome: 'success', + }, +}; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/findings/findings_flyout/findings_flyout.test.tsx b/x-pack/plugins/cloud_security_posture/public/pages/findings/findings_flyout/findings_flyout.test.tsx new file mode 100644 index 0000000000000..40b87da1245ef --- /dev/null +++ b/x-pack/plugins/cloud_security_posture/public/pages/findings/findings_flyout/findings_flyout.test.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 userEvent from '@testing-library/user-event'; +import { FindingsRuleFlyout } from './findings_flyout'; +import { render, screen } from '@testing-library/react'; +import { TestProvider } from '../../../test/test_provider'; +import { mockFindingsHit } from '../__mocks__/findings'; +import { LATEST_FINDINGS_INDEX_DEFAULT_NS } from '../../../../common/constants'; + +const TestComponent = () => ( + + + +); + +describe('', () => { + describe('Overview Tab', () => { + it('details and remediation accordions are open', () => { + const { getAllByRole } = render(); + + getAllByRole('button', { expanded: true, name: 'Details' }); + getAllByRole('button', { expanded: true, name: 'Remediation' }); + }); + + it('displays text details summary info', () => { + const { getAllByText, getByText } = render(); + + getAllByText(mockFindingsHit.rule.name); + getByText(mockFindingsHit.resource.id); + getByText(mockFindingsHit.resource.name); + getAllByText(mockFindingsHit.rule.section); + getByText(LATEST_FINDINGS_INDEX_DEFAULT_NS); + mockFindingsHit.rule.tags.forEach((tag) => { + getAllByText(tag); + }); + }); + }); + + describe('Rule Tab', () => { + it('displays rule text details', () => { + const { getByText, getAllByText } = render(); + + userEvent.click(screen.getByTestId('findings_flyout_tab_rule')); + + getAllByText(mockFindingsHit.rule.name); + getByText(mockFindingsHit.rule.benchmark.name); + getAllByText(mockFindingsHit.rule.section); + mockFindingsHit.rule.tags.forEach((tag) => { + getAllByText(tag); + }); + }); + }); + + describe('Resource Tab', () => { + it('displays resource name and id', () => { + const { getAllByText } = render(); + + userEvent.click(screen.getByTestId('findings_flyout_tab_resource')); + + getAllByText(mockFindingsHit.resource.name); + getAllByText(mockFindingsHit.resource.id); + }); + }); +}); diff --git a/x-pack/plugins/cloud_security_posture/public/pages/findings/findings_flyout/findings_flyout.tsx b/x-pack/plugins/cloud_security_posture/public/pages/findings/findings_flyout/findings_flyout.tsx index 0b00136b165c5..8229084c10dd9 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/findings/findings_flyout/findings_flyout.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/findings/findings_flyout/findings_flyout.tsx @@ -129,7 +129,12 @@ export const FindingsRuleFlyout = ({ onClose, findings }: FindingFlyoutProps) => {tabs.map((v) => ( - setTab(v)}> + setTab(v)} + data-test-subj={`findings_flyout_tab_${v.id}`} + > {v.title} ))} diff --git a/x-pack/plugins/cloud_security_posture/public/pages/findings/findings_flyout/overview_tab.tsx b/x-pack/plugins/cloud_security_posture/public/pages/findings/findings_flyout/overview_tab.tsx index 5dba83b9019b8..a0c5d330d22a3 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/findings/findings_flyout/overview_tab.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/findings/findings_flyout/overview_tab.tsx @@ -46,7 +46,7 @@ const getDetailsList = (data: CspFinding, discoverIndexLink: string | undefined) description: ( <> {data.rule.tags.map((tag) => ( - {tag} + {tag} ))} ), diff --git a/x-pack/plugins/cloud_security_posture/public/pages/findings/findings_flyout/rule_tab.tsx b/x-pack/plugins/cloud_security_posture/public/pages/findings/findings_flyout/rule_tab.tsx index 74904041888a4..e51abb0bd3e9d 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/findings/findings_flyout/rule_tab.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/findings/findings_flyout/rule_tab.tsx @@ -31,7 +31,7 @@ export const getRuleList = (rule: CspFinding['rule']) => [ description: ( <> {rule.tags.map((tag) => ( - {tag} + {tag} ))} ), diff --git a/x-pack/plugins/cloud_security_posture/public/pages/findings/latest_findings/latest_findings_container.test.tsx b/x-pack/plugins/cloud_security_posture/public/pages/findings/latest_findings/latest_findings_container.test.tsx index 2d709433e7fc5..3c6b51f881989 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/findings/latest_findings/latest_findings_container.test.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/findings/latest_findings/latest_findings_container.test.tsx @@ -16,7 +16,6 @@ import { TestProvider } from '../../../test/test_provider'; import { getFindingsQuery } from './use_latest_findings'; import { encodeQuery } from '../../../common/navigation/query_utils'; import { useLocation } from 'react-router-dom'; -import { RisonObject } from 'rison-node'; import { buildEsQuery } from '@kbn/es-query'; import { getPaginationQuery } from '../utils/utils'; import { chartPluginMock } from '@kbn/charts-plugin/public/mocks'; @@ -52,7 +51,7 @@ describe('', () => { }); (useLocation as jest.Mock).mockReturnValue({ - search: encodeQuery(query as unknown as RisonObject), + search: encodeQuery(query), }); render( diff --git a/x-pack/plugins/cloud_security_posture/public/pages/findings/layout/findings_distribution_bar.tsx b/x-pack/plugins/cloud_security_posture/public/pages/findings/layout/findings_distribution_bar.tsx index f293b82341a61..9db41a7786174 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/findings/layout/findings_distribution_bar.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/findings/layout/findings_distribution_bar.tsx @@ -126,6 +126,7 @@ const DistributionBar: React.FC> = ({ distributionOnClick={() => { distributionOnClick(RULE_PASSED); }} + data-test-subj="distribution_bar_passed" /> > = ({ distributionOnClick={() => { distributionOnClick(RULE_FAILED); }} + data-test-subj="distribution_bar_failed" /> ); @@ -142,12 +144,15 @@ const DistributionBarPart = ({ value, color, distributionOnClick, + ...rest }: { value: number; color: string; distributionOnClick: () => void; + ['data-test-subj']: string; }) => (